VideoConsumer.cpp revision 6298fd45
1dba5824bSPhil Greenway//	Copyright (c) 1998-99, Be Incorporated, All Rights Reserved.
2dba5824bSPhil Greenway//	SMS
3dba5824bSPhil Greenway//	VideoConsumer.cpp
4dba5824bSPhil Greenway
59d3f15c6SIngo Weinhold
6e3145a8dSFrançois Revol#include "FileUploadClient.h"
79d3f15c6SIngo Weinhold#include "FtpClient.h"
8e3145a8dSFrançois Revol#include "SftpClient.h"
99d3f15c6SIngo Weinhold#include "VideoConsumer.h"
109d3f15c6SIngo Weinhold
11dba5824bSPhil Greenway#include <fcntl.h>
129d3f15c6SIngo Weinhold#include <stdio.h>
13dba5824bSPhil Greenway#include <unistd.h>
14dba5824bSPhil Greenway#include <string.h>
159d3f15c6SIngo Weinhold
169d3f15c6SIngo Weinhold#include <Application.h>
179d3f15c6SIngo Weinhold#include <Buffer.h>
189d3f15c6SIngo Weinhold#include <BufferGroup.h>
199d3f15c6SIngo Weinhold#include <MediaRoster.h>
20dba5824bSPhil Greenway#include <NodeInfo.h>
21dba5824bSPhil Greenway#include <scheduler.h>
22dba5824bSPhil Greenway#include <StringView.h>
239d3f15c6SIngo Weinhold#include <TimeSource.h>
249d3f15c6SIngo Weinhold#include <View.h>
25dba5824bSPhil Greenway
26dba5824bSPhil Greenway
27dba5824bSPhil Greenway#define M1 ((double)1000000.0)
28dba5824bSPhil Greenway#define JITTER		20000
29dba5824bSPhil Greenway
30dba5824bSPhil Greenway#define	FUNCTION	printf
31dba5824bSPhil Greenway#define ERROR		printf
32dba5824bSPhil Greenway#define PROGRESS	printf
33dba5824bSPhil Greenway#define LOOP		printf
34dba5824bSPhil Greenway
359d3f15c6SIngo Weinholdstatic status_t SetFileType(BFile* file,  int32 translator, uint32 type);
369d3f15c6SIngo Weinhold
379d3f15c6SIngo Weinholdconst media_raw_video_format vid_format = {29.97, 1, 0, 239, B_VIDEO_TOP_LEFT_RIGHT,
389d3f15c6SIngo Weinhold	1, 1, {B_RGB16, 320, 240, 320 * 4, 0, 0}};
399d3f15c6SIngo Weinhold
409d3f15c6SIngo Weinhold
419d3f15c6SIngo WeinholdVideoConsumer::VideoConsumer(const char* name, BView* view, BStringView* statusLine,
429d3f15c6SIngo Weinhold	BMediaAddOn* addon, const uint32 internalId)
439d3f15c6SIngo Weinhold	: BMediaNode(name), BMediaEventLooper(), BBufferConsumer(B_MEDIA_RAW_VIDEO),
449d3f15c6SIngo Weinhold	fStatusLine(statusLine),
459d3f15c6SIngo Weinhold	fInternalID(internalId),
469d3f15c6SIngo Weinhold	fAddOn(addon),
479d3f15c6SIngo Weinhold	fConnectionActive(false),
489d3f15c6SIngo Weinhold	fMyLatency(20000),
499d3f15c6SIngo Weinhold	fWindow(NULL),
509d3f15c6SIngo Weinhold	fView(view),
519d3f15c6SIngo Weinhold	fOurBuffers(false),
529d3f15c6SIngo Weinhold	fBuffers(NULL),
539d3f15c6SIngo Weinhold	fTimeToFtp(false),
549d3f15c6SIngo Weinhold	fFtpComplete(true),
559d3f15c6SIngo Weinhold	fRate(1000000),
569d3f15c6SIngo Weinhold	fImageFormat(0),
579d3f15c6SIngo Weinhold	fTranslator(0),
58e3145a8dSFrançois Revol	fUploadClient(0),
599d3f15c6SIngo Weinhold	fPassiveFtp(true)
60dba5824bSPhil Greenway{
61dba5824bSPhil Greenway	FUNCTION("VideoConsumer::VideoConsumer\n");
62dba5824bSPhil Greenway
63dba5824bSPhil Greenway	AddNodeKind(B_PHYSICAL_OUTPUT);
64dba5824bSPhil Greenway	SetEventLatency(0);
659d3f15c6SIngo Weinhold	fWindow = fView->Window();
66dba5824bSPhil Greenway
679d3f15c6SIngo Weinhold	for (uint32 j = 0; j < 3; j++) {
689d3f15c6SIngo Weinhold		fBitmap[j] = NULL;
699d3f15c6SIngo Weinhold		fBufferMap[j] = 0;
70dba5824bSPhil Greenway	}
719d3f15c6SIngo Weinhold
729d3f15c6SIngo Weinhold	strcpy(fFileNameText, "");
739d3f15c6SIngo Weinhold	strcpy(fServerText, "");
749d3f15c6SIngo Weinhold	strcpy(fLoginText, "");
759d3f15c6SIngo Weinhold	strcpy(fPasswordText, "");
769d3f15c6SIngo Weinhold	strcpy(fDirectoryText, "");
77dba5824bSPhil Greenway
78dba5824bSPhil Greenway	SetPriority(B_DISPLAY_PRIORITY);
79dba5824bSPhil Greenway}
80dba5824bSPhil Greenway
81dba5824bSPhil Greenway
82dba5824bSPhil GreenwayVideoConsumer::~VideoConsumer()
83dba5824bSPhil Greenway{
84dba5824bSPhil Greenway	FUNCTION("VideoConsumer::~VideoConsumer\n");
85dba5824bSPhil Greenway
86dba5824bSPhil Greenway	Quit();
87dba5824bSPhil Greenway
889d3f15c6SIngo Weinhold	if (fWindow) {
89dba5824bSPhil Greenway		printf("Locking the window\n");
909d3f15c6SIngo Weinhold		if (fWindow->Lock()) {
91dba5824bSPhil Greenway			printf("Closing the window\n");
929d3f15c6SIngo Weinhold			fWindow->Close();
939d3f15c6SIngo Weinhold			fWindow = 0;
94dba5824bSPhil Greenway		}
95dba5824bSPhil Greenway	}
96dba5824bSPhil Greenway
97dba5824bSPhil Greenway	// clean up ftp thread
98dba5824bSPhil Greenway	// wait up to 30 seconds if ftp is in progress
99dba5824bSPhil Greenway	int32 count = 0;
1009d3f15c6SIngo Weinhold	while (!fFtpComplete && count < 30) {
101dba5824bSPhil Greenway		snooze(1000000);
102dba5824bSPhil Greenway		count++;
103dba5824bSPhil Greenway	}
104dba5824bSPhil Greenway
1059d3f15c6SIngo Weinhold	if (count == 30)
1069d3f15c6SIngo Weinhold		kill_thread(fFtpThread);
107dba5824bSPhil Greenway
108dba5824bSPhil Greenway	DeleteBuffers();
109dba5824bSPhil Greenway
110dba5824bSPhil Greenway}
111dba5824bSPhil Greenway
112dba5824bSPhil Greenway/********************************
113dba5824bSPhil Greenway	From BMediaNode
114dba5824bSPhil Greenway********************************/
115dba5824bSPhil Greenway
116dba5824bSPhil Greenway
1179d3f15c6SIngo WeinholdBMediaAddOn*
1189d3f15c6SIngo WeinholdVideoConsumer::AddOn(long* cookie) const
119dba5824bSPhil Greenway{
120dba5824bSPhil Greenway	FUNCTION("VideoConsumer::AddOn\n");
121dba5824bSPhil Greenway	// do the right thing if we're ever used with an add-on
1229d3f15c6SIngo Weinhold	*cookie = fInternalID;
1239d3f15c6SIngo Weinhold	return fAddOn;
124dba5824bSPhil Greenway}
125dba5824bSPhil Greenway
126dba5824bSPhil Greenway
127dba5824bSPhil Greenway// This implementation is required to get around a bug in
128dba5824bSPhil Greenway// the ppc compiler.
129dba5824bSPhil Greenway
130dba5824bSPhil Greenwayvoid
1319d3f15c6SIngo WeinholdVideoConsumer::Start(bigtime_t performanceTime)
132dba5824bSPhil Greenway{
1339d3f15c6SIngo Weinhold	BMediaEventLooper::Start(performanceTime);
134dba5824bSPhil Greenway}
135dba5824bSPhil Greenway
1369d3f15c6SIngo Weinhold
137dba5824bSPhil Greenwayvoid
1389d3f15c6SIngo WeinholdVideoConsumer::Stop(bigtime_t performanceTime, bool immediate)
139dba5824bSPhil Greenway{
1409d3f15c6SIngo Weinhold	BMediaEventLooper::Stop(performanceTime, immediate);
141dba5824bSPhil Greenway}
142dba5824bSPhil Greenway
1439d3f15c6SIngo Weinhold
144dba5824bSPhil Greenwayvoid
1459d3f15c6SIngo WeinholdVideoConsumer::Seek(bigtime_t mediaTime, bigtime_t performanceTime)
146dba5824bSPhil Greenway{
1479d3f15c6SIngo Weinhold	BMediaEventLooper::Seek(mediaTime, performanceTime);
148dba5824bSPhil Greenway}
149dba5824bSPhil Greenway
1509d3f15c6SIngo Weinhold
151dba5824bSPhil Greenwayvoid
1529d3f15c6SIngo WeinholdVideoConsumer::TimeWarp(bigtime_t atRealTime, bigtime_t toPerformanceTime)
153dba5824bSPhil Greenway{
1549d3f15c6SIngo Weinhold	BMediaEventLooper::TimeWarp(atRealTime, toPerformanceTime);
155dba5824bSPhil Greenway}
156dba5824bSPhil Greenway
1579d3f15c6SIngo Weinhold
158dba5824bSPhil Greenwaystatus_t
1599d3f15c6SIngo WeinholdVideoConsumer::DeleteHook(BMediaNode* node)
160dba5824bSPhil Greenway{
161dba5824bSPhil Greenway	return BMediaEventLooper::DeleteHook(node);
162dba5824bSPhil Greenway}
163dba5824bSPhil Greenway
164dba5824bSPhil Greenway
165dba5824bSPhil Greenwayvoid
166dba5824bSPhil GreenwayVideoConsumer::NodeRegistered()
167dba5824bSPhil Greenway{
168dba5824bSPhil Greenway	FUNCTION("VideoConsumer::NodeRegistered\n");
1699d3f15c6SIngo Weinhold	fIn.destination.port = ControlPort();
1709d3f15c6SIngo Weinhold	fIn.destination.id = 0;
1719d3f15c6SIngo Weinhold	fIn.source = media_source::null;
1729d3f15c6SIngo Weinhold	fIn.format.type = B_MEDIA_RAW_VIDEO;
1739d3f15c6SIngo Weinhold	fIn.format.u.raw_video = vid_format;
174dba5824bSPhil Greenway
175dba5824bSPhil Greenway	Run();
176dba5824bSPhil Greenway}
177dba5824bSPhil Greenway
178dba5824bSPhil Greenway
179dba5824bSPhil Greenwaystatus_t
1809d3f15c6SIngo WeinholdVideoConsumer::RequestCompleted(const media_request_info& info)
181dba5824bSPhil Greenway{
182dba5824bSPhil Greenway	FUNCTION("VideoConsumer::RequestCompleted\n");
1839d3f15c6SIngo Weinhold	switch (info.what) {
184dba5824bSPhil Greenway		case media_request_info::B_SET_OUTPUT_BUFFERS_FOR:
1859d3f15c6SIngo Weinhold			if (info.status != B_OK)
186dba5824bSPhil Greenway					ERROR("VideoConsumer::RequestCompleted: Not using our buffers!\n");
187dba5824bSPhil Greenway			break;
1889d3f15c6SIngo Weinhold
189859c1f01SNiels Sascha Reedijk		default:
190859c1f01SNiels Sascha Reedijk			ERROR("VideoConsumer::RequestCompleted: Invalid argument\n");
191859c1f01SNiels Sascha Reedijk			break;
192dba5824bSPhil Greenway	}
193dba5824bSPhil Greenway	return B_OK;
194dba5824bSPhil Greenway}
195dba5824bSPhil Greenway
196dba5824bSPhil Greenway
197dba5824bSPhil Greenwaystatus_t
1989d3f15c6SIngo WeinholdVideoConsumer::HandleMessage(int32 message, const void* data, size_t size)
199dba5824bSPhil Greenway{
200dba5824bSPhil Greenway	//FUNCTION("VideoConsumer::HandleMessage\n");
2019d3f15c6SIngo Weinhold	ftp_msg_info* info = (ftp_msg_info*)data;
202dba5824bSPhil Greenway	status_t status = B_OK;
2039d3f15c6SIngo Weinhold
2049d3f15c6SIngo Weinhold	switch (message) {
205dba5824bSPhil Greenway		case FTP_INFO:
206dba5824bSPhil Greenway			PROGRESS("VideoConsumer::HandleMessage - FTP_INFO message\n");
2079d3f15c6SIngo Weinhold			fRate = info->rate;
2089d3f15c6SIngo Weinhold			fImageFormat = info->imageFormat;
2099d3f15c6SIngo Weinhold			fTranslator = info->translator;
2109d3f15c6SIngo Weinhold			fPassiveFtp = info->passiveFtp;
211e3145a8dSFrançois Revol			fUploadClient = info->uploadClient;
2129d3f15c6SIngo Weinhold			strcpy(fFileNameText, info->fileNameText);
2139d3f15c6SIngo Weinhold			strcpy(fServerText, info->serverText);
2149d3f15c6SIngo Weinhold			strcpy(fLoginText, info->loginText);
2159d3f15c6SIngo Weinhold			strcpy(fPasswordText, info->passwordText);
2169d3f15c6SIngo Weinhold			strcpy(fDirectoryText, info->directoryText);
217dba5824bSPhil Greenway			// remove old user events
2189d3f15c6SIngo Weinhold			EventQueue()->FlushEvents(TimeSource()->Now(), BTimedEventQueue::B_ALWAYS,
2199d3f15c6SIngo Weinhold				true, BTimedEventQueue::B_USER_EVENT);
2209d3f15c6SIngo Weinhold			if (fRate != B_INFINITE_TIMEOUT) {
2219d3f15c6SIngo Weinhold				// if rate is not "Never," push an event
2229d3f15c6SIngo Weinhold				// to restart captures 5 seconds from now
2239d3f15c6SIngo Weinhold				media_timed_event event(TimeSource()->Now() + 5000000,
2249d3f15c6SIngo Weinhold					BTimedEventQueue::B_USER_EVENT);
225dba5824bSPhil Greenway				EventQueue()->AddEvent(event);
226dba5824bSPhil Greenway			}
227dba5824bSPhil Greenway			break;
228dba5824bSPhil Greenway	}
229dba5824bSPhil Greenway
230dba5824bSPhil Greenway	return status;
231dba5824bSPhil Greenway}
232dba5824bSPhil Greenway
233dba5824bSPhil Greenway
234dba5824bSPhil Greenwayvoid
2359d3f15c6SIngo WeinholdVideoConsumer::BufferReceived(BBuffer* buffer)
236dba5824bSPhil Greenway{
237e3145a8dSFrançois Revol	LOOP("VideoConsumer::Buffer #%ld received, start_time %Ld\n", buffer->ID(), buffer->Header()->start_time);
238dba5824bSPhil Greenway
2399d3f15c6SIngo Weinhold	if (RunState() == B_STOPPED) {
240dba5824bSPhil Greenway		buffer->Recycle();
241dba5824bSPhil Greenway		return;
242dba5824bSPhil Greenway	}
243dba5824bSPhil Greenway
244dba5824bSPhil Greenway	media_timed_event event(buffer->Header()->start_time, BTimedEventQueue::B_HANDLE_BUFFER,
2459d3f15c6SIngo Weinhold		buffer, BTimedEventQueue::B_RECYCLE_BUFFER);
246dba5824bSPhil Greenway	EventQueue()->AddEvent(event);
247dba5824bSPhil Greenway}
248dba5824bSPhil Greenway
249dba5824bSPhil Greenway
250dba5824bSPhil Greenwayvoid
2519d3f15c6SIngo WeinholdVideoConsumer::ProducerDataStatus(const media_destination& forWhom, int32 status,
2529d3f15c6SIngo Weinhold	bigtime_t atMediaTime)
253dba5824bSPhil Greenway{
254dba5824bSPhil Greenway	FUNCTION("VideoConsumer::ProducerDataStatus\n");
255dba5824bSPhil Greenway
2569d3f15c6SIngo Weinhold	if (forWhom != fIn.destination)
257dba5824bSPhil Greenway		return;
258dba5824bSPhil Greenway}
259dba5824bSPhil Greenway
260dba5824bSPhil Greenway
261dba5824bSPhil Greenwaystatus_t
2629d3f15c6SIngo WeinholdVideoConsumer::CreateBuffers(const media_format& withFormat)
263dba5824bSPhil Greenway{
264dba5824bSPhil Greenway	FUNCTION("VideoConsumer::CreateBuffers\n");
2659d3f15c6SIngo Weinhold
266dba5824bSPhil Greenway	DeleteBuffers();
2679d3f15c6SIngo Weinhold		// delete any old buffers
268dba5824bSPhil Greenway
269dba5824bSPhil Greenway	status_t status = B_OK;
270dba5824bSPhil Greenway
271dba5824bSPhil Greenway	// create a buffer group
2729d3f15c6SIngo Weinhold	uint32 xSize = withFormat.u.raw_video.display.line_width;
2739d3f15c6SIngo Weinhold	uint32 ySize = withFormat.u.raw_video.display.line_count;
2749d3f15c6SIngo Weinhold	color_space colorspace = withFormat.u.raw_video.display.format;
2759d3f15c6SIngo Weinhold	PROGRESS("VideoConsumer::CreateBuffers - Colorspace = %d\n", colorspace);
2769d3f15c6SIngo Weinhold
2779d3f15c6SIngo Weinhold	fBuffers = new BBufferGroup();
2789d3f15c6SIngo Weinhold	status = fBuffers->InitCheck();
2799d3f15c6SIngo Weinhold	if (status != B_OK) {
280dba5824bSPhil Greenway		ERROR("VideoConsumer::CreateBuffers - ERROR CREATING BUFFER GROUP\n");
281dba5824bSPhil Greenway		return status;
282dba5824bSPhil Greenway	}
283dba5824bSPhil Greenway	// and attach the  bitmaps to the buffer group
2849d3f15c6SIngo Weinhold	for (uint32 j = 0; j < 3; j++) {
2859d3f15c6SIngo Weinhold		fBitmap[j] = new BBitmap(BRect(0, 0, (xSize - 1), (ySize - 1)), colorspace,
2869d3f15c6SIngo Weinhold			false, true);
2879d3f15c6SIngo Weinhold		if (fBitmap[j]->IsValid()) {
288dba5824bSPhil Greenway			buffer_clone_info info;
2899d3f15c6SIngo Weinhold			if ((info.area = area_for(fBitmap[j]->Bits())) == B_ERROR)
2909d3f15c6SIngo Weinhold				ERROR("VideoConsumer::CreateBuffers - ERROR IN AREA_FOR\n");
291dba5824bSPhil Greenway			info.offset = 0;
2929d3f15c6SIngo Weinhold			info.size = (size_t)fBitmap[j]->BitsLength();
293dba5824bSPhil Greenway			info.flags = j;
294dba5824bSPhil Greenway			info.buffer = 0;
295dba5824bSPhil Greenway
2969d3f15c6SIngo Weinhold			if ((status = fBuffers->AddBuffer(info)) != B_OK) {
297dba5824bSPhil Greenway				ERROR("VideoConsumer::CreateBuffers - ERROR ADDING BUFFER TO GROUP\n");
298dba5824bSPhil Greenway				return status;
2999d3f15c6SIngo Weinhold			}
3009d3f15c6SIngo Weinhold			else
3019d3f15c6SIngo Weinhold				PROGRESS("VideoConsumer::CreateBuffers - SUCCESSFUL ADD BUFFER TO GROUP\n");
3029d3f15c6SIngo Weinhold		} else {
3039d3f15c6SIngo Weinhold			ERROR("VideoConsumer::CreateBuffers - ERROR CREATING VIDEO RING BUFFER: %08lx\n",
3049d3f15c6SIngo Weinhold				status);
305dba5824bSPhil Greenway			return B_ERROR;
3069d3f15c6SIngo Weinhold		}
307dba5824bSPhil Greenway	}
3089d3f15c6SIngo Weinhold
3099d3f15c6SIngo Weinhold	BBuffer** buffList = new BBuffer * [3];
3109d3f15c6SIngo Weinhold	for (int j = 0; j < 3; j++)
3119d3f15c6SIngo Weinhold		buffList[j] = 0;
3129d3f15c6SIngo Weinhold
3139d3f15c6SIngo Weinhold	if ((status = fBuffers->GetBufferList(3, buffList)) == B_OK)
314dba5824bSPhil Greenway		for (int j = 0; j < 3; j++)
3159d3f15c6SIngo Weinhold			if (buffList[j] != NULL) {
3169d3f15c6SIngo Weinhold				fBufferMap[j] = (uint32)buffList[j];
3179d3f15c6SIngo Weinhold				PROGRESS(" j = %d buffer = %08lx\n", j, fBufferMap[j]);
3189d3f15c6SIngo Weinhold			} else {
319dba5824bSPhil Greenway				ERROR("VideoConsumer::CreateBuffers ERROR MAPPING RING BUFFER\n");
320dba5824bSPhil Greenway				return B_ERROR;
321dba5824bSPhil Greenway			}
322dba5824bSPhil Greenway	else
323dba5824bSPhil Greenway		ERROR("VideoConsumer::CreateBuffers ERROR IN GET BUFFER LIST\n");
3249d3f15c6SIngo Weinhold
325dba5824bSPhil Greenway	FUNCTION("VideoConsumer::CreateBuffers - EXIT\n");
326dba5824bSPhil Greenway	return status;
327dba5824bSPhil Greenway}
328dba5824bSPhil Greenway
329dba5824bSPhil Greenway
330dba5824bSPhil Greenwayvoid
331dba5824bSPhil GreenwayVideoConsumer::DeleteBuffers()
332dba5824bSPhil Greenway{
333dba5824bSPhil Greenway	FUNCTION("VideoConsumer::DeleteBuffers\n");
3349d3f15c6SIngo Weinhold
3359d3f15c6SIngo Weinhold	if (fBuffers) {
3369d3f15c6SIngo Weinhold		delete fBuffers;
3379d3f15c6SIngo Weinhold		fBuffers = NULL;
3389d3f15c6SIngo Weinhold
339dba5824bSPhil Greenway		for (uint32 j = 0; j < 3; j++)
3409d3f15c6SIngo Weinhold			if (fBitmap[j]->IsValid()) {
3419d3f15c6SIngo Weinhold				delete fBitmap[j];
3429d3f15c6SIngo Weinhold				fBitmap[j] = NULL;
343dba5824bSPhil Greenway			}
344dba5824bSPhil Greenway	}
345dba5824bSPhil Greenway	FUNCTION("VideoConsumer::DeleteBuffers - EXIT\n");
346dba5824bSPhil Greenway}
347dba5824bSPhil Greenway
348dba5824bSPhil Greenway
349dba5824bSPhil Greenwaystatus_t
3509d3f15c6SIngo WeinholdVideoConsumer::Connected(const media_source& producer, const media_destination& where,
3519d3f15c6SIngo Weinhold	const media_format& withFormat, media_input* outInput)
352dba5824bSPhil Greenway{
353dba5824bSPhil Greenway	FUNCTION("VideoConsumer::Connected\n");
354dba5824bSPhil Greenway
3559d3f15c6SIngo Weinhold	fIn.source = producer;
3569d3f15c6SIngo Weinhold	fIn.format = withFormat;
3579d3f15c6SIngo Weinhold	fIn.node = Node();
3589d3f15c6SIngo Weinhold	sprintf(fIn.name, "Video Consumer");
3599d3f15c6SIngo Weinhold	*outInput = fIn;
3609d3f15c6SIngo Weinhold
3619d3f15c6SIngo Weinhold	uint32 userData = 0;
3629d3f15c6SIngo Weinhold	int32 changeTag = 1;
3639d3f15c6SIngo Weinhold	if (CreateBuffers(withFormat) == B_OK)
3649d3f15c6SIngo Weinhold		BBufferConsumer::SetOutputBuffersFor(producer, fDestination,
3659d3f15c6SIngo Weinhold			fBuffers, (void *)&userData, &changeTag, true);
3669d3f15c6SIngo Weinhold	else {
367dba5824bSPhil Greenway		ERROR("VideoConsumer::Connected - COULDN'T CREATE BUFFERS\n");
368dba5824bSPhil Greenway		return B_ERROR;
369dba5824bSPhil Greenway	}
370dba5824bSPhil Greenway
3719d3f15c6SIngo Weinhold	fFtpBitmap = new BBitmap(BRect(0, 0, 320 - 1, 240 - 1), B_RGB32, false, false);
3729d3f15c6SIngo Weinhold	fConnectionActive = true;
3739d3f15c6SIngo Weinhold
374dba5824bSPhil Greenway	FUNCTION("VideoConsumer::Connected - EXIT\n");
375dba5824bSPhil Greenway	return B_OK;
376dba5824bSPhil Greenway}
377dba5824bSPhil Greenway
378dba5824bSPhil Greenway
379dba5824bSPhil Greenwayvoid
3809d3f15c6SIngo WeinholdVideoConsumer::Disconnected(const media_source& producer, const media_destination& where)
381dba5824bSPhil Greenway{
382dba5824bSPhil Greenway	FUNCTION("VideoConsumer::Disconnected\n");
383dba5824bSPhil Greenway
3849d3f15c6SIngo Weinhold	if (where == fIn.destination && producer == fIn.source) {
385dba5824bSPhil Greenway		// disconnect the connection
3869d3f15c6SIngo Weinhold		fIn.source = media_source::null;
3879d3f15c6SIngo Weinhold		delete fFtpBitmap;
3889d3f15c6SIngo Weinhold		fConnectionActive = false;
389dba5824bSPhil Greenway	}
390dba5824bSPhil Greenway
391dba5824bSPhil Greenway}
392dba5824bSPhil Greenway
393dba5824bSPhil Greenway
394dba5824bSPhil Greenwaystatus_t
3959d3f15c6SIngo WeinholdVideoConsumer::AcceptFormat(const media_destination& dest, media_format* format)
396dba5824bSPhil Greenway{
397dba5824bSPhil Greenway	FUNCTION("VideoConsumer::AcceptFormat\n");
398dba5824bSPhil Greenway
3999d3f15c6SIngo Weinhold	if (dest != fIn.destination) {
400dba5824bSPhil Greenway		ERROR("VideoConsumer::AcceptFormat - BAD DESTINATION\n");
401dba5824bSPhil Greenway		return B_MEDIA_BAD_DESTINATION;
402dba5824bSPhil Greenway	}
4039d3f15c6SIngo Weinhold
404dba5824bSPhil Greenway	if (format->type == B_MEDIA_NO_TYPE)
405dba5824bSPhil Greenway		format->type = B_MEDIA_RAW_VIDEO;
406dba5824bSPhil Greenway
4079d3f15c6SIngo Weinhold	if (format->type != B_MEDIA_RAW_VIDEO) {
408dba5824bSPhil Greenway		ERROR("VideoConsumer::AcceptFormat - BAD FORMAT\n");
409dba5824bSPhil Greenway		return B_MEDIA_BAD_FORMAT;
410dba5824bSPhil Greenway	}
411dba5824bSPhil Greenway
4129d3f15c6SIngo Weinhold	if (format->u.raw_video.display.format != B_RGB32
4139d3f15c6SIngo Weinhold		&& format->u.raw_video.display.format != B_RGB16
4149d3f15c6SIngo Weinhold		&& format->u.raw_video.display.format != B_RGB15
4159d3f15c6SIngo Weinhold		&& format->u.raw_video.display.format != B_GRAY8
4169d3f15c6SIngo Weinhold		&&
4179d3f15c6SIngo Weinhold		format->u.raw_video.display.format != media_raw_video_format::wildcard.display.format) {
418dba5824bSPhil Greenway		ERROR("AcceptFormat - not a format we know about!\n");
419dba5824bSPhil Greenway		return B_MEDIA_BAD_FORMAT;
420dba5824bSPhil Greenway	}
4219d3f15c6SIngo Weinhold
4229d3f15c6SIngo Weinhold	if (format->u.raw_video.display.format == media_raw_video_format::wildcard.display.format) {
423dba5824bSPhil Greenway		format->u.raw_video.display.format = B_RGB16;
424dba5824bSPhil Greenway	}
425dba5824bSPhil Greenway
4269d3f15c6SIngo Weinhold	char formatString[256];
4279d3f15c6SIngo Weinhold	string_for_format(*format, formatString, 256);
4289d3f15c6SIngo Weinhold	FUNCTION("VideoConsumer::AcceptFormat: %s\n", formatString);
429dba5824bSPhil Greenway
430dba5824bSPhil Greenway	return B_OK;
431dba5824bSPhil Greenway}
432dba5824bSPhil Greenway
433dba5824bSPhil Greenway
434dba5824bSPhil Greenwaystatus_t
4359d3f15c6SIngo WeinholdVideoConsumer::GetNextInput(int32* cookie, media_input* outInput)
436dba5824bSPhil Greenway{
437dba5824bSPhil Greenway	FUNCTION("VideoConsumer::GetNextInput\n");
438dba5824bSPhil Greenway
439dba5824bSPhil Greenway	// custom build a destination for this connection
440dba5824bSPhil Greenway	// put connection number in id
441dba5824bSPhil Greenway
4429d3f15c6SIngo Weinhold	if (*cookie < 1) {
4439d3f15c6SIngo Weinhold		fIn.node = Node();
4449d3f15c6SIngo Weinhold		fIn.destination.id = *cookie;
4459d3f15c6SIngo Weinhold		sprintf(fIn.name, "Video Consumer");
4469d3f15c6SIngo Weinhold		*outInput = fIn;
447dba5824bSPhil Greenway		(*cookie)++;
448dba5824bSPhil Greenway		return B_OK;
4499d3f15c6SIngo Weinhold	} else {
450dba5824bSPhil Greenway		ERROR("VideoConsumer::GetNextInput - - BAD INDEX\n");
451dba5824bSPhil Greenway		return B_MEDIA_BAD_DESTINATION;
452dba5824bSPhil Greenway	}
453dba5824bSPhil Greenway}
454dba5824bSPhil Greenway
455dba5824bSPhil Greenway
456dba5824bSPhil Greenwayvoid
457dba5824bSPhil GreenwayVideoConsumer::DisposeInputCookie(int32 /*cookie*/)
458dba5824bSPhil Greenway{
459dba5824bSPhil Greenway}
460dba5824bSPhil Greenway
461dba5824bSPhil Greenway
462dba5824bSPhil Greenwaystatus_t
4639d3f15c6SIngo WeinholdVideoConsumer::GetLatencyFor(const media_destination& forWhom, bigtime_t* outLatency,
4649d3f15c6SIngo Weinhold	media_node_id* out_timesource)
465dba5824bSPhil Greenway{
466dba5824bSPhil Greenway	FUNCTION("VideoConsumer::GetLatencyFor\n");
467dba5824bSPhil Greenway
4689d3f15c6SIngo Weinhold	if (forWhom != fIn.destination)
469dba5824bSPhil Greenway		return B_MEDIA_BAD_DESTINATION;
470dba5824bSPhil Greenway
4719d3f15c6SIngo Weinhold	*outLatency = fMyLatency;
472dba5824bSPhil Greenway	*out_timesource = TimeSource()->ID();
473dba5824bSPhil Greenway	return B_OK;
474dba5824bSPhil Greenway}
475dba5824bSPhil Greenway
476dba5824bSPhil Greenway
477dba5824bSPhil Greenwaystatus_t
4789d3f15c6SIngo WeinholdVideoConsumer::FormatChanged(const media_source& producer, const media_destination& consumer,
4799d3f15c6SIngo Weinhold	int32 fromChangeCount, const media_format& format)
480dba5824bSPhil Greenway{
481dba5824bSPhil Greenway	FUNCTION("VideoConsumer::FormatChanged\n");
4829d3f15c6SIngo Weinhold
4839d3f15c6SIngo Weinhold	if (consumer != fIn.destination)
484dba5824bSPhil Greenway		return B_MEDIA_BAD_DESTINATION;
485dba5824bSPhil Greenway
4869d3f15c6SIngo Weinhold	if (producer != fIn.source)
487dba5824bSPhil Greenway		return B_MEDIA_BAD_SOURCE;
488dba5824bSPhil Greenway
4899d3f15c6SIngo Weinhold	fIn.format = format;
4909d3f15c6SIngo Weinhold
491dba5824bSPhil Greenway	return CreateBuffers(format);
492dba5824bSPhil Greenway}
493dba5824bSPhil Greenway
494dba5824bSPhil Greenway
495dba5824bSPhil Greenwayvoid
4969d3f15c6SIngo WeinholdVideoConsumer::HandleEvent(const media_timed_event* event, bigtime_t lateness,
497dba5824bSPhil Greenway	bool realTimeEvent)
498dba5824bSPhil Greenway{
499dba5824bSPhil Greenway	LOOP("VideoConsumer::HandleEvent\n");
500dba5824bSPhil Greenway
5019d3f15c6SIngo Weinhold	BBuffer* buffer;
5029d3f15c6SIngo Weinhold
5039d3f15c6SIngo Weinhold	switch (event->type) {
504dba5824bSPhil Greenway		case BTimedEventQueue::B_START:
505dba5824bSPhil Greenway			PROGRESS("VideoConsumer::HandleEvent - START\n");
506dba5824bSPhil Greenway			break;
5079d3f15c6SIngo Weinhold
508dba5824bSPhil Greenway		case BTimedEventQueue::B_STOP:
509dba5824bSPhil Greenway			PROGRESS("VideoConsumer::HandleEvent - STOP\n");
5109d3f15c6SIngo Weinhold			EventQueue()->FlushEvents(event->event_time, BTimedEventQueue::B_ALWAYS,
5119d3f15c6SIngo Weinhold				true, BTimedEventQueue::B_HANDLE_BUFFER);
512dba5824bSPhil Greenway			break;
5139d3f15c6SIngo Weinhold
514dba5824bSPhil Greenway		case BTimedEventQueue::B_USER_EVENT:
515dba5824bSPhil Greenway			PROGRESS("VideoConsumer::HandleEvent - USER EVENT\n");
5169d3f15c6SIngo Weinhold			if (RunState() == B_STARTED) {
5179d3f15c6SIngo Weinhold				fTimeToFtp = true;
5189d3f15c6SIngo Weinhold				PROGRESS("Pushing user event for %.4f, time now %.4f\n",
5199d3f15c6SIngo Weinhold					(event->event_time + fRate) / M1, event->event_time/M1);
5209d3f15c6SIngo Weinhold				media_timed_event newEvent(event->event_time + fRate,
5219d3f15c6SIngo Weinhold					BTimedEventQueue::B_USER_EVENT);
522dba5824bSPhil Greenway				EventQueue()->AddEvent(newEvent);
523dba5824bSPhil Greenway			}
5249d3f15c6SIngo Weinhold			break;
5259d3f15c6SIngo Weinhold
526dba5824bSPhil Greenway		case BTimedEventQueue::B_HANDLE_BUFFER:
5279d3f15c6SIngo Weinhold		{
528dba5824bSPhil Greenway			LOOP("VideoConsumer::HandleEvent - HANDLE BUFFER\n");
5299d3f15c6SIngo Weinhold			buffer = (BBuffer *)event->pointer;
5309d3f15c6SIngo Weinhold			if (RunState() == B_STARTED && fConnectionActive) {
531dba5824bSPhil Greenway				// see if this is one of our buffers
532dba5824bSPhil Greenway				uint32 index = 0;
5339d3f15c6SIngo Weinhold				fOurBuffers = true;
5349d3f15c6SIngo Weinhold				while (index < 3)
5359d3f15c6SIngo Weinhold					if ((uint32)buffer == fBufferMap[index])
536dba5824bSPhil Greenway						break;
537dba5824bSPhil Greenway					else
538dba5824bSPhil Greenway						index++;
5399d3f15c6SIngo Weinhold
5409d3f15c6SIngo Weinhold				if (index == 3) {
541dba5824bSPhil Greenway					// no, buffers belong to consumer
5429d3f15c6SIngo Weinhold					fOurBuffers = false;
543dba5824bSPhil Greenway					index = 0;
544dba5824bSPhil Greenway				}
5459d3f15c6SIngo Weinhold
5469d3f15c6SIngo Weinhold				if (fFtpComplete && fTimeToFtp) {
547dba5824bSPhil Greenway					PROGRESS("VidConsumer::HandleEvent - SPAWNING FTP THREAD\n");
5489d3f15c6SIngo Weinhold					fTimeToFtp = false;
5499d3f15c6SIngo Weinhold					fFtpComplete = false;
5509d3f15c6SIngo Weinhold					memcpy(fFtpBitmap->Bits(), buffer->Data(), fFtpBitmap->BitsLength());
5519d3f15c6SIngo Weinhold					fFtpThread = spawn_thread(FtpRun, "Video Window Ftp", B_NORMAL_PRIORITY, this);
5529d3f15c6SIngo Weinhold					resume_thread(fFtpThread);
553dba5824bSPhil Greenway				}
554dba5824bSPhil Greenway
5559d3f15c6SIngo Weinhold				if ((RunMode() == B_OFFLINE)
5569d3f15c6SIngo Weinhold					|| ((TimeSource()->Now() > (buffer->Header()->start_time - JITTER))
5579d3f15c6SIngo Weinhold						&& (TimeSource()->Now() < (buffer->Header()->start_time + JITTER)))) {
5589d3f15c6SIngo Weinhold					if (!fOurBuffers)
559dba5824bSPhil Greenway						// not our buffers, so we need to copy
5609d3f15c6SIngo Weinhold						memcpy(fBitmap[index]->Bits(), buffer->Data(), fBitmap[index]->BitsLength());
5619d3f15c6SIngo Weinhold
5629d3f15c6SIngo Weinhold					if (fWindow->Lock()) {
563dba5824bSPhil Greenway						uint32 flags;
5649d3f15c6SIngo Weinhold						if ((fBitmap[index]->ColorSpace() == B_GRAY8) &&
5659d3f15c6SIngo Weinhold							!bitmaps_support_space(fBitmap[index]->ColorSpace(), &flags)) {
566dba5824bSPhil Greenway							// handle mapping of GRAY8 until app server knows how
5679d3f15c6SIngo Weinhold							uint32* start = (uint32*)fBitmap[index]->Bits();
5689d3f15c6SIngo Weinhold							int32 size = fBitmap[index]->BitsLength();
5699d3f15c6SIngo Weinhold							uint32* end = start + size / 4;
5709d3f15c6SIngo Weinhold							for (uint32* p = start; p < end; p++)
571dba5824bSPhil Greenway								*p = (*p >> 3) & 0x1f1f1f1f;
572dba5824bSPhil Greenway						}
5739d3f15c6SIngo Weinhold
5749d3f15c6SIngo Weinhold						fView->DrawBitmap(fBitmap[index]);
5759d3f15c6SIngo Weinhold						fWindow->Unlock();
576dba5824bSPhil Greenway					}
577dba5824bSPhil Greenway				}
578dba5824bSPhil Greenway				else
579dba5824bSPhil Greenway					PROGRESS("VidConsumer::HandleEvent - DROPPED FRAME\n");
580dba5824bSPhil Greenway				buffer->Recycle();
581dba5824bSPhil Greenway			}
582dba5824bSPhil Greenway			else
583dba5824bSPhil Greenway				buffer->Recycle();
584dba5824bSPhil Greenway			break;
5859d3f15c6SIngo Weinhold		}
5869d3f15c6SIngo Weinhold
587dba5824bSPhil Greenway		default:
588dba5824bSPhil Greenway			ERROR("VideoConsumer::HandleEvent - BAD EVENT\n");
589dba5824bSPhil Greenway			break;
590dba5824bSPhil Greenway	}
591dba5824bSPhil Greenway}
592dba5824bSPhil Greenway
593dba5824bSPhil Greenway
594dba5824bSPhil Greenwaystatus_t
5959d3f15c6SIngo WeinholdVideoConsumer::FtpRun(void* data)
596dba5824bSPhil Greenway{
597dba5824bSPhil Greenway	FUNCTION("VideoConsumer::FtpRun\n");
598dba5824bSPhil Greenway
599dba5824bSPhil Greenway	((VideoConsumer *)data)->FtpThread();
600dba5824bSPhil Greenway
601dba5824bSPhil Greenway	return 0;
602dba5824bSPhil Greenway}
603dba5824bSPhil Greenway
604dba5824bSPhil Greenway
605dba5824bSPhil Greenwayvoid
606dba5824bSPhil GreenwayVideoConsumer::FtpThread()
607dba5824bSPhil Greenway{
608dba5824bSPhil Greenway	FUNCTION("VideoConsumer::FtpThread\n");
609dba5824bSPhil Greenway
6109d3f15c6SIngo Weinhold	if (LocalSave(fFileNameText, fFtpBitmap) == B_OK)
6119d3f15c6SIngo Weinhold		FtpSave(fFileNameText);
6129d3f15c6SIngo Weinhold
613dba5824bSPhil Greenway#if 0
614dba5824bSPhil Greenway	// save a small version, too
6159d3f15c6SIngo Weinhold	BBitmap* b = new BBitmap(BRect(0,0,159,119), B_RGB32, true, false);
6169d3f15c6SIngo Weinhold	BView* v = new BView(BRect(0,0,159,119), "SmallView 1", 0, B_WILL_DRAW);
617dba5824bSPhil Greenway	b->AddChild(v);
618dba5824bSPhil Greenway
619dba5824bSPhil Greenway	b->Lock();
6209d3f15c6SIngo Weinhold	v->DrawBitmap(fFtpBitmap, v->Frame());
621dba5824bSPhil Greenway	v->Sync();
622dba5824bSPhil Greenway	b->Unlock();
623dba5824bSPhil Greenway
624dba5824bSPhil Greenway	if (LocalSave("small.jpg", b) == B_OK)
625dba5824bSPhil Greenway		FtpSave("small.jpg");
626dba5824bSPhil Greenway
627dba5824bSPhil Greenway	delete b;
628dba5824bSPhil Greenway#endif
629dba5824bSPhil Greenway
6309d3f15c6SIngo Weinhold	fFtpComplete = true;
631dba5824bSPhil Greenway}
632dba5824bSPhil Greenway
633dba5824bSPhil Greenway
634dba5824bSPhil Greenwayvoid
6359d3f15c6SIngo WeinholdVideoConsumer::UpdateFtpStatus(char* status)
636dba5824bSPhil Greenway{
637dba5824bSPhil Greenway	printf("FTP STATUS: %s\n",status);
6389d3f15c6SIngo Weinhold	if (fView->Window()->Lock()) {
6399d3f15c6SIngo Weinhold		fStatusLine->SetText(status);
6409d3f15c6SIngo Weinhold		fView->Window()->Unlock();
641dba5824bSPhil Greenway	}
642dba5824bSPhil Greenway}
643dba5824bSPhil Greenway
644dba5824bSPhil Greenway
645dba5824bSPhil Greenwaystatus_t
6469d3f15c6SIngo WeinholdVideoConsumer::LocalSave(char* filename, BBitmap* bitmap)
647dba5824bSPhil Greenway{
6489d3f15c6SIngo Weinhold	BFile* output;
6499d3f15c6SIngo Weinhold
650dba5824bSPhil Greenway	UpdateFtpStatus("Capturing Image ...");
651dba5824bSPhil Greenway
652dba5824bSPhil Greenway	/* save a local copy of the image in the requested format */
6539d3f15c6SIngo Weinhold	output = new BFile();
6549d3f15c6SIngo Weinhold	if (output->SetTo(filename, B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE) == B_NO_ERROR) {
655dba5824bSPhil Greenway		BBitmapStream input(bitmap);
6569d3f15c6SIngo Weinhold		status_t err = BTranslatorRoster::Default()->Translate(&input, NULL, NULL,
6579d3f15c6SIngo Weinhold        	output, fImageFormat);
6589d3f15c6SIngo Weinhold        if (err == B_OK) {
6599d3f15c6SIngo Weinhold        	err = SetFileType(output, fTranslator, fImageFormat);
660dba5824bSPhil Greenway        	if (err != B_OK)
661dba5824bSPhil Greenway        		UpdateFtpStatus("Error setting type of output file");
662dba5824bSPhil Greenway        }
663dba5824bSPhil Greenway        else
664dba5824bSPhil Greenway        	UpdateFtpStatus("Error writing output file");
6659d3f15c6SIngo Weinhold
6669d3f15c6SIngo Weinhold		input.DetachBitmap(&bitmap);
6679d3f15c6SIngo Weinhold		output->Unset();
6689d3f15c6SIngo Weinhold		delete output;
6699d3f15c6SIngo Weinhold		return B_OK;
6709d3f15c6SIngo Weinhold    } else {
671dba5824bSPhil Greenway		UpdateFtpStatus("Error creating output file");
672dba5824bSPhil Greenway    	return B_ERROR;
673dba5824bSPhil Greenway    }
674dba5824bSPhil Greenway}
675dba5824bSPhil Greenway
676dba5824bSPhil Greenway
677dba5824bSPhil Greenwaystatus_t
6789d3f15c6SIngo WeinholdVideoConsumer::FtpSave(char* filename)
679dba5824bSPhil Greenway{
680e3145a8dSFrançois Revol	FileUploadClient *ftp;
681e3145a8dSFrançois Revol
682e3145a8dSFrançois Revol	//XXX: make that cleaner
683e3145a8dSFrançois Revol	switch (fUploadClient) {
684e3145a8dSFrançois Revol		case 0:
685e3145a8dSFrançois Revol			ftp = new FtpClient;
686e3145a8dSFrançois Revol			break;
687e3145a8dSFrançois Revol		case 1:
688e3145a8dSFrançois Revol			ftp = new SftpClient;
689e3145a8dSFrançois Revol			break;
690e3145a8dSFrançois Revol		default:
69171814054SFrançois Revol			fprintf(stderr, "invalid upload client %d\n", fUploadClient);
692e3145a8dSFrançois Revol			return EINVAL;
693e3145a8dSFrançois Revol	}
6949d3f15c6SIngo Weinhold
695e3145a8dSFrançois Revol	ftp->SetPassive(fPassiveFtp);
6969d3f15c6SIngo Weinhold		// ftp the local file to our web site
697dba5824bSPhil Greenway
698dba5824bSPhil Greenway	UpdateFtpStatus("Logging in ...");
699e3145a8dSFrançois Revol	if (ftp->Connect((string)fServerText, (string)fLoginText, (string)fPasswordText)) {
7009d3f15c6SIngo Weinhold		// connect to server
701dba5824bSPhil Greenway		UpdateFtpStatus("Connected ...");
7029d3f15c6SIngo Weinhold
703e3145a8dSFrançois Revol		if (ftp->ChangeDir((string)fDirectoryText)) {
7049d3f15c6SIngo Weinhold			// cd to the desired directory
705dba5824bSPhil Greenway			UpdateFtpStatus("Transmitting ...");
7069d3f15c6SIngo Weinhold
707e3145a8dSFrançois Revol			if (ftp->PutFile((string)filename, (string)"temp")) {
7089d3f15c6SIngo Weinhold				// send the file to the server
7096298fd45SFrançois Revol
7106298fd45SFrançois Revol				ftp->Chmod((string)filename, (string)"644");
7116298fd45SFrançois Revol				// make it world readable
7126298fd45SFrançois Revol
713dba5824bSPhil Greenway				UpdateFtpStatus("Renaming ...");
7149d3f15c6SIngo Weinhold
715e3145a8dSFrançois Revol				if (ftp->MoveFile((string)"temp", (string)filename)) {
7169d3f15c6SIngo Weinhold					// change to the desired name
717dba5824bSPhil Greenway					uint32 time = real_time_clock();
718dba5824bSPhil Greenway					char s[80];
7199d3f15c6SIngo Weinhold					strcpy(s, "Last Capture: ");
7209d3f15c6SIngo Weinhold					strcat(s, ctime((const long*)&time));
7219d3f15c6SIngo Weinhold					s[strlen(s) - 1] = 0;
722dba5824bSPhil Greenway					UpdateFtpStatus(s);
723e3145a8dSFrançois Revol					delete ftp;
724dba5824bSPhil Greenway					return B_OK;
7259d3f15c6SIngo Weinhold				}
7269d3f15c6SIngo Weinhold				else
7279d3f15c6SIngo Weinhold					UpdateFtpStatus("Rename failed");
7289d3f15c6SIngo Weinhold			}
7299d3f15c6SIngo Weinhold			else
7309d3f15c6SIngo Weinhold				UpdateFtpStatus("File transmission failed");
7319d3f15c6SIngo Weinhold		}
7329d3f15c6SIngo Weinhold		else
7339d3f15c6SIngo Weinhold			UpdateFtpStatus("Couldn't find requested directory on server");
7349d3f15c6SIngo Weinhold	}
7359d3f15c6SIngo Weinhold	else
7369d3f15c6SIngo Weinhold		UpdateFtpStatus("Server login failed");
7379d3f15c6SIngo Weinhold
738e3145a8dSFrançois Revol	delete ftp;
739dba5824bSPhil Greenway	return B_ERROR;
740dba5824bSPhil Greenway}
741dba5824bSPhil Greenway
742dba5824bSPhil Greenway
743dba5824bSPhil Greenwaystatus_t
7449d3f15c6SIngo WeinholdSetFileType(BFile* file, int32 translator, uint32 type)
745dba5824bSPhil Greenway{
7469d3f15c6SIngo Weinhold	translation_format* formats;
7479d3f15c6SIngo Weinhold	int32 count;
7489d3f15c6SIngo Weinhold
7499d3f15c6SIngo Weinhold	status_t err = BTranslatorRoster::Default()->GetOutputFormats(translator,
7509d3f15c6SIngo Weinhold		(const translation_format **)&formats, &count);
7519d3f15c6SIngo Weinhold	if (err < B_OK)
7529d3f15c6SIngo Weinhold		return err;
7539d3f15c6SIngo Weinhold
7549d3f15c6SIngo Weinhold	const char* mime = NULL;
7559d3f15c6SIngo Weinhold	for (int ix = 0; ix < count; ix++) {
7569d3f15c6SIngo Weinhold		if (formats[ix].type == type) {
7579d3f15c6SIngo Weinhold			mime = formats[ix].MIME;
7589d3f15c6SIngo Weinhold			break;
7599d3f15c6SIngo Weinhold		}
7609d3f15c6SIngo Weinhold	}
761dba5824bSPhil Greenway
7629d3f15c6SIngo Weinhold	if (mime == NULL) {
7639d3f15c6SIngo Weinhold		/* this should not happen, but being defensive might be prudent */
7649d3f15c6SIngo Weinhold		return B_ERROR;
7659d3f15c6SIngo Weinhold	}
766dba5824bSPhil Greenway
7679d3f15c6SIngo Weinhold	/* use BNodeInfo to set the file type */
7689d3f15c6SIngo Weinhold	BNodeInfo ninfo(file);
7699d3f15c6SIngo Weinhold	return ninfo.SetType(mime);
7709d3f15c6SIngo Weinhold}
771