VideoConsumer.cpp revision a8aeb8a9
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>
19c4f9b1d1SStephan Aßmus#include <Catalog.h>
20c4f9b1d1SStephan Aßmus#include <Locale.h>
219d3f15c6SIngo Weinhold#include <MediaRoster.h>
22dba5824bSPhil Greenway#include <NodeInfo.h>
23dba5824bSPhil Greenway#include <scheduler.h>
24dba5824bSPhil Greenway#include <StringView.h>
259d3f15c6SIngo Weinhold#include <TimeSource.h>
269d3f15c6SIngo Weinhold#include <View.h>
27dba5824bSPhil Greenway
28dba5824bSPhil Greenway
29546208a5SOliver Tappe#undef B_TRANSLATION_CONTEXT
30546208a5SOliver Tappe#define B_TRANSLATION_CONTEXT "VideoConsumer.cpp"
31c4f9b1d1SStephan Aßmus
32dba5824bSPhil Greenway#define M1 ((double)1000000.0)
33dba5824bSPhil Greenway#define JITTER		20000
34dba5824bSPhil Greenway
35dba5824bSPhil Greenway#define	FUNCTION	printf
36dba5824bSPhil Greenway#define ERROR		printf
37dba5824bSPhil Greenway#define PROGRESS	printf
38dba5824bSPhil Greenway#define LOOP		printf
39dba5824bSPhil Greenway
40c4f9b1d1SStephan Aßmus
419d3f15c6SIngo Weinholdstatic status_t SetFileType(BFile* file,  int32 translator, uint32 type);
429d3f15c6SIngo Weinhold
43c4f9b1d1SStephan Aßmusconst media_raw_video_format vid_format = {29.97, 1, 0, 239,
44c4f9b1d1SStephan Aßmus	B_VIDEO_TOP_LEFT_RIGHT, 1, 1, {B_RGB16, 320, 240, 320 * 4, 0, 0}};
459d3f15c6SIngo Weinhold
469d3f15c6SIngo Weinhold
47476fad7fSMatt MadiaVideoConsumer::VideoConsumer(const char* name, BView* view,
48c4f9b1d1SStephan Aßmus	BStringView* statusLine,
499d3f15c6SIngo Weinhold	BMediaAddOn* addon, const uint32 internalId)
50476fad7fSMatt Madia	: BMediaNode(name),
51476fad7fSMatt Madia	BMediaEventLooper(),
52c4f9b1d1SStephan Aßmus	BBufferConsumer(B_MEDIA_RAW_VIDEO),
539d3f15c6SIngo Weinhold	fStatusLine(statusLine),
549d3f15c6SIngo Weinhold	fInternalID(internalId),
559d3f15c6SIngo Weinhold	fAddOn(addon),
569d3f15c6SIngo Weinhold	fConnectionActive(false),
579d3f15c6SIngo Weinhold	fMyLatency(20000),
589d3f15c6SIngo Weinhold	fWindow(NULL),
599d3f15c6SIngo Weinhold	fView(view),
609d3f15c6SIngo Weinhold	fOurBuffers(false),
619d3f15c6SIngo Weinhold	fBuffers(NULL),
629d3f15c6SIngo Weinhold	fTimeToFtp(false),
639d3f15c6SIngo Weinhold	fFtpComplete(true),
649d3f15c6SIngo Weinhold	fRate(1000000),
659d3f15c6SIngo Weinhold	fImageFormat(0),
669d3f15c6SIngo Weinhold	fTranslator(0),
67e3145a8dSFrançois Revol	fUploadClient(0),
689d3f15c6SIngo Weinhold	fPassiveFtp(true)
69dba5824bSPhil Greenway{
70dba5824bSPhil Greenway	FUNCTION("VideoConsumer::VideoConsumer\n");
71dba5824bSPhil Greenway
72dba5824bSPhil Greenway	AddNodeKind(B_PHYSICAL_OUTPUT);
73dba5824bSPhil Greenway	SetEventLatency(0);
749d3f15c6SIngo Weinhold	fWindow = fView->Window();
75476fad7fSMatt Madia
769d3f15c6SIngo Weinhold	for (uint32 j = 0; j < 3; j++) {
779d3f15c6SIngo Weinhold		fBitmap[j] = NULL;
789d3f15c6SIngo Weinhold		fBufferMap[j] = 0;
79dba5824bSPhil Greenway	}
809d3f15c6SIngo Weinhold
819d3f15c6SIngo Weinhold	strcpy(fFileNameText, "");
829d3f15c6SIngo Weinhold	strcpy(fServerText, "");
839d3f15c6SIngo Weinhold	strcpy(fLoginText, "");
849d3f15c6SIngo Weinhold	strcpy(fPasswordText, "");
859d3f15c6SIngo Weinhold	strcpy(fDirectoryText, "");
86dba5824bSPhil Greenway
87dba5824bSPhil Greenway	SetPriority(B_DISPLAY_PRIORITY);
88dba5824bSPhil Greenway}
89dba5824bSPhil Greenway
90dba5824bSPhil Greenway
91dba5824bSPhil GreenwayVideoConsumer::~VideoConsumer()
92dba5824bSPhil Greenway{
93dba5824bSPhil Greenway	FUNCTION("VideoConsumer::~VideoConsumer\n");
94476fad7fSMatt Madia
95dba5824bSPhil Greenway	Quit();
96dba5824bSPhil Greenway
979d3f15c6SIngo Weinhold	if (fWindow) {
98c4f9b1d1SStephan Aßmus		printf(B_TRANSLATE("Locking the window\n"));
999d3f15c6SIngo Weinhold		if (fWindow->Lock()) {
100c4f9b1d1SStephan Aßmus			printf(B_TRANSLATE("Closing the window\n"));
1019d3f15c6SIngo Weinhold			fWindow->Close();
1029d3f15c6SIngo Weinhold			fWindow = 0;
103dba5824bSPhil Greenway		}
104dba5824bSPhil Greenway	}
105dba5824bSPhil Greenway
106dba5824bSPhil Greenway	// clean up ftp thread
107dba5824bSPhil Greenway	// wait up to 30 seconds if ftp is in progress
108dba5824bSPhil Greenway	int32 count = 0;
1099d3f15c6SIngo Weinhold	while (!fFtpComplete && count < 30) {
110dba5824bSPhil Greenway		snooze(1000000);
111dba5824bSPhil Greenway		count++;
112dba5824bSPhil Greenway	}
113476fad7fSMatt Madia
114476fad7fSMatt Madia	if (count == 30)
1159d3f15c6SIngo Weinhold		kill_thread(fFtpThread);
116476fad7fSMatt Madia
117dba5824bSPhil Greenway	DeleteBuffers();
118476fad7fSMatt Madia
119dba5824bSPhil Greenway}
120dba5824bSPhil Greenway
121dba5824bSPhil Greenway/********************************
122dba5824bSPhil Greenway	From BMediaNode
123dba5824bSPhil Greenway********************************/
124dba5824bSPhil Greenway
125dba5824bSPhil Greenway
1269d3f15c6SIngo WeinholdBMediaAddOn*
127afcbccb9SJérôme DuvalVideoConsumer::AddOn(int32* cookie) const
128dba5824bSPhil Greenway{
129dba5824bSPhil Greenway	FUNCTION("VideoConsumer::AddOn\n");
130dba5824bSPhil Greenway	// do the right thing if we're ever used with an add-on
1319d3f15c6SIngo Weinhold	*cookie = fInternalID;
1329d3f15c6SIngo Weinhold	return fAddOn;
133dba5824bSPhil Greenway}
134dba5824bSPhil Greenway
135dba5824bSPhil Greenway
136dba5824bSPhil Greenway// This implementation is required to get around a bug in
137dba5824bSPhil Greenway// the ppc compiler.
138dba5824bSPhil Greenway
139476fad7fSMatt Madiavoid
1409d3f15c6SIngo WeinholdVideoConsumer::Start(bigtime_t performanceTime)
141dba5824bSPhil Greenway{
1429d3f15c6SIngo Weinhold	BMediaEventLooper::Start(performanceTime);
143dba5824bSPhil Greenway}
144dba5824bSPhil Greenway
1459d3f15c6SIngo Weinhold
146476fad7fSMatt Madiavoid
1479d3f15c6SIngo WeinholdVideoConsumer::Stop(bigtime_t performanceTime, bool immediate)
148dba5824bSPhil Greenway{
1499d3f15c6SIngo Weinhold	BMediaEventLooper::Stop(performanceTime, immediate);
150dba5824bSPhil Greenway}
151dba5824bSPhil Greenway
1529d3f15c6SIngo Weinhold
153476fad7fSMatt Madiavoid
1549d3f15c6SIngo WeinholdVideoConsumer::Seek(bigtime_t mediaTime, bigtime_t performanceTime)
155dba5824bSPhil Greenway{
1569d3f15c6SIngo Weinhold	BMediaEventLooper::Seek(mediaTime, performanceTime);
157dba5824bSPhil Greenway}
158dba5824bSPhil Greenway
1599d3f15c6SIngo Weinhold
160476fad7fSMatt Madiavoid
1619d3f15c6SIngo WeinholdVideoConsumer::TimeWarp(bigtime_t atRealTime, bigtime_t toPerformanceTime)
162dba5824bSPhil Greenway{
1639d3f15c6SIngo Weinhold	BMediaEventLooper::TimeWarp(atRealTime, toPerformanceTime);
164dba5824bSPhil Greenway}
165dba5824bSPhil Greenway
1669d3f15c6SIngo Weinhold
167476fad7fSMatt Madiastatus_t
1689d3f15c6SIngo WeinholdVideoConsumer::DeleteHook(BMediaNode* node)
169dba5824bSPhil Greenway{
170dba5824bSPhil Greenway	return BMediaEventLooper::DeleteHook(node);
171dba5824bSPhil Greenway}
172dba5824bSPhil Greenway
173dba5824bSPhil Greenway
174dba5824bSPhil Greenwayvoid
175dba5824bSPhil GreenwayVideoConsumer::NodeRegistered()
176dba5824bSPhil Greenway{
177dba5824bSPhil Greenway	FUNCTION("VideoConsumer::NodeRegistered\n");
1789d3f15c6SIngo Weinhold	fIn.destination.port = ControlPort();
1799d3f15c6SIngo Weinhold	fIn.destination.id = 0;
1809d3f15c6SIngo Weinhold	fIn.source = media_source::null;
1819d3f15c6SIngo Weinhold	fIn.format.type = B_MEDIA_RAW_VIDEO;
1829d3f15c6SIngo Weinhold	fIn.format.u.raw_video = vid_format;
183dba5824bSPhil Greenway
184dba5824bSPhil Greenway	Run();
185dba5824bSPhil Greenway}
186dba5824bSPhil Greenway
187dba5824bSPhil Greenway
188dba5824bSPhil Greenwaystatus_t
1899d3f15c6SIngo WeinholdVideoConsumer::RequestCompleted(const media_request_info& info)
190dba5824bSPhil Greenway{
191dba5824bSPhil Greenway	FUNCTION("VideoConsumer::RequestCompleted\n");
1929d3f15c6SIngo Weinhold	switch (info.what) {
193dba5824bSPhil Greenway		case media_request_info::B_SET_OUTPUT_BUFFERS_FOR:
1949d3f15c6SIngo Weinhold			if (info.status != B_OK)
195dba5824bSPhil Greenway					ERROR("VideoConsumer::RequestCompleted: Not using our buffers!\n");
196dba5824bSPhil Greenway			break;
1979d3f15c6SIngo Weinhold
198859c1f01SNiels Sascha Reedijk		default:
199859c1f01SNiels Sascha Reedijk			ERROR("VideoConsumer::RequestCompleted: Invalid argument\n");
200859c1f01SNiels Sascha Reedijk			break;
201dba5824bSPhil Greenway	}
202dba5824bSPhil Greenway	return B_OK;
203dba5824bSPhil Greenway}
204dba5824bSPhil Greenway
205dba5824bSPhil Greenway
206dba5824bSPhil Greenwaystatus_t
2079d3f15c6SIngo WeinholdVideoConsumer::HandleMessage(int32 message, const void* data, size_t size)
208dba5824bSPhil Greenway{
209dba5824bSPhil Greenway	//FUNCTION("VideoConsumer::HandleMessage\n");
2109d3f15c6SIngo Weinhold	ftp_msg_info* info = (ftp_msg_info*)data;
211dba5824bSPhil Greenway	status_t status = B_OK;
2129d3f15c6SIngo Weinhold
2139d3f15c6SIngo Weinhold	switch (message) {
214dba5824bSPhil Greenway		case FTP_INFO:
215dba5824bSPhil Greenway			PROGRESS("VideoConsumer::HandleMessage - FTP_INFO message\n");
2169d3f15c6SIngo Weinhold			fRate = info->rate;
2179d3f15c6SIngo Weinhold			fImageFormat = info->imageFormat;
2189d3f15c6SIngo Weinhold			fTranslator = info->translator;
2199d3f15c6SIngo Weinhold			fPassiveFtp = info->passiveFtp;
220e3145a8dSFrançois Revol			fUploadClient = info->uploadClient;
2219d3f15c6SIngo Weinhold			strcpy(fFileNameText, info->fileNameText);
2229d3f15c6SIngo Weinhold			strcpy(fServerText, info->serverText);
2239d3f15c6SIngo Weinhold			strcpy(fLoginText, info->loginText);
2249d3f15c6SIngo Weinhold			strcpy(fPasswordText, info->passwordText);
2259d3f15c6SIngo Weinhold			strcpy(fDirectoryText, info->directoryText);
226dba5824bSPhil Greenway			// remove old user events
2279d3f15c6SIngo Weinhold			EventQueue()->FlushEvents(TimeSource()->Now(), BTimedEventQueue::B_ALWAYS,
2289d3f15c6SIngo Weinhold				true, BTimedEventQueue::B_USER_EVENT);
2299d3f15c6SIngo Weinhold			if (fRate != B_INFINITE_TIMEOUT) {
2309d3f15c6SIngo Weinhold				// if rate is not "Never," push an event
2319d3f15c6SIngo Weinhold				// to restart captures 5 seconds from now
2329d3f15c6SIngo Weinhold				media_timed_event event(TimeSource()->Now() + 5000000,
2339d3f15c6SIngo Weinhold					BTimedEventQueue::B_USER_EVENT);
234dba5824bSPhil Greenway				EventQueue()->AddEvent(event);
235dba5824bSPhil Greenway			}
236dba5824bSPhil Greenway			break;
237dba5824bSPhil Greenway	}
238476fad7fSMatt Madia
239dba5824bSPhil Greenway	return status;
240dba5824bSPhil Greenway}
241dba5824bSPhil Greenway
242dba5824bSPhil Greenway
243dba5824bSPhil Greenwayvoid
2449d3f15c6SIngo WeinholdVideoConsumer::BufferReceived(BBuffer* buffer)
245dba5824bSPhil Greenway{
246afcbccb9SJérôme Duval	LOOP("VideoConsumer::Buffer #%" B_PRId32 " received, start_time %" B_PRIdBIGTIME
247afcbccb9SJérôme Duval		"\n", buffer->ID(), buffer->Header()->start_time);
248dba5824bSPhil Greenway
2499d3f15c6SIngo Weinhold	if (RunState() == B_STOPPED) {
250dba5824bSPhil Greenway		buffer->Recycle();
251dba5824bSPhil Greenway		return;
252dba5824bSPhil Greenway	}
253dba5824bSPhil Greenway
254dba5824bSPhil Greenway	media_timed_event event(buffer->Header()->start_time, BTimedEventQueue::B_HANDLE_BUFFER,
2559d3f15c6SIngo Weinhold		buffer, BTimedEventQueue::B_RECYCLE_BUFFER);
256dba5824bSPhil Greenway	EventQueue()->AddEvent(event);
257dba5824bSPhil Greenway}
258dba5824bSPhil Greenway
259dba5824bSPhil Greenway
260dba5824bSPhil Greenwayvoid
2619d3f15c6SIngo WeinholdVideoConsumer::ProducerDataStatus(const media_destination& forWhom, int32 status,
2629d3f15c6SIngo Weinhold	bigtime_t atMediaTime)
263dba5824bSPhil Greenway{
264dba5824bSPhil Greenway	FUNCTION("VideoConsumer::ProducerDataStatus\n");
265dba5824bSPhil Greenway
266476fad7fSMatt Madia	if (forWhom != fIn.destination)
267dba5824bSPhil Greenway		return;
268dba5824bSPhil Greenway}
269dba5824bSPhil Greenway
270dba5824bSPhil Greenway
271dba5824bSPhil Greenwaystatus_t
2729d3f15c6SIngo WeinholdVideoConsumer::CreateBuffers(const media_format& withFormat)
273dba5824bSPhil Greenway{
274dba5824bSPhil Greenway	FUNCTION("VideoConsumer::CreateBuffers\n");
2759d3f15c6SIngo Weinhold
276476fad7fSMatt Madia	DeleteBuffers();
2779d3f15c6SIngo Weinhold		// delete any old buffers
278dba5824bSPhil Greenway
279dba5824bSPhil Greenway	status_t status = B_OK;
280dba5824bSPhil Greenway
281dba5824bSPhil Greenway	// create a buffer group
2829d3f15c6SIngo Weinhold	uint32 xSize = withFormat.u.raw_video.display.line_width;
283476fad7fSMatt Madia	uint32 ySize = withFormat.u.raw_video.display.line_count;
2849d3f15c6SIngo Weinhold	color_space colorspace = withFormat.u.raw_video.display.format;
2859d3f15c6SIngo Weinhold	PROGRESS("VideoConsumer::CreateBuffers - Colorspace = %d\n", colorspace);
2869d3f15c6SIngo Weinhold
2879d3f15c6SIngo Weinhold	fBuffers = new BBufferGroup();
2889d3f15c6SIngo Weinhold	status = fBuffers->InitCheck();
2899d3f15c6SIngo Weinhold	if (status != B_OK) {
290dba5824bSPhil Greenway		ERROR("VideoConsumer::CreateBuffers - ERROR CREATING BUFFER GROUP\n");
291dba5824bSPhil Greenway		return status;
292dba5824bSPhil Greenway	}
293dba5824bSPhil Greenway	// and attach the  bitmaps to the buffer group
2949d3f15c6SIngo Weinhold	for (uint32 j = 0; j < 3; j++) {
2959d3f15c6SIngo Weinhold		fBitmap[j] = new BBitmap(BRect(0, 0, (xSize - 1), (ySize - 1)), colorspace,
2969d3f15c6SIngo Weinhold			false, true);
297476fad7fSMatt Madia		if (fBitmap[j]->IsValid()) {
298dba5824bSPhil Greenway			buffer_clone_info info;
2999d3f15c6SIngo Weinhold			if ((info.area = area_for(fBitmap[j]->Bits())) == B_ERROR)
3009d3f15c6SIngo Weinhold				ERROR("VideoConsumer::CreateBuffers - ERROR IN AREA_FOR\n");
301dba5824bSPhil Greenway			info.offset = 0;
3029d3f15c6SIngo Weinhold			info.size = (size_t)fBitmap[j]->BitsLength();
303dba5824bSPhil Greenway			info.flags = j;
304dba5824bSPhil Greenway			info.buffer = 0;
305dba5824bSPhil Greenway
3069d3f15c6SIngo Weinhold			if ((status = fBuffers->AddBuffer(info)) != B_OK) {
307dba5824bSPhil Greenway				ERROR("VideoConsumer::CreateBuffers - ERROR ADDING BUFFER TO GROUP\n");
308dba5824bSPhil Greenway				return status;
3099d3f15c6SIngo Weinhold			}
3109d3f15c6SIngo Weinhold			else
3119d3f15c6SIngo Weinhold				PROGRESS("VideoConsumer::CreateBuffers - SUCCESSFUL ADD BUFFER TO GROUP\n");
3129d3f15c6SIngo Weinhold		} else {
313afcbccb9SJérôme Duval			ERROR("VideoConsumer::CreateBuffers - ERROR CREATING VIDEO RING "
314afcbccb9SJérôme Duval				"BUFFER: %08" B_PRIx32 "\n", status);
315dba5824bSPhil Greenway			return B_ERROR;
3169d3f15c6SIngo Weinhold		}
317dba5824bSPhil Greenway	}
3189d3f15c6SIngo Weinhold
319f50d7408SDario Casalinuovo	BBuffer* buffList[3];
3209d3f15c6SIngo Weinhold	for (int j = 0; j < 3; j++)
321f50d7408SDario Casalinuovo		buffList[j] = NULL;
3229d3f15c6SIngo Weinhold
323476fad7fSMatt Madia	if ((status = fBuffers->GetBufferList(3, buffList)) == B_OK)
324dba5824bSPhil Greenway		for (int j = 0; j < 3; j++)
3259d3f15c6SIngo Weinhold			if (buffList[j] != NULL) {
326afcbccb9SJérôme Duval				fBufferMap[j] = buffList[j];
327afcbccb9SJérôme Duval				PROGRESS(" j = %d buffer = %p\n", j, fBufferMap[j]);
3289d3f15c6SIngo Weinhold			} else {
329dba5824bSPhil Greenway				ERROR("VideoConsumer::CreateBuffers ERROR MAPPING RING BUFFER\n");
330dba5824bSPhil Greenway				return B_ERROR;
331dba5824bSPhil Greenway			}
332dba5824bSPhil Greenway	else
333dba5824bSPhil Greenway		ERROR("VideoConsumer::CreateBuffers ERROR IN GET BUFFER LIST\n");
3349d3f15c6SIngo Weinhold
3353dd6b9cfSFrançois Revol	fFtpBitmap = new BBitmap(BRect(0, 0, xSize - 1, ySize - 1), B_RGB32, false, false);
3363dd6b9cfSFrançois Revol
337dba5824bSPhil Greenway	FUNCTION("VideoConsumer::CreateBuffers - EXIT\n");
338dba5824bSPhil Greenway	return status;
339dba5824bSPhil Greenway}
340dba5824bSPhil Greenway
341dba5824bSPhil Greenway
342dba5824bSPhil Greenwayvoid
343dba5824bSPhil GreenwayVideoConsumer::DeleteBuffers()
344dba5824bSPhil Greenway{
345dba5824bSPhil Greenway	FUNCTION("VideoConsumer::DeleteBuffers\n");
3469d3f15c6SIngo Weinhold
3479d3f15c6SIngo Weinhold	if (fBuffers) {
3489d3f15c6SIngo Weinhold		delete fBuffers;
3499d3f15c6SIngo Weinhold		fBuffers = NULL;
3509d3f15c6SIngo Weinhold
351dba5824bSPhil Greenway		for (uint32 j = 0; j < 3; j++)
3529d3f15c6SIngo Weinhold			if (fBitmap[j]->IsValid()) {
3539d3f15c6SIngo Weinhold				delete fBitmap[j];
3549d3f15c6SIngo Weinhold				fBitmap[j] = NULL;
355dba5824bSPhil Greenway			}
356dba5824bSPhil Greenway	}
357dba5824bSPhil Greenway	FUNCTION("VideoConsumer::DeleteBuffers - EXIT\n");
358dba5824bSPhil Greenway}
359dba5824bSPhil Greenway
360dba5824bSPhil Greenway
361dba5824bSPhil Greenwaystatus_t
3629d3f15c6SIngo WeinholdVideoConsumer::Connected(const media_source& producer, const media_destination& where,
3639d3f15c6SIngo Weinhold	const media_format& withFormat, media_input* outInput)
364dba5824bSPhil Greenway{
365dba5824bSPhil Greenway	FUNCTION("VideoConsumer::Connected\n");
366476fad7fSMatt Madia
3679d3f15c6SIngo Weinhold	fIn.source = producer;
3689d3f15c6SIngo Weinhold	fIn.format = withFormat;
3699d3f15c6SIngo Weinhold	fIn.node = Node();
3709d3f15c6SIngo Weinhold	sprintf(fIn.name, "Video Consumer");
3719d3f15c6SIngo Weinhold	*outInput = fIn;
3729d3f15c6SIngo Weinhold
3739d3f15c6SIngo Weinhold	uint32 userData = 0;
374476fad7fSMatt Madia	int32 changeTag = 1;
3759d3f15c6SIngo Weinhold	if (CreateBuffers(withFormat) == B_OK)
376476fad7fSMatt Madia		BBufferConsumer::SetOutputBuffersFor(producer, fDestination,
3779d3f15c6SIngo Weinhold			fBuffers, (void *)&userData, &changeTag, true);
3789d3f15c6SIngo Weinhold	else {
379dba5824bSPhil Greenway		ERROR("VideoConsumer::Connected - COULDN'T CREATE BUFFERS\n");
380dba5824bSPhil Greenway		return B_ERROR;
381dba5824bSPhil Greenway	}
382dba5824bSPhil Greenway
3839d3f15c6SIngo Weinhold	fConnectionActive = true;
3849d3f15c6SIngo Weinhold
385dba5824bSPhil Greenway	FUNCTION("VideoConsumer::Connected - EXIT\n");
386dba5824bSPhil Greenway	return B_OK;
387dba5824bSPhil Greenway}
388dba5824bSPhil Greenway
389dba5824bSPhil Greenway
390dba5824bSPhil Greenwayvoid
3919d3f15c6SIngo WeinholdVideoConsumer::Disconnected(const media_source& producer, const media_destination& where)
392dba5824bSPhil Greenway{
393dba5824bSPhil Greenway	FUNCTION("VideoConsumer::Disconnected\n");
394dba5824bSPhil Greenway
3959d3f15c6SIngo Weinhold	if (where == fIn.destination && producer == fIn.source) {
396dba5824bSPhil Greenway		// disconnect the connection
3979d3f15c6SIngo Weinhold		fIn.source = media_source::null;
3989d3f15c6SIngo Weinhold		delete fFtpBitmap;
3999d3f15c6SIngo Weinhold		fConnectionActive = false;
400dba5824bSPhil Greenway	}
401dba5824bSPhil Greenway
402dba5824bSPhil Greenway}
403dba5824bSPhil Greenway
404dba5824bSPhil Greenway
405dba5824bSPhil Greenwaystatus_t
4069d3f15c6SIngo WeinholdVideoConsumer::AcceptFormat(const media_destination& dest, media_format* format)
407dba5824bSPhil Greenway{
408dba5824bSPhil Greenway	FUNCTION("VideoConsumer::AcceptFormat\n");
409476fad7fSMatt Madia
4109d3f15c6SIngo Weinhold	if (dest != fIn.destination) {
411dba5824bSPhil Greenway		ERROR("VideoConsumer::AcceptFormat - BAD DESTINATION\n");
412476fad7fSMatt Madia		return B_MEDIA_BAD_DESTINATION;
413dba5824bSPhil Greenway	}
4149d3f15c6SIngo Weinhold
415dba5824bSPhil Greenway	if (format->type == B_MEDIA_NO_TYPE)
416dba5824bSPhil Greenway		format->type = B_MEDIA_RAW_VIDEO;
417476fad7fSMatt Madia
4189d3f15c6SIngo Weinhold	if (format->type != B_MEDIA_RAW_VIDEO) {
419dba5824bSPhil Greenway		ERROR("VideoConsumer::AcceptFormat - BAD FORMAT\n");
420dba5824bSPhil Greenway		return B_MEDIA_BAD_FORMAT;
421dba5824bSPhil Greenway	}
422dba5824bSPhil Greenway
4239d3f15c6SIngo Weinhold	if (format->u.raw_video.display.format != B_RGB32
4249d3f15c6SIngo Weinhold		&& format->u.raw_video.display.format != B_RGB16
4259d3f15c6SIngo Weinhold		&& format->u.raw_video.display.format != B_RGB15
4269d3f15c6SIngo Weinhold		&& format->u.raw_video.display.format != B_GRAY8
427476fad7fSMatt Madia		&&
4289d3f15c6SIngo Weinhold		format->u.raw_video.display.format != media_raw_video_format::wildcard.display.format) {
429dba5824bSPhil Greenway		ERROR("AcceptFormat - not a format we know about!\n");
430dba5824bSPhil Greenway		return B_MEDIA_BAD_FORMAT;
431dba5824bSPhil Greenway	}
4329d3f15c6SIngo Weinhold
4339d3f15c6SIngo Weinhold	if (format->u.raw_video.display.format == media_raw_video_format::wildcard.display.format) {
434dba5824bSPhil Greenway		format->u.raw_video.display.format = B_RGB16;
435dba5824bSPhil Greenway	}
436dba5824bSPhil Greenway
437476fad7fSMatt Madia	char formatString[256];
4389d3f15c6SIngo Weinhold	string_for_format(*format, formatString, 256);
4399d3f15c6SIngo Weinhold	FUNCTION("VideoConsumer::AcceptFormat: %s\n", formatString);
440dba5824bSPhil Greenway
441dba5824bSPhil Greenway	return B_OK;
442dba5824bSPhil Greenway}
443dba5824bSPhil Greenway
444dba5824bSPhil Greenway
445dba5824bSPhil Greenwaystatus_t
4469d3f15c6SIngo WeinholdVideoConsumer::GetNextInput(int32* cookie, media_input* outInput)
447dba5824bSPhil Greenway{
448dba5824bSPhil Greenway	FUNCTION("VideoConsumer::GetNextInput\n");
449dba5824bSPhil Greenway
450dba5824bSPhil Greenway	// custom build a destination for this connection
451dba5824bSPhil Greenway	// put connection number in id
452dba5824bSPhil Greenway
4539d3f15c6SIngo Weinhold	if (*cookie < 1) {
4549d3f15c6SIngo Weinhold		fIn.node = Node();
4559d3f15c6SIngo Weinhold		fIn.destination.id = *cookie;
4569d3f15c6SIngo Weinhold		sprintf(fIn.name, "Video Consumer");
4579d3f15c6SIngo Weinhold		*outInput = fIn;
458dba5824bSPhil Greenway		(*cookie)++;
459dba5824bSPhil Greenway		return B_OK;
4609d3f15c6SIngo Weinhold	} else {
461dba5824bSPhil Greenway		ERROR("VideoConsumer::GetNextInput - - BAD INDEX\n");
462dba5824bSPhil Greenway		return B_MEDIA_BAD_DESTINATION;
463dba5824bSPhil Greenway	}
464dba5824bSPhil Greenway}
465dba5824bSPhil Greenway
466dba5824bSPhil Greenway
467dba5824bSPhil Greenwayvoid
468dba5824bSPhil GreenwayVideoConsumer::DisposeInputCookie(int32 /*cookie*/)
469dba5824bSPhil Greenway{
470dba5824bSPhil Greenway}
471dba5824bSPhil Greenway
472dba5824bSPhil Greenway
473dba5824bSPhil Greenwaystatus_t
4749d3f15c6SIngo WeinholdVideoConsumer::GetLatencyFor(const media_destination& forWhom, bigtime_t* outLatency,
4759d3f15c6SIngo Weinhold	media_node_id* out_timesource)
476dba5824bSPhil Greenway{
477dba5824bSPhil Greenway	FUNCTION("VideoConsumer::GetLatencyFor\n");
478476fad7fSMatt Madia
4799d3f15c6SIngo Weinhold	if (forWhom != fIn.destination)
480dba5824bSPhil Greenway		return B_MEDIA_BAD_DESTINATION;
481476fad7fSMatt Madia
4829d3f15c6SIngo Weinhold	*outLatency = fMyLatency;
483dba5824bSPhil Greenway	*out_timesource = TimeSource()->ID();
484dba5824bSPhil Greenway	return B_OK;
485dba5824bSPhil Greenway}
486dba5824bSPhil Greenway
487dba5824bSPhil Greenway
488dba5824bSPhil Greenwaystatus_t
489476fad7fSMatt MadiaVideoConsumer::FormatChanged(const media_source& producer, const media_destination& consumer,
4909d3f15c6SIngo Weinhold	int32 fromChangeCount, const media_format& format)
491dba5824bSPhil Greenway{
492dba5824bSPhil Greenway	FUNCTION("VideoConsumer::FormatChanged\n");
4939d3f15c6SIngo Weinhold
4949d3f15c6SIngo Weinhold	if (consumer != fIn.destination)
495dba5824bSPhil Greenway		return B_MEDIA_BAD_DESTINATION;
496dba5824bSPhil Greenway
4979d3f15c6SIngo Weinhold	if (producer != fIn.source)
498dba5824bSPhil Greenway		return B_MEDIA_BAD_SOURCE;
499dba5824bSPhil Greenway
5009d3f15c6SIngo Weinhold	fIn.format = format;
5019d3f15c6SIngo Weinhold
502dba5824bSPhil Greenway	return CreateBuffers(format);
503dba5824bSPhil Greenway}
504dba5824bSPhil Greenway
505dba5824bSPhil Greenway
506dba5824bSPhil Greenwayvoid
5079d3f15c6SIngo WeinholdVideoConsumer::HandleEvent(const media_timed_event* event, bigtime_t lateness,
508dba5824bSPhil Greenway	bool realTimeEvent)
509dba5824bSPhil Greenway{
510dba5824bSPhil Greenway	LOOP("VideoConsumer::HandleEvent\n");
511476fad7fSMatt Madia
5129d3f15c6SIngo Weinhold	BBuffer* buffer;
5139d3f15c6SIngo Weinhold
5149d3f15c6SIngo Weinhold	switch (event->type) {
515dba5824bSPhil Greenway		case BTimedEventQueue::B_START:
516dba5824bSPhil Greenway			PROGRESS("VideoConsumer::HandleEvent - START\n");
517dba5824bSPhil Greenway			break;
5189d3f15c6SIngo Weinhold
519dba5824bSPhil Greenway		case BTimedEventQueue::B_STOP:
520dba5824bSPhil Greenway			PROGRESS("VideoConsumer::HandleEvent - STOP\n");
5219d3f15c6SIngo Weinhold			EventQueue()->FlushEvents(event->event_time, BTimedEventQueue::B_ALWAYS,
5229d3f15c6SIngo Weinhold				true, BTimedEventQueue::B_HANDLE_BUFFER);
523dba5824bSPhil Greenway			break;
5249d3f15c6SIngo Weinhold
525dba5824bSPhil Greenway		case BTimedEventQueue::B_USER_EVENT:
526dba5824bSPhil Greenway			PROGRESS("VideoConsumer::HandleEvent - USER EVENT\n");
5279d3f15c6SIngo Weinhold			if (RunState() == B_STARTED) {
5289d3f15c6SIngo Weinhold				fTimeToFtp = true;
5299d3f15c6SIngo Weinhold				PROGRESS("Pushing user event for %.4f, time now %.4f\n",
5309d3f15c6SIngo Weinhold					(event->event_time + fRate) / M1, event->event_time/M1);
5319d3f15c6SIngo Weinhold				media_timed_event newEvent(event->event_time + fRate,
5329d3f15c6SIngo Weinhold					BTimedEventQueue::B_USER_EVENT);
533dba5824bSPhil Greenway				EventQueue()->AddEvent(newEvent);
534dba5824bSPhil Greenway			}
5359d3f15c6SIngo Weinhold			break;
5369d3f15c6SIngo Weinhold
537dba5824bSPhil Greenway		case BTimedEventQueue::B_HANDLE_BUFFER:
5389d3f15c6SIngo Weinhold		{
539dba5824bSPhil Greenway			LOOP("VideoConsumer::HandleEvent - HANDLE BUFFER\n");
5409d3f15c6SIngo Weinhold			buffer = (BBuffer *)event->pointer;
5419d3f15c6SIngo Weinhold			if (RunState() == B_STARTED && fConnectionActive) {
542dba5824bSPhil Greenway				// see if this is one of our buffers
543dba5824bSPhil Greenway				uint32 index = 0;
5449d3f15c6SIngo Weinhold				fOurBuffers = true;
5459d3f15c6SIngo Weinhold				while (index < 3)
546afcbccb9SJérôme Duval					if (buffer == fBufferMap[index])
547dba5824bSPhil Greenway						break;
548dba5824bSPhil Greenway					else
549dba5824bSPhil Greenway						index++;
5509d3f15c6SIngo Weinhold
5519d3f15c6SIngo Weinhold				if (index == 3) {
552dba5824bSPhil Greenway					// no, buffers belong to consumer
5539d3f15c6SIngo Weinhold					fOurBuffers = false;
554dba5824bSPhil Greenway					index = 0;
555dba5824bSPhil Greenway				}
556476fad7fSMatt Madia
5579d3f15c6SIngo Weinhold				if (fFtpComplete && fTimeToFtp) {
558dba5824bSPhil Greenway					PROGRESS("VidConsumer::HandleEvent - SPAWNING FTP THREAD\n");
5599d3f15c6SIngo Weinhold					fTimeToFtp = false;
5609d3f15c6SIngo Weinhold					fFtpComplete = false;
5619d3f15c6SIngo Weinhold					memcpy(fFtpBitmap->Bits(), buffer->Data(), fFtpBitmap->BitsLength());
5629d3f15c6SIngo Weinhold					fFtpThread = spawn_thread(FtpRun, "Video Window Ftp", B_NORMAL_PRIORITY, this);
563476fad7fSMatt Madia					resume_thread(fFtpThread);
564dba5824bSPhil Greenway				}
565dba5824bSPhil Greenway
5669d3f15c6SIngo Weinhold				if ((RunMode() == B_OFFLINE)
5679d3f15c6SIngo Weinhold					|| ((TimeSource()->Now() > (buffer->Header()->start_time - JITTER))
5689d3f15c6SIngo Weinhold						&& (TimeSource()->Now() < (buffer->Header()->start_time + JITTER)))) {
5699d3f15c6SIngo Weinhold					if (!fOurBuffers)
570dba5824bSPhil Greenway						// not our buffers, so we need to copy
5719d3f15c6SIngo Weinhold						memcpy(fBitmap[index]->Bits(), buffer->Data(), fBitmap[index]->BitsLength());
5729d3f15c6SIngo Weinhold
5739d3f15c6SIngo Weinhold					if (fWindow->Lock()) {
574dba5824bSPhil Greenway						uint32 flags;
5759d3f15c6SIngo Weinhold						if ((fBitmap[index]->ColorSpace() == B_GRAY8) &&
5769d3f15c6SIngo Weinhold							!bitmaps_support_space(fBitmap[index]->ColorSpace(), &flags)) {
577dba5824bSPhil Greenway							// handle mapping of GRAY8 until app server knows how
5789d3f15c6SIngo Weinhold							uint32* start = (uint32*)fBitmap[index]->Bits();
5799d3f15c6SIngo Weinhold							int32 size = fBitmap[index]->BitsLength();
5809d3f15c6SIngo Weinhold							uint32* end = start + size / 4;
5819d3f15c6SIngo Weinhold							for (uint32* p = start; p < end; p++)
582476fad7fSMatt Madia								*p = (*p >> 3) & 0x1f1f1f1f;
583dba5824bSPhil Greenway						}
5849d3f15c6SIngo Weinhold
58545c2e6b8SFrançois Revol						fView->DrawBitmap(fBitmap[index], fView->Bounds());
5869d3f15c6SIngo Weinhold						fWindow->Unlock();
587dba5824bSPhil Greenway					}
588dba5824bSPhil Greenway				}
589dba5824bSPhil Greenway				else
590dba5824bSPhil Greenway					PROGRESS("VidConsumer::HandleEvent - DROPPED FRAME\n");
591dba5824bSPhil Greenway				buffer->Recycle();
592dba5824bSPhil Greenway			}
593dba5824bSPhil Greenway			else
594dba5824bSPhil Greenway				buffer->Recycle();
595dba5824bSPhil Greenway			break;
5969d3f15c6SIngo Weinhold		}
5979d3f15c6SIngo Weinhold
598dba5824bSPhil Greenway		default:
599dba5824bSPhil Greenway			ERROR("VideoConsumer::HandleEvent - BAD EVENT\n");
600dba5824bSPhil Greenway			break;
601476fad7fSMatt Madia	}
602dba5824bSPhil Greenway}
603dba5824bSPhil Greenway
604dba5824bSPhil Greenway
605dba5824bSPhil Greenwaystatus_t
6069d3f15c6SIngo WeinholdVideoConsumer::FtpRun(void* data)
607dba5824bSPhil Greenway{
608dba5824bSPhil Greenway	FUNCTION("VideoConsumer::FtpRun\n");
609476fad7fSMatt Madia
610dba5824bSPhil Greenway	((VideoConsumer *)data)->FtpThread();
611dba5824bSPhil Greenway
612dba5824bSPhil Greenway	return 0;
613dba5824bSPhil Greenway}
614dba5824bSPhil Greenway
615dba5824bSPhil Greenway
616dba5824bSPhil Greenwayvoid
617dba5824bSPhil GreenwayVideoConsumer::FtpThread()
618dba5824bSPhil Greenway{
619f5e3b474SStephan Aßmus	char fullPath[B_PATH_NAME_LENGTH];
620dba5824bSPhil Greenway	FUNCTION("VideoConsumer::FtpThread\n");
621f5e3b474SStephan Aßmus	if (fUploadClient == 2) {
622f5e3b474SStephan Aßmus		// 64 + 64 = 128 max
623f5e3b474SStephan Aßmus		snprintf(fullPath, B_PATH_NAME_LENGTH, "%s/%s", fDirectoryText, fFileNameText);
624f5e3b474SStephan Aßmus		LocalSave(fullPath, fFtpBitmap);
625f5e3b474SStephan Aßmus	} else if (LocalSave(fFileNameText, fFtpBitmap) == B_OK)
6269d3f15c6SIngo Weinhold		FtpSave(fFileNameText);
6279d3f15c6SIngo Weinhold
628dba5824bSPhil Greenway#if 0
629dba5824bSPhil Greenway	// save a small version, too
6309d3f15c6SIngo Weinhold	BBitmap* b = new BBitmap(BRect(0,0,159,119), B_RGB32, true, false);
6319d3f15c6SIngo Weinhold	BView* v = new BView(BRect(0,0,159,119), "SmallView 1", 0, B_WILL_DRAW);
632dba5824bSPhil Greenway	b->AddChild(v);
633dba5824bSPhil Greenway
634dba5824bSPhil Greenway	b->Lock();
6359d3f15c6SIngo Weinhold	v->DrawBitmap(fFtpBitmap, v->Frame());
636dba5824bSPhil Greenway	v->Sync();
637476fad7fSMatt Madia	b->Unlock();
638dba5824bSPhil Greenway
639476fad7fSMatt Madia	if (LocalSave("small.jpg", b) == B_OK)
640dba5824bSPhil Greenway		FtpSave("small.jpg");
641476fad7fSMatt Madia
642dba5824bSPhil Greenway	delete b;
643dba5824bSPhil Greenway#endif
644476fad7fSMatt Madia
645476fad7fSMatt Madia	fFtpComplete = true;
646dba5824bSPhil Greenway}
647dba5824bSPhil Greenway
648dba5824bSPhil Greenway
649dba5824bSPhil Greenwayvoid
650241dbd37SFrançois RevolVideoConsumer::UpdateFtpStatus(const char* status)
651dba5824bSPhil Greenway{
652dba5824bSPhil Greenway	printf("FTP STATUS: %s\n",status);
6539d3f15c6SIngo Weinhold	if (fView->Window()->Lock()) {
6549d3f15c6SIngo Weinhold		fStatusLine->SetText(status);
6559d3f15c6SIngo Weinhold		fView->Window()->Unlock();
656dba5824bSPhil Greenway	}
657dba5824bSPhil Greenway}
658dba5824bSPhil Greenway
659dba5824bSPhil Greenway
660dba5824bSPhil Greenwaystatus_t
6619d3f15c6SIngo WeinholdVideoConsumer::LocalSave(char* filename, BBitmap* bitmap)
662dba5824bSPhil Greenway{
6639d3f15c6SIngo Weinhold	BFile* output;
6649d3f15c6SIngo Weinhold
665c4f9b1d1SStephan Aßmus	UpdateFtpStatus(B_TRANSLATE("Capturing Image" B_UTF8_ELLIPSIS));
666dba5824bSPhil Greenway
667dba5824bSPhil Greenway	/* save a local copy of the image in the requested format */
6689d3f15c6SIngo Weinhold	output = new BFile();
6699d3f15c6SIngo Weinhold	if (output->SetTo(filename, B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE) == B_NO_ERROR) {
670dba5824bSPhil Greenway		BBitmapStream input(bitmap);
6719d3f15c6SIngo Weinhold		status_t err = BTranslatorRoster::Default()->Translate(&input, NULL, NULL,
672a8aeb8a9SAdrien Destugues			output, fImageFormat);
673a8aeb8a9SAdrien Destugues		if (err == B_OK) {
674a8aeb8a9SAdrien Destugues			err = SetFileType(output, fTranslator, fImageFormat);
675a8aeb8a9SAdrien Destugues			if (err != B_OK)
676a8aeb8a9SAdrien Destugues				UpdateFtpStatus(B_TRANSLATE("Error setting type of output file"));
677a8aeb8a9SAdrien Destugues		}
678a8aeb8a9SAdrien Destugues		else
679a8aeb8a9SAdrien Destugues			UpdateFtpStatus(B_TRANSLATE("Error writing output file"));
6809d3f15c6SIngo Weinhold
6819d3f15c6SIngo Weinhold		input.DetachBitmap(&bitmap);
6829d3f15c6SIngo Weinhold		output->Unset();
6839d3f15c6SIngo Weinhold		delete output;
6849d3f15c6SIngo Weinhold		return B_OK;
685a8aeb8a9SAdrien Destugues	} else {
686c4f9b1d1SStephan Aßmus		UpdateFtpStatus(B_TRANSLATE("Error creating output file"));
687a8aeb8a9SAdrien Destugues		return B_ERROR;
688a8aeb8a9SAdrien Destugues	}
689dba5824bSPhil Greenway}
690dba5824bSPhil Greenway
691dba5824bSPhil Greenway
692dba5824bSPhil Greenwaystatus_t
6939d3f15c6SIngo WeinholdVideoConsumer::FtpSave(char* filename)
694dba5824bSPhil Greenway{
695e3145a8dSFrançois Revol	FileUploadClient *ftp;
696476fad7fSMatt Madia
697e3145a8dSFrançois Revol	//XXX: make that cleaner
698e3145a8dSFrançois Revol	switch (fUploadClient) {
699e3145a8dSFrançois Revol		case 0:
700e3145a8dSFrançois Revol			ftp = new FtpClient;
701e3145a8dSFrançois Revol			break;
702e3145a8dSFrançois Revol		case 1:
703e3145a8dSFrançois Revol			ftp = new SftpClient;
704e3145a8dSFrançois Revol			break;
705f5e3b474SStephan Aßmus		case 2:
706f5e3b474SStephan Aßmus			return B_OK;
707e3145a8dSFrançois Revol		default:
708476fad7fSMatt Madia			fprintf(stderr, B_TRANSLATE("invalid upload client %ld\n"),
709c4f9b1d1SStephan Aßmus				fUploadClient);
710e3145a8dSFrançois Revol			return EINVAL;
711e3145a8dSFrançois Revol	}
7129d3f15c6SIngo Weinhold
713e3145a8dSFrançois Revol	ftp->SetPassive(fPassiveFtp);
7149d3f15c6SIngo Weinhold		// ftp the local file to our web site
715dba5824bSPhil Greenway
716c4f9b1d1SStephan Aßmus	UpdateFtpStatus(B_TRANSLATE("Logging in" B_UTF8_ELLIPSIS));
717476fad7fSMatt Madia	if (ftp->Connect((string)fServerText, (string)fLoginText,
718c4f9b1d1SStephan Aßmus		(string)fPasswordText)) {
7199d3f15c6SIngo Weinhold		// connect to server
720c4f9b1d1SStephan Aßmus		UpdateFtpStatus(B_TRANSLATE("Connected" B_UTF8_ELLIPSIS));
7219d3f15c6SIngo Weinhold
722e3145a8dSFrançois Revol		if (ftp->ChangeDir((string)fDirectoryText)) {
7239d3f15c6SIngo Weinhold			// cd to the desired directory
7242824c5d3SAdrien Destugues			UpdateFtpStatus(B_TRANSLATE("Upload" B_UTF8_ELLIPSIS));
7259d3f15c6SIngo Weinhold
726e3145a8dSFrançois Revol			if (ftp->PutFile((string)filename, (string)"temp")) {
7279d3f15c6SIngo Weinhold				// send the file to the server
7286298fd45SFrançois Revol
72961946f58SFrançois Revol				ftp->Chmod((string)"temp", (string)"644");
7306298fd45SFrançois Revol				// make it world readable
7316298fd45SFrançois Revol
732c4f9b1d1SStephan Aßmus				UpdateFtpStatus(B_TRANSLATE("Renaming" B_UTF8_ELLIPSIS));
7339d3f15c6SIngo Weinhold
734e3145a8dSFrançois Revol				if (ftp->MoveFile((string)"temp", (string)filename)) {
7359d3f15c6SIngo Weinhold					// change to the desired name
736dba5824bSPhil Greenway					uint32 time = real_time_clock();
737dba5824bSPhil Greenway					char s[80];
738c4f9b1d1SStephan Aßmus					strcpy(s, B_TRANSLATE("Last Capture: "));
739afcbccb9SJérôme Duval					strcat(s, ctime((const time_t*)&time));
7409d3f15c6SIngo Weinhold					s[strlen(s) - 1] = 0;
741dba5824bSPhil Greenway					UpdateFtpStatus(s);
742e3145a8dSFrançois Revol					delete ftp;
743dba5824bSPhil Greenway					return B_OK;
7442824c5d3SAdrien Destugues				} else
745c4f9b1d1SStephan Aßmus					UpdateFtpStatus(B_TRANSLATE("Rename failed"));
7462824c5d3SAdrien Destugues			} else
7472824c5d3SAdrien Destugues				UpdateFtpStatus(B_TRANSLATE("File upload failed"));
7482824c5d3SAdrien Destugues		} else
749c4f9b1d1SStephan Aßmus			UpdateFtpStatus(B_TRANSLATE("Couldn't find requested directory on "
750c4f9b1d1SStephan Aßmus				"server"));
7519d3f15c6SIngo Weinhold	}
7529d3f15c6SIngo Weinhold	else
753c4f9b1d1SStephan Aßmus		UpdateFtpStatus(B_TRANSLATE("Server login failed"));
7549d3f15c6SIngo Weinhold
755e3145a8dSFrançois Revol	delete ftp;
756dba5824bSPhil Greenway	return B_ERROR;
757dba5824bSPhil Greenway}
758dba5824bSPhil Greenway
759dba5824bSPhil Greenway
760dba5824bSPhil Greenwaystatus_t
761476fad7fSMatt MadiaSetFileType(BFile* file, int32 translator, uint32 type)
762476fad7fSMatt Madia{
7639d3f15c6SIngo Weinhold	translation_format* formats;
7649d3f15c6SIngo Weinhold	int32 count;
7659d3f15c6SIngo Weinhold
7669d3f15c6SIngo Weinhold	status_t err = BTranslatorRoster::Default()->GetOutputFormats(translator,
7679d3f15c6SIngo Weinhold		(const translation_format **)&formats, &count);
7689d3f15c6SIngo Weinhold	if (err < B_OK)
7699d3f15c6SIngo Weinhold		return err;
7709d3f15c6SIngo Weinhold
7719d3f15c6SIngo Weinhold	const char* mime = NULL;
7729d3f15c6SIngo Weinhold	for (int ix = 0; ix < count; ix++) {
7739d3f15c6SIngo Weinhold		if (formats[ix].type == type) {
7749d3f15c6SIngo Weinhold			mime = formats[ix].MIME;
7759d3f15c6SIngo Weinhold			break;
7769d3f15c6SIngo Weinhold		}
7779d3f15c6SIngo Weinhold	}
778dba5824bSPhil Greenway
7799d3f15c6SIngo Weinhold	if (mime == NULL) {
7809d3f15c6SIngo Weinhold		/* this should not happen, but being defensive might be prudent */
7819d3f15c6SIngo Weinhold		return B_ERROR;
7829d3f15c6SIngo Weinhold	}
783dba5824bSPhil Greenway
7849d3f15c6SIngo Weinhold	/* use BNodeInfo to set the file type */
7859d3f15c6SIngo Weinhold	BNodeInfo ninfo(file);
7869d3f15c6SIngo Weinhold	return ninfo.SetType(mime);
7879d3f15c6SIngo Weinhold}
788