VideoConsumer.cpp revision 45c2e6b8
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
3253dd6b9cfSFrançois Revol	fFtpBitmap = new BBitmap(BRect(0, 0, xSize - 1, ySize - 1), B_RGB32, false, false);
3263dd6b9cfSFrançois Revol
327dba5824bSPhil Greenway	FUNCTION("VideoConsumer::CreateBuffers - EXIT\n");
328dba5824bSPhil Greenway	return status;
329dba5824bSPhil Greenway}
330dba5824bSPhil Greenway
331dba5824bSPhil Greenway
332dba5824bSPhil Greenwayvoid
333dba5824bSPhil GreenwayVideoConsumer::DeleteBuffers()
334dba5824bSPhil Greenway{
335dba5824bSPhil Greenway	FUNCTION("VideoConsumer::DeleteBuffers\n");
3369d3f15c6SIngo Weinhold
3379d3f15c6SIngo Weinhold	if (fBuffers) {
3389d3f15c6SIngo Weinhold		delete fBuffers;
3399d3f15c6SIngo Weinhold		fBuffers = NULL;
3409d3f15c6SIngo Weinhold
341dba5824bSPhil Greenway		for (uint32 j = 0; j < 3; j++)
3429d3f15c6SIngo Weinhold			if (fBitmap[j]->IsValid()) {
3439d3f15c6SIngo Weinhold				delete fBitmap[j];
3449d3f15c6SIngo Weinhold				fBitmap[j] = NULL;
345dba5824bSPhil Greenway			}
346dba5824bSPhil Greenway	}
347dba5824bSPhil Greenway	FUNCTION("VideoConsumer::DeleteBuffers - EXIT\n");
348dba5824bSPhil Greenway}
349dba5824bSPhil Greenway
350dba5824bSPhil Greenway
351dba5824bSPhil Greenwaystatus_t
3529d3f15c6SIngo WeinholdVideoConsumer::Connected(const media_source& producer, const media_destination& where,
3539d3f15c6SIngo Weinhold	const media_format& withFormat, media_input* outInput)
354dba5824bSPhil Greenway{
355dba5824bSPhil Greenway	FUNCTION("VideoConsumer::Connected\n");
356dba5824bSPhil Greenway
3579d3f15c6SIngo Weinhold	fIn.source = producer;
3589d3f15c6SIngo Weinhold	fIn.format = withFormat;
3599d3f15c6SIngo Weinhold	fIn.node = Node();
3609d3f15c6SIngo Weinhold	sprintf(fIn.name, "Video Consumer");
3619d3f15c6SIngo Weinhold	*outInput = fIn;
3629d3f15c6SIngo Weinhold
3639d3f15c6SIngo Weinhold	uint32 userData = 0;
3649d3f15c6SIngo Weinhold	int32 changeTag = 1;
3659d3f15c6SIngo Weinhold	if (CreateBuffers(withFormat) == B_OK)
3669d3f15c6SIngo Weinhold		BBufferConsumer::SetOutputBuffersFor(producer, fDestination,
3679d3f15c6SIngo Weinhold			fBuffers, (void *)&userData, &changeTag, true);
3689d3f15c6SIngo Weinhold	else {
369dba5824bSPhil Greenway		ERROR("VideoConsumer::Connected - COULDN'T CREATE BUFFERS\n");
370dba5824bSPhil Greenway		return B_ERROR;
371dba5824bSPhil Greenway	}
372dba5824bSPhil Greenway
3739d3f15c6SIngo Weinhold	fConnectionActive = true;
3749d3f15c6SIngo Weinhold
375dba5824bSPhil Greenway	FUNCTION("VideoConsumer::Connected - EXIT\n");
376dba5824bSPhil Greenway	return B_OK;
377dba5824bSPhil Greenway}
378dba5824bSPhil Greenway
379dba5824bSPhil Greenway
380dba5824bSPhil Greenwayvoid
3819d3f15c6SIngo WeinholdVideoConsumer::Disconnected(const media_source& producer, const media_destination& where)
382dba5824bSPhil Greenway{
383dba5824bSPhil Greenway	FUNCTION("VideoConsumer::Disconnected\n");
384dba5824bSPhil Greenway
3859d3f15c6SIngo Weinhold	if (where == fIn.destination && producer == fIn.source) {
386dba5824bSPhil Greenway		// disconnect the connection
3879d3f15c6SIngo Weinhold		fIn.source = media_source::null;
3889d3f15c6SIngo Weinhold		delete fFtpBitmap;
3899d3f15c6SIngo Weinhold		fConnectionActive = false;
390dba5824bSPhil Greenway	}
391dba5824bSPhil Greenway
392dba5824bSPhil Greenway}
393dba5824bSPhil Greenway
394dba5824bSPhil Greenway
395dba5824bSPhil Greenwaystatus_t
3969d3f15c6SIngo WeinholdVideoConsumer::AcceptFormat(const media_destination& dest, media_format* format)
397dba5824bSPhil Greenway{
398dba5824bSPhil Greenway	FUNCTION("VideoConsumer::AcceptFormat\n");
399dba5824bSPhil Greenway
4009d3f15c6SIngo Weinhold	if (dest != fIn.destination) {
401dba5824bSPhil Greenway		ERROR("VideoConsumer::AcceptFormat - BAD DESTINATION\n");
402dba5824bSPhil Greenway		return B_MEDIA_BAD_DESTINATION;
403dba5824bSPhil Greenway	}
4049d3f15c6SIngo Weinhold
405dba5824bSPhil Greenway	if (format->type == B_MEDIA_NO_TYPE)
406dba5824bSPhil Greenway		format->type = B_MEDIA_RAW_VIDEO;
407dba5824bSPhil Greenway
4089d3f15c6SIngo Weinhold	if (format->type != B_MEDIA_RAW_VIDEO) {
409dba5824bSPhil Greenway		ERROR("VideoConsumer::AcceptFormat - BAD FORMAT\n");
410dba5824bSPhil Greenway		return B_MEDIA_BAD_FORMAT;
411dba5824bSPhil Greenway	}
412dba5824bSPhil Greenway
4139d3f15c6SIngo Weinhold	if (format->u.raw_video.display.format != B_RGB32
4149d3f15c6SIngo Weinhold		&& format->u.raw_video.display.format != B_RGB16
4159d3f15c6SIngo Weinhold		&& format->u.raw_video.display.format != B_RGB15
4169d3f15c6SIngo Weinhold		&& format->u.raw_video.display.format != B_GRAY8
4179d3f15c6SIngo Weinhold		&&
4189d3f15c6SIngo Weinhold		format->u.raw_video.display.format != media_raw_video_format::wildcard.display.format) {
419dba5824bSPhil Greenway		ERROR("AcceptFormat - not a format we know about!\n");
420dba5824bSPhil Greenway		return B_MEDIA_BAD_FORMAT;
421dba5824bSPhil Greenway	}
4229d3f15c6SIngo Weinhold
4239d3f15c6SIngo Weinhold	if (format->u.raw_video.display.format == media_raw_video_format::wildcard.display.format) {
424dba5824bSPhil Greenway		format->u.raw_video.display.format = B_RGB16;
425dba5824bSPhil Greenway	}
426dba5824bSPhil Greenway
4279d3f15c6SIngo Weinhold	char formatString[256];
4289d3f15c6SIngo Weinhold	string_for_format(*format, formatString, 256);
4299d3f15c6SIngo Weinhold	FUNCTION("VideoConsumer::AcceptFormat: %s\n", formatString);
430dba5824bSPhil Greenway
431dba5824bSPhil Greenway	return B_OK;
432dba5824bSPhil Greenway}
433dba5824bSPhil Greenway
434dba5824bSPhil Greenway
435dba5824bSPhil Greenwaystatus_t
4369d3f15c6SIngo WeinholdVideoConsumer::GetNextInput(int32* cookie, media_input* outInput)
437dba5824bSPhil Greenway{
438dba5824bSPhil Greenway	FUNCTION("VideoConsumer::GetNextInput\n");
439dba5824bSPhil Greenway
440dba5824bSPhil Greenway	// custom build a destination for this connection
441dba5824bSPhil Greenway	// put connection number in id
442dba5824bSPhil Greenway
4439d3f15c6SIngo Weinhold	if (*cookie < 1) {
4449d3f15c6SIngo Weinhold		fIn.node = Node();
4459d3f15c6SIngo Weinhold		fIn.destination.id = *cookie;
4469d3f15c6SIngo Weinhold		sprintf(fIn.name, "Video Consumer");
4479d3f15c6SIngo Weinhold		*outInput = fIn;
448dba5824bSPhil Greenway		(*cookie)++;
449dba5824bSPhil Greenway		return B_OK;
4509d3f15c6SIngo Weinhold	} else {
451dba5824bSPhil Greenway		ERROR("VideoConsumer::GetNextInput - - BAD INDEX\n");
452dba5824bSPhil Greenway		return B_MEDIA_BAD_DESTINATION;
453dba5824bSPhil Greenway	}
454dba5824bSPhil Greenway}
455dba5824bSPhil Greenway
456dba5824bSPhil Greenway
457dba5824bSPhil Greenwayvoid
458dba5824bSPhil GreenwayVideoConsumer::DisposeInputCookie(int32 /*cookie*/)
459dba5824bSPhil Greenway{
460dba5824bSPhil Greenway}
461dba5824bSPhil Greenway
462dba5824bSPhil Greenway
463dba5824bSPhil Greenwaystatus_t
4649d3f15c6SIngo WeinholdVideoConsumer::GetLatencyFor(const media_destination& forWhom, bigtime_t* outLatency,
4659d3f15c6SIngo Weinhold	media_node_id* out_timesource)
466dba5824bSPhil Greenway{
467dba5824bSPhil Greenway	FUNCTION("VideoConsumer::GetLatencyFor\n");
468dba5824bSPhil Greenway
4699d3f15c6SIngo Weinhold	if (forWhom != fIn.destination)
470dba5824bSPhil Greenway		return B_MEDIA_BAD_DESTINATION;
471dba5824bSPhil Greenway
4729d3f15c6SIngo Weinhold	*outLatency = fMyLatency;
473dba5824bSPhil Greenway	*out_timesource = TimeSource()->ID();
474dba5824bSPhil Greenway	return B_OK;
475dba5824bSPhil Greenway}
476dba5824bSPhil Greenway
477dba5824bSPhil Greenway
478dba5824bSPhil Greenwaystatus_t
4799d3f15c6SIngo WeinholdVideoConsumer::FormatChanged(const media_source& producer, const media_destination& consumer,
4809d3f15c6SIngo Weinhold	int32 fromChangeCount, const media_format& format)
481dba5824bSPhil Greenway{
482dba5824bSPhil Greenway	FUNCTION("VideoConsumer::FormatChanged\n");
4839d3f15c6SIngo Weinhold
4849d3f15c6SIngo Weinhold	if (consumer != fIn.destination)
485dba5824bSPhil Greenway		return B_MEDIA_BAD_DESTINATION;
486dba5824bSPhil Greenway
4879d3f15c6SIngo Weinhold	if (producer != fIn.source)
488dba5824bSPhil Greenway		return B_MEDIA_BAD_SOURCE;
489dba5824bSPhil Greenway
4909d3f15c6SIngo Weinhold	fIn.format = format;
4919d3f15c6SIngo Weinhold
492dba5824bSPhil Greenway	return CreateBuffers(format);
493dba5824bSPhil Greenway}
494dba5824bSPhil Greenway
495dba5824bSPhil Greenway
496dba5824bSPhil Greenwayvoid
4979d3f15c6SIngo WeinholdVideoConsumer::HandleEvent(const media_timed_event* event, bigtime_t lateness,
498dba5824bSPhil Greenway	bool realTimeEvent)
499dba5824bSPhil Greenway{
500dba5824bSPhil Greenway	LOOP("VideoConsumer::HandleEvent\n");
501dba5824bSPhil Greenway
5029d3f15c6SIngo Weinhold	BBuffer* buffer;
5039d3f15c6SIngo Weinhold
5049d3f15c6SIngo Weinhold	switch (event->type) {
505dba5824bSPhil Greenway		case BTimedEventQueue::B_START:
506dba5824bSPhil Greenway			PROGRESS("VideoConsumer::HandleEvent - START\n");
507dba5824bSPhil Greenway			break;
5089d3f15c6SIngo Weinhold
509dba5824bSPhil Greenway		case BTimedEventQueue::B_STOP:
510dba5824bSPhil Greenway			PROGRESS("VideoConsumer::HandleEvent - STOP\n");
5119d3f15c6SIngo Weinhold			EventQueue()->FlushEvents(event->event_time, BTimedEventQueue::B_ALWAYS,
5129d3f15c6SIngo Weinhold				true, BTimedEventQueue::B_HANDLE_BUFFER);
513dba5824bSPhil Greenway			break;
5149d3f15c6SIngo Weinhold
515dba5824bSPhil Greenway		case BTimedEventQueue::B_USER_EVENT:
516dba5824bSPhil Greenway			PROGRESS("VideoConsumer::HandleEvent - USER EVENT\n");
5179d3f15c6SIngo Weinhold			if (RunState() == B_STARTED) {
5189d3f15c6SIngo Weinhold				fTimeToFtp = true;
5199d3f15c6SIngo Weinhold				PROGRESS("Pushing user event for %.4f, time now %.4f\n",
5209d3f15c6SIngo Weinhold					(event->event_time + fRate) / M1, event->event_time/M1);
5219d3f15c6SIngo Weinhold				media_timed_event newEvent(event->event_time + fRate,
5229d3f15c6SIngo Weinhold					BTimedEventQueue::B_USER_EVENT);
523dba5824bSPhil Greenway				EventQueue()->AddEvent(newEvent);
524dba5824bSPhil Greenway			}
5259d3f15c6SIngo Weinhold			break;
5269d3f15c6SIngo Weinhold
527dba5824bSPhil Greenway		case BTimedEventQueue::B_HANDLE_BUFFER:
5289d3f15c6SIngo Weinhold		{
529dba5824bSPhil Greenway			LOOP("VideoConsumer::HandleEvent - HANDLE BUFFER\n");
5309d3f15c6SIngo Weinhold			buffer = (BBuffer *)event->pointer;
5319d3f15c6SIngo Weinhold			if (RunState() == B_STARTED && fConnectionActive) {
532dba5824bSPhil Greenway				// see if this is one of our buffers
533dba5824bSPhil Greenway				uint32 index = 0;
5349d3f15c6SIngo Weinhold				fOurBuffers = true;
5359d3f15c6SIngo Weinhold				while (index < 3)
5369d3f15c6SIngo Weinhold					if ((uint32)buffer == fBufferMap[index])
537dba5824bSPhil Greenway						break;
538dba5824bSPhil Greenway					else
539dba5824bSPhil Greenway						index++;
5409d3f15c6SIngo Weinhold
5419d3f15c6SIngo Weinhold				if (index == 3) {
542dba5824bSPhil Greenway					// no, buffers belong to consumer
5439d3f15c6SIngo Weinhold					fOurBuffers = false;
544dba5824bSPhil Greenway					index = 0;
545dba5824bSPhil Greenway				}
5469d3f15c6SIngo Weinhold
5479d3f15c6SIngo Weinhold				if (fFtpComplete && fTimeToFtp) {
548dba5824bSPhil Greenway					PROGRESS("VidConsumer::HandleEvent - SPAWNING FTP THREAD\n");
5499d3f15c6SIngo Weinhold					fTimeToFtp = false;
5509d3f15c6SIngo Weinhold					fFtpComplete = false;
5519d3f15c6SIngo Weinhold					memcpy(fFtpBitmap->Bits(), buffer->Data(), fFtpBitmap->BitsLength());
5529d3f15c6SIngo Weinhold					fFtpThread = spawn_thread(FtpRun, "Video Window Ftp", B_NORMAL_PRIORITY, this);
5539d3f15c6SIngo Weinhold					resume_thread(fFtpThread);
554dba5824bSPhil Greenway				}
555dba5824bSPhil Greenway
5569d3f15c6SIngo Weinhold				if ((RunMode() == B_OFFLINE)
5579d3f15c6SIngo Weinhold					|| ((TimeSource()->Now() > (buffer->Header()->start_time - JITTER))
5589d3f15c6SIngo Weinhold						&& (TimeSource()->Now() < (buffer->Header()->start_time + JITTER)))) {
5599d3f15c6SIngo Weinhold					if (!fOurBuffers)
560dba5824bSPhil Greenway						// not our buffers, so we need to copy
5619d3f15c6SIngo Weinhold						memcpy(fBitmap[index]->Bits(), buffer->Data(), fBitmap[index]->BitsLength());
5629d3f15c6SIngo Weinhold
5639d3f15c6SIngo Weinhold					if (fWindow->Lock()) {
564dba5824bSPhil Greenway						uint32 flags;
5659d3f15c6SIngo Weinhold						if ((fBitmap[index]->ColorSpace() == B_GRAY8) &&
5669d3f15c6SIngo Weinhold							!bitmaps_support_space(fBitmap[index]->ColorSpace(), &flags)) {
567dba5824bSPhil Greenway							// handle mapping of GRAY8 until app server knows how
5689d3f15c6SIngo Weinhold							uint32* start = (uint32*)fBitmap[index]->Bits();
5699d3f15c6SIngo Weinhold							int32 size = fBitmap[index]->BitsLength();
5709d3f15c6SIngo Weinhold							uint32* end = start + size / 4;
5719d3f15c6SIngo Weinhold							for (uint32* p = start; p < end; p++)
572dba5824bSPhil Greenway								*p = (*p >> 3) & 0x1f1f1f1f;
573dba5824bSPhil Greenway						}
5749d3f15c6SIngo Weinhold
57545c2e6b8SFrançois Revol						fView->DrawBitmap(fBitmap[index], fView->Bounds());
5769d3f15c6SIngo Weinhold						fWindow->Unlock();
577dba5824bSPhil Greenway					}
578dba5824bSPhil Greenway				}
579dba5824bSPhil Greenway				else
580dba5824bSPhil Greenway					PROGRESS("VidConsumer::HandleEvent - DROPPED FRAME\n");
581dba5824bSPhil Greenway				buffer->Recycle();
582dba5824bSPhil Greenway			}
583dba5824bSPhil Greenway			else
584dba5824bSPhil Greenway				buffer->Recycle();
585dba5824bSPhil Greenway			break;
5869d3f15c6SIngo Weinhold		}
5879d3f15c6SIngo Weinhold
588dba5824bSPhil Greenway		default:
589dba5824bSPhil Greenway			ERROR("VideoConsumer::HandleEvent - BAD EVENT\n");
590dba5824bSPhil Greenway			break;
591dba5824bSPhil Greenway	}
592dba5824bSPhil Greenway}
593dba5824bSPhil Greenway
594dba5824bSPhil Greenway
595dba5824bSPhil Greenwaystatus_t
5969d3f15c6SIngo WeinholdVideoConsumer::FtpRun(void* data)
597dba5824bSPhil Greenway{
598dba5824bSPhil Greenway	FUNCTION("VideoConsumer::FtpRun\n");
599dba5824bSPhil Greenway
600dba5824bSPhil Greenway	((VideoConsumer *)data)->FtpThread();
601dba5824bSPhil Greenway
602dba5824bSPhil Greenway	return 0;
603dba5824bSPhil Greenway}
604dba5824bSPhil Greenway
605dba5824bSPhil Greenway
606dba5824bSPhil Greenwayvoid
607dba5824bSPhil GreenwayVideoConsumer::FtpThread()
608dba5824bSPhil Greenway{
609dba5824bSPhil Greenway	FUNCTION("VideoConsumer::FtpThread\n");
610dba5824bSPhil Greenway
6119d3f15c6SIngo Weinhold	if (LocalSave(fFileNameText, fFtpBitmap) == B_OK)
6129d3f15c6SIngo Weinhold		FtpSave(fFileNameText);
6139d3f15c6SIngo Weinhold
614dba5824bSPhil Greenway#if 0
615dba5824bSPhil Greenway	// save a small version, too
6169d3f15c6SIngo Weinhold	BBitmap* b = new BBitmap(BRect(0,0,159,119), B_RGB32, true, false);
6179d3f15c6SIngo Weinhold	BView* v = new BView(BRect(0,0,159,119), "SmallView 1", 0, B_WILL_DRAW);
618dba5824bSPhil Greenway	b->AddChild(v);
619dba5824bSPhil Greenway
620dba5824bSPhil Greenway	b->Lock();
6219d3f15c6SIngo Weinhold	v->DrawBitmap(fFtpBitmap, v->Frame());
622dba5824bSPhil Greenway	v->Sync();
623dba5824bSPhil Greenway	b->Unlock();
624dba5824bSPhil Greenway
625dba5824bSPhil Greenway	if (LocalSave("small.jpg", b) == B_OK)
626dba5824bSPhil Greenway		FtpSave("small.jpg");
627dba5824bSPhil Greenway
628dba5824bSPhil Greenway	delete b;
629dba5824bSPhil Greenway#endif
630dba5824bSPhil Greenway
6319d3f15c6SIngo Weinhold	fFtpComplete = true;
632dba5824bSPhil Greenway}
633dba5824bSPhil Greenway
634dba5824bSPhil Greenway
635dba5824bSPhil Greenwayvoid
6369d3f15c6SIngo WeinholdVideoConsumer::UpdateFtpStatus(char* status)
637dba5824bSPhil Greenway{
638dba5824bSPhil Greenway	printf("FTP STATUS: %s\n",status);
6399d3f15c6SIngo Weinhold	if (fView->Window()->Lock()) {
6409d3f15c6SIngo Weinhold		fStatusLine->SetText(status);
6419d3f15c6SIngo Weinhold		fView->Window()->Unlock();
642dba5824bSPhil Greenway	}
643dba5824bSPhil Greenway}
644dba5824bSPhil Greenway
645dba5824bSPhil Greenway
646dba5824bSPhil Greenwaystatus_t
6479d3f15c6SIngo WeinholdVideoConsumer::LocalSave(char* filename, BBitmap* bitmap)
648dba5824bSPhil Greenway{
6499d3f15c6SIngo Weinhold	BFile* output;
6509d3f15c6SIngo Weinhold
651c9d15f8cSStephan Aßmus	UpdateFtpStatus("Capturing Image" B_UTF8_ELLIPSIS);
652dba5824bSPhil Greenway
653dba5824bSPhil Greenway	/* save a local copy of the image in the requested format */
6549d3f15c6SIngo Weinhold	output = new BFile();
6559d3f15c6SIngo Weinhold	if (output->SetTo(filename, B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE) == B_NO_ERROR) {
656dba5824bSPhil Greenway		BBitmapStream input(bitmap);
6579d3f15c6SIngo Weinhold		status_t err = BTranslatorRoster::Default()->Translate(&input, NULL, NULL,
6589d3f15c6SIngo Weinhold        	output, fImageFormat);
6599d3f15c6SIngo Weinhold        if (err == B_OK) {
6609d3f15c6SIngo Weinhold        	err = SetFileType(output, fTranslator, fImageFormat);
661dba5824bSPhil Greenway        	if (err != B_OK)
662dba5824bSPhil Greenway        		UpdateFtpStatus("Error setting type of output file");
663dba5824bSPhil Greenway        }
664dba5824bSPhil Greenway        else
665dba5824bSPhil Greenway        	UpdateFtpStatus("Error writing output file");
6669d3f15c6SIngo Weinhold
6679d3f15c6SIngo Weinhold		input.DetachBitmap(&bitmap);
6689d3f15c6SIngo Weinhold		output->Unset();
6699d3f15c6SIngo Weinhold		delete output;
6709d3f15c6SIngo Weinhold		return B_OK;
6719d3f15c6SIngo Weinhold    } else {
672dba5824bSPhil Greenway		UpdateFtpStatus("Error creating output file");
673dba5824bSPhil Greenway    	return B_ERROR;
674dba5824bSPhil Greenway    }
675dba5824bSPhil Greenway}
676dba5824bSPhil Greenway
677dba5824bSPhil Greenway
678dba5824bSPhil Greenwaystatus_t
6799d3f15c6SIngo WeinholdVideoConsumer::FtpSave(char* filename)
680dba5824bSPhil Greenway{
681e3145a8dSFrançois Revol	FileUploadClient *ftp;
682e3145a8dSFrançois Revol
683e3145a8dSFrançois Revol	//XXX: make that cleaner
684e3145a8dSFrançois Revol	switch (fUploadClient) {
685e3145a8dSFrançois Revol		case 0:
686e3145a8dSFrançois Revol			ftp = new FtpClient;
687e3145a8dSFrançois Revol			break;
688e3145a8dSFrançois Revol		case 1:
689e3145a8dSFrançois Revol			ftp = new SftpClient;
690e3145a8dSFrançois Revol			break;
691e3145a8dSFrançois Revol		default:
692629e25efSJérôme Duval			fprintf(stderr, "invalid upload client %ld\n", fUploadClient);
693e3145a8dSFrançois Revol			return EINVAL;
694e3145a8dSFrançois Revol	}
6959d3f15c6SIngo Weinhold
696e3145a8dSFrançois Revol	ftp->SetPassive(fPassiveFtp);
6979d3f15c6SIngo Weinhold		// ftp the local file to our web site
698dba5824bSPhil Greenway
699c9d15f8cSStephan Aßmus	UpdateFtpStatus("Logging in" B_UTF8_ELLIPSIS);
700e3145a8dSFrançois Revol	if (ftp->Connect((string)fServerText, (string)fLoginText, (string)fPasswordText)) {
7019d3f15c6SIngo Weinhold		// connect to server
702c9d15f8cSStephan Aßmus		UpdateFtpStatus("Connected" B_UTF8_ELLIPSIS);
7039d3f15c6SIngo Weinhold
704e3145a8dSFrançois Revol		if (ftp->ChangeDir((string)fDirectoryText)) {
7059d3f15c6SIngo Weinhold			// cd to the desired directory
706c9d15f8cSStephan Aßmus			UpdateFtpStatus("Transmitting" B_UTF8_ELLIPSIS);
7079d3f15c6SIngo Weinhold
708e3145a8dSFrançois Revol			if (ftp->PutFile((string)filename, (string)"temp")) {
7099d3f15c6SIngo Weinhold				// send the file to the server
7106298fd45SFrançois Revol
71161946f58SFrançois Revol				ftp->Chmod((string)"temp", (string)"644");
7126298fd45SFrançois Revol				// make it world readable
7136298fd45SFrançois Revol
714c9d15f8cSStephan Aßmus				UpdateFtpStatus("Renaming" B_UTF8_ELLIPSIS);
7159d3f15c6SIngo Weinhold
716e3145a8dSFrançois Revol				if (ftp->MoveFile((string)"temp", (string)filename)) {
7179d3f15c6SIngo Weinhold					// change to the desired name
718dba5824bSPhil Greenway					uint32 time = real_time_clock();
719dba5824bSPhil Greenway					char s[80];
7209d3f15c6SIngo Weinhold					strcpy(s, "Last Capture: ");
7219d3f15c6SIngo Weinhold					strcat(s, ctime((const long*)&time));
7229d3f15c6SIngo Weinhold					s[strlen(s) - 1] = 0;
723dba5824bSPhil Greenway					UpdateFtpStatus(s);
724e3145a8dSFrançois Revol					delete ftp;
725dba5824bSPhil Greenway					return B_OK;
7269d3f15c6SIngo Weinhold				}
7279d3f15c6SIngo Weinhold				else
7289d3f15c6SIngo Weinhold					UpdateFtpStatus("Rename failed");
7299d3f15c6SIngo Weinhold			}
7309d3f15c6SIngo Weinhold			else
7319d3f15c6SIngo Weinhold				UpdateFtpStatus("File transmission failed");
7329d3f15c6SIngo Weinhold		}
7339d3f15c6SIngo Weinhold		else
7349d3f15c6SIngo Weinhold			UpdateFtpStatus("Couldn't find requested directory on server");
7359d3f15c6SIngo Weinhold	}
7369d3f15c6SIngo Weinhold	else
7379d3f15c6SIngo Weinhold		UpdateFtpStatus("Server login failed");
7389d3f15c6SIngo Weinhold
739e3145a8dSFrançois Revol	delete ftp;
740dba5824bSPhil Greenway	return B_ERROR;
741dba5824bSPhil Greenway}
742dba5824bSPhil Greenway
743dba5824bSPhil Greenway
744dba5824bSPhil Greenwaystatus_t
7459d3f15c6SIngo WeinholdSetFileType(BFile* file, int32 translator, uint32 type)
746dba5824bSPhil Greenway{
7479d3f15c6SIngo Weinhold	translation_format* formats;
7489d3f15c6SIngo Weinhold	int32 count;
7499d3f15c6SIngo Weinhold
7509d3f15c6SIngo Weinhold	status_t err = BTranslatorRoster::Default()->GetOutputFormats(translator,
7519d3f15c6SIngo Weinhold		(const translation_format **)&formats, &count);
7529d3f15c6SIngo Weinhold	if (err < B_OK)
7539d3f15c6SIngo Weinhold		return err;
7549d3f15c6SIngo Weinhold
7559d3f15c6SIngo Weinhold	const char* mime = NULL;
7569d3f15c6SIngo Weinhold	for (int ix = 0; ix < count; ix++) {
7579d3f15c6SIngo Weinhold		if (formats[ix].type == type) {
7589d3f15c6SIngo Weinhold			mime = formats[ix].MIME;
7599d3f15c6SIngo Weinhold			break;
7609d3f15c6SIngo Weinhold		}
7619d3f15c6SIngo Weinhold	}
762dba5824bSPhil Greenway
7639d3f15c6SIngo Weinhold	if (mime == NULL) {
7649d3f15c6SIngo Weinhold		/* this should not happen, but being defensive might be prudent */
7659d3f15c6SIngo Weinhold		return B_ERROR;
7669d3f15c6SIngo Weinhold	}
767dba5824bSPhil Greenway
7689d3f15c6SIngo Weinhold	/* use BNodeInfo to set the file type */
7699d3f15c6SIngo Weinhold	BNodeInfo ninfo(file);
7709d3f15c6SIngo Weinhold	return ninfo.SetType(mime);
7719d3f15c6SIngo Weinhold}
772