VideoConsumer.cpp revision 6a739773
16a739773SCodeforEvolution/*
26a739773SCodeforEvolution * Copyright 1998-1999 Be, Inc. All Rights Reserved.
36a739773SCodeforEvolution * Copyright 2003-2019 Haiku, Inc. All rights reserved.
46a739773SCodeforEvolution * Distributed under the terms of the MIT License.
56a739773SCodeforEvolution */
6dba5824bSPhil Greenway
79d3f15c6SIngo Weinhold
89d3f15c6SIngo Weinhold#include "VideoConsumer.h"
99d3f15c6SIngo Weinhold
10dba5824bSPhil Greenway#include <fcntl.h>
119d3f15c6SIngo Weinhold#include <stdio.h>
12dba5824bSPhil Greenway#include <string.h>
136a739773SCodeforEvolution#include <unistd.h>
149d3f15c6SIngo Weinhold
159d3f15c6SIngo Weinhold#include <Application.h>
166a739773SCodeforEvolution#include <BitmapStream.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
286a739773SCodeforEvolution#include "FileUploadClient.h"
296a739773SCodeforEvolution#include "FtpClient.h"
306a739773SCodeforEvolution#include "SftpClient.h"
316a739773SCodeforEvolution
32dba5824bSPhil Greenway
33546208a5SOliver Tappe#undef B_TRANSLATION_CONTEXT
34546208a5SOliver Tappe#define B_TRANSLATION_CONTEXT "VideoConsumer.cpp"
35c4f9b1d1SStephan Aßmus
366a739773SCodeforEvolution
37dba5824bSPhil Greenway#define M1 ((double)1000000.0)
38dba5824bSPhil Greenway#define JITTER		20000
39dba5824bSPhil Greenway
40dba5824bSPhil Greenway#define	FUNCTION	printf
41dba5824bSPhil Greenway#define ERROR		printf
42dba5824bSPhil Greenway#define PROGRESS	printf
43dba5824bSPhil Greenway#define LOOP		printf
44dba5824bSPhil Greenway
45c4f9b1d1SStephan Aßmus
466a739773SCodeforEvolutionstatic status_t SetFileType(BFile* file, int32 translator, uint32 type);
479d3f15c6SIngo Weinhold
48c4f9b1d1SStephan Aßmusconst media_raw_video_format vid_format = {29.97, 1, 0, 239,
49c4f9b1d1SStephan Aßmus	B_VIDEO_TOP_LEFT_RIGHT, 1, 1, {B_RGB16, 320, 240, 320 * 4, 0, 0}};
509d3f15c6SIngo Weinhold
519d3f15c6SIngo Weinhold
52476fad7fSMatt MadiaVideoConsumer::VideoConsumer(const char* name, BView* view,
53c4f9b1d1SStephan Aßmus	BStringView* statusLine,
549d3f15c6SIngo Weinhold	BMediaAddOn* addon, const uint32 internalId)
556a739773SCodeforEvolution	:
566a739773SCodeforEvolution	BMediaNode(name),
57476fad7fSMatt Madia	BMediaEventLooper(),
58c4f9b1d1SStephan Aßmus	BBufferConsumer(B_MEDIA_RAW_VIDEO),
599d3f15c6SIngo Weinhold	fStatusLine(statusLine),
609d3f15c6SIngo Weinhold	fInternalID(internalId),
619d3f15c6SIngo Weinhold	fAddOn(addon),
629d3f15c6SIngo Weinhold	fConnectionActive(false),
639d3f15c6SIngo Weinhold	fMyLatency(20000),
649d3f15c6SIngo Weinhold	fWindow(NULL),
659d3f15c6SIngo Weinhold	fView(view),
669d3f15c6SIngo Weinhold	fOurBuffers(false),
679d3f15c6SIngo Weinhold	fBuffers(NULL),
689d3f15c6SIngo Weinhold	fTimeToFtp(false),
699d3f15c6SIngo Weinhold	fFtpComplete(true),
709d3f15c6SIngo Weinhold	fRate(1000000),
719d3f15c6SIngo Weinhold	fImageFormat(0),
729d3f15c6SIngo Weinhold	fTranslator(0),
73e3145a8dSFrançois Revol	fUploadClient(0),
749d3f15c6SIngo Weinhold	fPassiveFtp(true)
75dba5824bSPhil Greenway{
76dba5824bSPhil Greenway	FUNCTION("VideoConsumer::VideoConsumer\n");
77dba5824bSPhil Greenway
78dba5824bSPhil Greenway	AddNodeKind(B_PHYSICAL_OUTPUT);
79dba5824bSPhil Greenway	SetEventLatency(0);
809d3f15c6SIngo Weinhold	fWindow = fView->Window();
81476fad7fSMatt Madia
829d3f15c6SIngo Weinhold	for (uint32 j = 0; j < 3; j++) {
839d3f15c6SIngo Weinhold		fBitmap[j] = NULL;
846a739773SCodeforEvolution		fBufferMap[j] = NULL;
85dba5824bSPhil Greenway	}
869d3f15c6SIngo Weinhold
879d3f15c6SIngo Weinhold	strcpy(fFileNameText, "");
889d3f15c6SIngo Weinhold	strcpy(fServerText, "");
899d3f15c6SIngo Weinhold	strcpy(fLoginText, "");
909d3f15c6SIngo Weinhold	strcpy(fPasswordText, "");
919d3f15c6SIngo Weinhold	strcpy(fDirectoryText, "");
92dba5824bSPhil Greenway
93dba5824bSPhil Greenway	SetPriority(B_DISPLAY_PRIORITY);
94dba5824bSPhil Greenway}
95dba5824bSPhil Greenway
96dba5824bSPhil Greenway
97dba5824bSPhil GreenwayVideoConsumer::~VideoConsumer()
98dba5824bSPhil Greenway{
99dba5824bSPhil Greenway	FUNCTION("VideoConsumer::~VideoConsumer\n");
100476fad7fSMatt Madia
101dba5824bSPhil Greenway	Quit();
102dba5824bSPhil Greenway
1039d3f15c6SIngo Weinhold	if (fWindow) {
104b726920eSRob Gill		puts(B_TRANSLATE("Locking the window"));
1059d3f15c6SIngo Weinhold		if (fWindow->Lock()) {
106b726920eSRob Gill			puts(B_TRANSLATE("Closing the window"));
1079d3f15c6SIngo Weinhold			fWindow->Close();
1086a739773SCodeforEvolution			fWindow = NULL;
109dba5824bSPhil Greenway		}
110dba5824bSPhil Greenway	}
111dba5824bSPhil Greenway
112dba5824bSPhil Greenway	// clean up ftp thread
113dba5824bSPhil Greenway	// wait up to 30 seconds if ftp is in progress
114dba5824bSPhil Greenway	int32 count = 0;
1159d3f15c6SIngo Weinhold	while (!fFtpComplete && count < 30) {
116dba5824bSPhil Greenway		snooze(1000000);
117dba5824bSPhil Greenway		count++;
118dba5824bSPhil Greenway	}
119476fad7fSMatt Madia
120476fad7fSMatt Madia	if (count == 30)
1219d3f15c6SIngo Weinhold		kill_thread(fFtpThread);
122476fad7fSMatt Madia
123dba5824bSPhil Greenway	DeleteBuffers();
124dba5824bSPhil Greenway}
125dba5824bSPhil Greenway
126dba5824bSPhil Greenway/********************************
127dba5824bSPhil Greenway	From BMediaNode
128dba5824bSPhil Greenway********************************/
129dba5824bSPhil Greenway
130dba5824bSPhil Greenway
1319d3f15c6SIngo WeinholdBMediaAddOn*
132afcbccb9SJérôme DuvalVideoConsumer::AddOn(int32* cookie) const
133dba5824bSPhil Greenway{
134dba5824bSPhil Greenway	FUNCTION("VideoConsumer::AddOn\n");
135dba5824bSPhil Greenway	// do the right thing if we're ever used with an add-on
1369d3f15c6SIngo Weinhold	*cookie = fInternalID;
1379d3f15c6SIngo Weinhold	return fAddOn;
138dba5824bSPhil Greenway}
139dba5824bSPhil Greenway
140dba5824bSPhil Greenway
141dba5824bSPhil Greenway// This implementation is required to get around a bug in
142dba5824bSPhil Greenway// the ppc compiler.
143dba5824bSPhil Greenway
144476fad7fSMatt Madiavoid
1459d3f15c6SIngo WeinholdVideoConsumer::Start(bigtime_t performanceTime)
146dba5824bSPhil Greenway{
1479d3f15c6SIngo Weinhold	BMediaEventLooper::Start(performanceTime);
148dba5824bSPhil Greenway}
149dba5824bSPhil Greenway
1509d3f15c6SIngo Weinhold
151476fad7fSMatt Madiavoid
1529d3f15c6SIngo WeinholdVideoConsumer::Stop(bigtime_t performanceTime, bool immediate)
153dba5824bSPhil Greenway{
1549d3f15c6SIngo Weinhold	BMediaEventLooper::Stop(performanceTime, immediate);
155dba5824bSPhil Greenway}
156dba5824bSPhil Greenway
1579d3f15c6SIngo Weinhold
158476fad7fSMatt Madiavoid
1599d3f15c6SIngo WeinholdVideoConsumer::Seek(bigtime_t mediaTime, bigtime_t performanceTime)
160dba5824bSPhil Greenway{
1619d3f15c6SIngo Weinhold	BMediaEventLooper::Seek(mediaTime, performanceTime);
162dba5824bSPhil Greenway}
163dba5824bSPhil Greenway
1649d3f15c6SIngo Weinhold
165476fad7fSMatt Madiavoid
1669d3f15c6SIngo WeinholdVideoConsumer::TimeWarp(bigtime_t atRealTime, bigtime_t toPerformanceTime)
167dba5824bSPhil Greenway{
1689d3f15c6SIngo Weinhold	BMediaEventLooper::TimeWarp(atRealTime, toPerformanceTime);
169dba5824bSPhil Greenway}
170dba5824bSPhil Greenway
1719d3f15c6SIngo Weinhold
172476fad7fSMatt Madiastatus_t
1739d3f15c6SIngo WeinholdVideoConsumer::DeleteHook(BMediaNode* node)
174dba5824bSPhil Greenway{
175dba5824bSPhil Greenway	return BMediaEventLooper::DeleteHook(node);
176dba5824bSPhil Greenway}
177dba5824bSPhil Greenway
178dba5824bSPhil Greenway
179dba5824bSPhil Greenwayvoid
180dba5824bSPhil GreenwayVideoConsumer::NodeRegistered()
181dba5824bSPhil Greenway{
182dba5824bSPhil Greenway	FUNCTION("VideoConsumer::NodeRegistered\n");
1839d3f15c6SIngo Weinhold	fIn.destination.port = ControlPort();
1849d3f15c6SIngo Weinhold	fIn.destination.id = 0;
1859d3f15c6SIngo Weinhold	fIn.source = media_source::null;
1869d3f15c6SIngo Weinhold	fIn.format.type = B_MEDIA_RAW_VIDEO;
1879d3f15c6SIngo Weinhold	fIn.format.u.raw_video = vid_format;
188dba5824bSPhil Greenway
189dba5824bSPhil Greenway	Run();
190dba5824bSPhil Greenway}
191dba5824bSPhil Greenway
192dba5824bSPhil Greenway
193dba5824bSPhil Greenwaystatus_t
1949d3f15c6SIngo WeinholdVideoConsumer::RequestCompleted(const media_request_info& info)
195dba5824bSPhil Greenway{
196dba5824bSPhil Greenway	FUNCTION("VideoConsumer::RequestCompleted\n");
1979d3f15c6SIngo Weinhold	switch (info.what) {
198dba5824bSPhil Greenway		case media_request_info::B_SET_OUTPUT_BUFFERS_FOR:
1999d3f15c6SIngo Weinhold			if (info.status != B_OK)
2006a739773SCodeforEvolution					ERROR("VideoConsumer::RequestCompleted: "
2016a739773SCodeforEvolution						  "Not using our buffers!\n");
202dba5824bSPhil Greenway			break;
2039d3f15c6SIngo Weinhold
204859c1f01SNiels Sascha Reedijk		default:
205859c1f01SNiels Sascha Reedijk			ERROR("VideoConsumer::RequestCompleted: Invalid argument\n");
206859c1f01SNiels Sascha Reedijk			break;
207dba5824bSPhil Greenway	}
2086a739773SCodeforEvolution
209dba5824bSPhil Greenway	return B_OK;
210dba5824bSPhil Greenway}
211dba5824bSPhil Greenway
212dba5824bSPhil Greenway
213dba5824bSPhil Greenwaystatus_t
2149d3f15c6SIngo WeinholdVideoConsumer::HandleMessage(int32 message, const void* data, size_t size)
215dba5824bSPhil Greenway{
216dba5824bSPhil Greenway	//FUNCTION("VideoConsumer::HandleMessage\n");
2179d3f15c6SIngo Weinhold	ftp_msg_info* info = (ftp_msg_info*)data;
2189d3f15c6SIngo Weinhold
2199d3f15c6SIngo Weinhold	switch (message) {
220dba5824bSPhil Greenway		case FTP_INFO:
221dba5824bSPhil Greenway			PROGRESS("VideoConsumer::HandleMessage - FTP_INFO message\n");
2229d3f15c6SIngo Weinhold			fRate = info->rate;
2239d3f15c6SIngo Weinhold			fImageFormat = info->imageFormat;
2249d3f15c6SIngo Weinhold			fTranslator = info->translator;
2259d3f15c6SIngo Weinhold			fPassiveFtp = info->passiveFtp;
226e3145a8dSFrançois Revol			fUploadClient = info->uploadClient;
2279d3f15c6SIngo Weinhold			strcpy(fFileNameText, info->fileNameText);
2289d3f15c6SIngo Weinhold			strcpy(fServerText, info->serverText);
2299d3f15c6SIngo Weinhold			strcpy(fLoginText, info->loginText);
2309d3f15c6SIngo Weinhold			strcpy(fPasswordText, info->passwordText);
2319d3f15c6SIngo Weinhold			strcpy(fDirectoryText, info->directoryText);
232dba5824bSPhil Greenway			// remove old user events
2336a739773SCodeforEvolution			EventQueue()->FlushEvents(TimeSource()->Now(),
2346a739773SCodeforEvolution				BTimedEventQueue::B_ALWAYS, true,
2356a739773SCodeforEvolution				BTimedEventQueue::B_USER_EVENT);
2369d3f15c6SIngo Weinhold			if (fRate != B_INFINITE_TIMEOUT) {
2379d3f15c6SIngo Weinhold				// if rate is not "Never," push an event
2389d3f15c6SIngo Weinhold				// to restart captures 5 seconds from now
2399d3f15c6SIngo Weinhold				media_timed_event event(TimeSource()->Now() + 5000000,
2409d3f15c6SIngo Weinhold					BTimedEventQueue::B_USER_EVENT);
241dba5824bSPhil Greenway				EventQueue()->AddEvent(event);
242dba5824bSPhil Greenway			}
243dba5824bSPhil Greenway			break;
244dba5824bSPhil Greenway	}
245476fad7fSMatt Madia
2466a739773SCodeforEvolution	return B_OK;
247dba5824bSPhil Greenway}
248dba5824bSPhil Greenway
249dba5824bSPhil Greenway
250dba5824bSPhil Greenwayvoid
2519d3f15c6SIngo WeinholdVideoConsumer::BufferReceived(BBuffer* buffer)
252dba5824bSPhil Greenway{
2536a739773SCodeforEvolution	LOOP("VideoConsumer::Buffer #%" B_PRId32 " received, start_time %"
2546a739773SCodeforEvolution		B_PRIdBIGTIME "\n", buffer->ID(), buffer->Header()->start_time);
255dba5824bSPhil Greenway
2569d3f15c6SIngo Weinhold	if (RunState() == B_STOPPED) {
257dba5824bSPhil Greenway		buffer->Recycle();
258dba5824bSPhil Greenway		return;
259dba5824bSPhil Greenway	}
260dba5824bSPhil Greenway
2616a739773SCodeforEvolution	media_timed_event event(buffer->Header()->start_time,
2626a739773SCodeforEvolution		BTimedEventQueue::B_HANDLE_BUFFER, buffer,
2636a739773SCodeforEvolution		BTimedEventQueue::B_RECYCLE_BUFFER);
264dba5824bSPhil Greenway	EventQueue()->AddEvent(event);
265dba5824bSPhil Greenway}
266dba5824bSPhil Greenway
267dba5824bSPhil Greenway
268dba5824bSPhil Greenwayvoid
2696a739773SCodeforEvolutionVideoConsumer::ProducerDataStatus(const media_destination& forWhom,
2706a739773SCodeforEvolution	int32 status, bigtime_t atMediaTime)
271dba5824bSPhil Greenway{
272dba5824bSPhil Greenway	FUNCTION("VideoConsumer::ProducerDataStatus\n");
273dba5824bSPhil Greenway
274476fad7fSMatt Madia	if (forWhom != fIn.destination)
275dba5824bSPhil Greenway		return;
276dba5824bSPhil Greenway}
277dba5824bSPhil Greenway
278dba5824bSPhil Greenway
279dba5824bSPhil Greenwaystatus_t
2809d3f15c6SIngo WeinholdVideoConsumer::CreateBuffers(const media_format& withFormat)
281dba5824bSPhil Greenway{
282dba5824bSPhil Greenway	FUNCTION("VideoConsumer::CreateBuffers\n");
2839d3f15c6SIngo Weinhold
284476fad7fSMatt Madia	DeleteBuffers();
2859d3f15c6SIngo Weinhold		// delete any old buffers
286dba5824bSPhil Greenway
287dba5824bSPhil Greenway	status_t status = B_OK;
288dba5824bSPhil Greenway
289dba5824bSPhil Greenway	// create a buffer group
2909d3f15c6SIngo Weinhold	uint32 xSize = withFormat.u.raw_video.display.line_width;
291476fad7fSMatt Madia	uint32 ySize = withFormat.u.raw_video.display.line_count;
2929d3f15c6SIngo Weinhold	color_space colorspace = withFormat.u.raw_video.display.format;
2939d3f15c6SIngo Weinhold	PROGRESS("VideoConsumer::CreateBuffers - Colorspace = %d\n", colorspace);
2949d3f15c6SIngo Weinhold
2959d3f15c6SIngo Weinhold	fBuffers = new BBufferGroup();
2969d3f15c6SIngo Weinhold	status = fBuffers->InitCheck();
2979d3f15c6SIngo Weinhold	if (status != B_OK) {
298dba5824bSPhil Greenway		ERROR("VideoConsumer::CreateBuffers - ERROR CREATING BUFFER GROUP\n");
299dba5824bSPhil Greenway		return status;
300dba5824bSPhil Greenway	}
301dba5824bSPhil Greenway	// and attach the  bitmaps to the buffer group
3029d3f15c6SIngo Weinhold	for (uint32 j = 0; j < 3; j++) {
3036a739773SCodeforEvolution		fBitmap[j] = new BBitmap(BRect(0, 0, (xSize - 1), (ySize - 1)),
3046a739773SCodeforEvolution			colorspace, false, true);
305476fad7fSMatt Madia		if (fBitmap[j]->IsValid()) {
306dba5824bSPhil Greenway			buffer_clone_info info;
3079d3f15c6SIngo Weinhold			if ((info.area = area_for(fBitmap[j]->Bits())) == B_ERROR)
3089d3f15c6SIngo Weinhold				ERROR("VideoConsumer::CreateBuffers - ERROR IN AREA_FOR\n");
309dba5824bSPhil Greenway			info.offset = 0;
3109d3f15c6SIngo Weinhold			info.size = (size_t)fBitmap[j]->BitsLength();
311dba5824bSPhil Greenway			info.flags = j;
312dba5824bSPhil Greenway			info.buffer = 0;
313dba5824bSPhil Greenway
3149d3f15c6SIngo Weinhold			if ((status = fBuffers->AddBuffer(info)) != B_OK) {
3156a739773SCodeforEvolution				ERROR("VideoConsumer::CreateBuffers - "
3166a739773SCodeforEvolution					  "ERROR ADDING BUFFER TO GROUP\n");
317dba5824bSPhil Greenway				return status;
3189d3f15c6SIngo Weinhold			}
3199d3f15c6SIngo Weinhold			else
3206a739773SCodeforEvolution				PROGRESS("VideoConsumer::CreateBuffers - "
3216a739773SCodeforEvolution						 "SUCCESSFUL ADD BUFFER TO GROUP\n");
3229d3f15c6SIngo Weinhold		} else {
323afcbccb9SJérôme Duval			ERROR("VideoConsumer::CreateBuffers - ERROR CREATING VIDEO RING "
324afcbccb9SJérôme Duval				"BUFFER: %08" B_PRIx32 "\n", status);
325dba5824bSPhil Greenway			return B_ERROR;
3269d3f15c6SIngo Weinhold		}
327dba5824bSPhil Greenway	}
3289d3f15c6SIngo Weinhold
329f50d7408SDario Casalinuovo	BBuffer* buffList[3];
3309d3f15c6SIngo Weinhold	for (int j = 0; j < 3; j++)
331f50d7408SDario Casalinuovo		buffList[j] = NULL;
3329d3f15c6SIngo Weinhold
3336a739773SCodeforEvolution	status = fBuffers->GetBufferList(3, buffList);
3346a739773SCodeforEvolution	if (status == B_OK)
335dba5824bSPhil Greenway		for (int j = 0; j < 3; j++)
3369d3f15c6SIngo Weinhold			if (buffList[j] != NULL) {
337afcbccb9SJérôme Duval				fBufferMap[j] = buffList[j];
338afcbccb9SJérôme Duval				PROGRESS(" j = %d buffer = %p\n", j, fBufferMap[j]);
3399d3f15c6SIngo Weinhold			} else {
3406a739773SCodeforEvolution				ERROR("VideoConsumer::CreateBuffers "
3416a739773SCodeforEvolution					  "ERROR MAPPING RING BUFFER\n");
342dba5824bSPhil Greenway				return B_ERROR;
343dba5824bSPhil Greenway			}
344dba5824bSPhil Greenway	else
345dba5824bSPhil Greenway		ERROR("VideoConsumer::CreateBuffers ERROR IN GET BUFFER LIST\n");
3469d3f15c6SIngo Weinhold
3476a739773SCodeforEvolution	fFtpBitmap = new BBitmap(BRect(0, 0, xSize - 1, ySize - 1), B_RGB32, false,
3486a739773SCodeforEvolution		false);
3493dd6b9cfSFrançois Revol
350dba5824bSPhil Greenway	FUNCTION("VideoConsumer::CreateBuffers - EXIT\n");
351dba5824bSPhil Greenway	return status;
352dba5824bSPhil Greenway}
353dba5824bSPhil Greenway
354dba5824bSPhil Greenway
355dba5824bSPhil Greenwayvoid
356dba5824bSPhil GreenwayVideoConsumer::DeleteBuffers()
357dba5824bSPhil Greenway{
358dba5824bSPhil Greenway	FUNCTION("VideoConsumer::DeleteBuffers\n");
3599d3f15c6SIngo Weinhold
3609d3f15c6SIngo Weinhold	if (fBuffers) {
3619d3f15c6SIngo Weinhold		delete fBuffers;
3629d3f15c6SIngo Weinhold		fBuffers = NULL;
3639d3f15c6SIngo Weinhold
364dba5824bSPhil Greenway		for (uint32 j = 0; j < 3; j++)
3659d3f15c6SIngo Weinhold			if (fBitmap[j]->IsValid()) {
3669d3f15c6SIngo Weinhold				delete fBitmap[j];
3679d3f15c6SIngo Weinhold				fBitmap[j] = NULL;
368dba5824bSPhil Greenway			}
369dba5824bSPhil Greenway	}
3706a739773SCodeforEvolution
371dba5824bSPhil Greenway	FUNCTION("VideoConsumer::DeleteBuffers - EXIT\n");
372dba5824bSPhil Greenway}
373dba5824bSPhil Greenway
374dba5824bSPhil Greenway
375dba5824bSPhil Greenwaystatus_t
3766a739773SCodeforEvolutionVideoConsumer::Connected(const media_source& producer,
3776a739773SCodeforEvolution	const media_destination& where, const media_format& withFormat,
3786a739773SCodeforEvolution	media_input* outInput)
379dba5824bSPhil Greenway{
380dba5824bSPhil Greenway	FUNCTION("VideoConsumer::Connected\n");
381476fad7fSMatt Madia
3829d3f15c6SIngo Weinhold	fIn.source = producer;
3839d3f15c6SIngo Weinhold	fIn.format = withFormat;
3849d3f15c6SIngo Weinhold	fIn.node = Node();
3859d3f15c6SIngo Weinhold	sprintf(fIn.name, "Video Consumer");
3869d3f15c6SIngo Weinhold	*outInput = fIn;
3879d3f15c6SIngo Weinhold
3889d3f15c6SIngo Weinhold	uint32 userData = 0;
389476fad7fSMatt Madia	int32 changeTag = 1;
3909d3f15c6SIngo Weinhold	if (CreateBuffers(withFormat) == B_OK)
391476fad7fSMatt Madia		BBufferConsumer::SetOutputBuffersFor(producer, fDestination,
3926a739773SCodeforEvolution			fBuffers, (void*)&userData, &changeTag, true);
3939d3f15c6SIngo Weinhold	else {
394dba5824bSPhil Greenway		ERROR("VideoConsumer::Connected - COULDN'T CREATE BUFFERS\n");
395dba5824bSPhil Greenway		return B_ERROR;
396dba5824bSPhil Greenway	}
397dba5824bSPhil Greenway
3989d3f15c6SIngo Weinhold	fConnectionActive = true;
3999d3f15c6SIngo Weinhold
400dba5824bSPhil Greenway	FUNCTION("VideoConsumer::Connected - EXIT\n");
401dba5824bSPhil Greenway	return B_OK;
402dba5824bSPhil Greenway}
403dba5824bSPhil Greenway
404dba5824bSPhil Greenway
405dba5824bSPhil Greenwayvoid
4066a739773SCodeforEvolutionVideoConsumer::Disconnected(const media_source& producer,
4076a739773SCodeforEvolution	const media_destination& where)
408dba5824bSPhil Greenway{
409dba5824bSPhil Greenway	FUNCTION("VideoConsumer::Disconnected\n");
410dba5824bSPhil Greenway
4119d3f15c6SIngo Weinhold	if (where == fIn.destination && producer == fIn.source) {
412dba5824bSPhil Greenway		// disconnect the connection
4139d3f15c6SIngo Weinhold		fIn.source = media_source::null;
4149d3f15c6SIngo Weinhold		delete fFtpBitmap;
4159d3f15c6SIngo Weinhold		fConnectionActive = false;
416dba5824bSPhil Greenway	}
417dba5824bSPhil Greenway
418dba5824bSPhil Greenway}
419dba5824bSPhil Greenway
420dba5824bSPhil Greenway
421dba5824bSPhil Greenwaystatus_t
4229d3f15c6SIngo WeinholdVideoConsumer::AcceptFormat(const media_destination& dest, media_format* format)
423dba5824bSPhil Greenway{
424dba5824bSPhil Greenway	FUNCTION("VideoConsumer::AcceptFormat\n");
425476fad7fSMatt Madia
4269d3f15c6SIngo Weinhold	if (dest != fIn.destination) {
427dba5824bSPhil Greenway		ERROR("VideoConsumer::AcceptFormat - BAD DESTINATION\n");
428476fad7fSMatt Madia		return B_MEDIA_BAD_DESTINATION;
429dba5824bSPhil Greenway	}
4309d3f15c6SIngo Weinhold
431dba5824bSPhil Greenway	if (format->type == B_MEDIA_NO_TYPE)
432dba5824bSPhil Greenway		format->type = B_MEDIA_RAW_VIDEO;
433476fad7fSMatt Madia
4349d3f15c6SIngo Weinhold	if (format->type != B_MEDIA_RAW_VIDEO) {
435dba5824bSPhil Greenway		ERROR("VideoConsumer::AcceptFormat - BAD FORMAT\n");
436dba5824bSPhil Greenway		return B_MEDIA_BAD_FORMAT;
437dba5824bSPhil Greenway	}
438dba5824bSPhil Greenway
4399d3f15c6SIngo Weinhold	if (format->u.raw_video.display.format != B_RGB32
4409d3f15c6SIngo Weinhold		&& format->u.raw_video.display.format != B_RGB16
4419d3f15c6SIngo Weinhold		&& format->u.raw_video.display.format != B_RGB15
4429d3f15c6SIngo Weinhold		&& format->u.raw_video.display.format != B_GRAY8
443476fad7fSMatt Madia		&&
4446a739773SCodeforEvolution		format->u.raw_video.display.format
4456a739773SCodeforEvolution			!= media_raw_video_format::wildcard.display.format) {
446dba5824bSPhil Greenway		ERROR("AcceptFormat - not a format we know about!\n");
447dba5824bSPhil Greenway		return B_MEDIA_BAD_FORMAT;
448dba5824bSPhil Greenway	}
4499d3f15c6SIngo Weinhold
4506a739773SCodeforEvolution	if (format->u.raw_video.display.format
4516a739773SCodeforEvolution		== media_raw_video_format::wildcard.display.format) {
452dba5824bSPhil Greenway		format->u.raw_video.display.format = B_RGB16;
453dba5824bSPhil Greenway	}
454dba5824bSPhil Greenway
455476fad7fSMatt Madia	char formatString[256];
4569d3f15c6SIngo Weinhold	string_for_format(*format, formatString, 256);
4579d3f15c6SIngo Weinhold	FUNCTION("VideoConsumer::AcceptFormat: %s\n", formatString);
458dba5824bSPhil Greenway
459dba5824bSPhil Greenway	return B_OK;
460dba5824bSPhil Greenway}
461dba5824bSPhil Greenway
462dba5824bSPhil Greenway
463dba5824bSPhil Greenwaystatus_t
4649d3f15c6SIngo WeinholdVideoConsumer::GetNextInput(int32* cookie, media_input* outInput)
465dba5824bSPhil Greenway{
466dba5824bSPhil Greenway	FUNCTION("VideoConsumer::GetNextInput\n");
467dba5824bSPhil Greenway
468dba5824bSPhil Greenway	// custom build a destination for this connection
469dba5824bSPhil Greenway	// put connection number in id
470dba5824bSPhil Greenway
4719d3f15c6SIngo Weinhold	if (*cookie < 1) {
4729d3f15c6SIngo Weinhold		fIn.node = Node();
4739d3f15c6SIngo Weinhold		fIn.destination.id = *cookie;
4749d3f15c6SIngo Weinhold		sprintf(fIn.name, "Video Consumer");
4759d3f15c6SIngo Weinhold		*outInput = fIn;
476dba5824bSPhil Greenway		(*cookie)++;
4776a739773SCodeforEvolution
478dba5824bSPhil Greenway		return B_OK;
479dba5824bSPhil Greenway	}
4806a739773SCodeforEvolution
4816a739773SCodeforEvolution	ERROR("VideoConsumer::GetNextInput - - BAD INDEX\n");
4826a739773SCodeforEvolution	return B_MEDIA_BAD_DESTINATION;
483dba5824bSPhil Greenway}
484dba5824bSPhil Greenway
485dba5824bSPhil Greenway
486dba5824bSPhil Greenwayvoid
487dba5824bSPhil GreenwayVideoConsumer::DisposeInputCookie(int32 /*cookie*/)
488dba5824bSPhil Greenway{
489dba5824bSPhil Greenway}
490dba5824bSPhil Greenway
491dba5824bSPhil Greenway
492dba5824bSPhil Greenwaystatus_t
4936a739773SCodeforEvolutionVideoConsumer::GetLatencyFor(const media_destination& forWhom,
4946a739773SCodeforEvolution	bigtime_t* outLatency, media_node_id* out_timesource)
495dba5824bSPhil Greenway{
496dba5824bSPhil Greenway	FUNCTION("VideoConsumer::GetLatencyFor\n");
497476fad7fSMatt Madia
4989d3f15c6SIngo Weinhold	if (forWhom != fIn.destination)
499dba5824bSPhil Greenway		return B_MEDIA_BAD_DESTINATION;
500476fad7fSMatt Madia
5019d3f15c6SIngo Weinhold	*outLatency = fMyLatency;
502dba5824bSPhil Greenway	*out_timesource = TimeSource()->ID();
503dba5824bSPhil Greenway	return B_OK;
504dba5824bSPhil Greenway}
505dba5824bSPhil Greenway
506dba5824bSPhil Greenway
507dba5824bSPhil Greenwaystatus_t
5086a739773SCodeforEvolutionVideoConsumer::FormatChanged(const media_source& producer,
5096a739773SCodeforEvolution	const media_destination& consumer, int32 fromChangeCount,
5106a739773SCodeforEvolution	const media_format& format)
511dba5824bSPhil Greenway{
512dba5824bSPhil Greenway	FUNCTION("VideoConsumer::FormatChanged\n");
5139d3f15c6SIngo Weinhold
5149d3f15c6SIngo Weinhold	if (consumer != fIn.destination)
515dba5824bSPhil Greenway		return B_MEDIA_BAD_DESTINATION;
516dba5824bSPhil Greenway
5179d3f15c6SIngo Weinhold	if (producer != fIn.source)
518dba5824bSPhil Greenway		return B_MEDIA_BAD_SOURCE;
519dba5824bSPhil Greenway
5209d3f15c6SIngo Weinhold	fIn.format = format;
5219d3f15c6SIngo Weinhold
522dba5824bSPhil Greenway	return CreateBuffers(format);
523dba5824bSPhil Greenway}
524dba5824bSPhil Greenway
525dba5824bSPhil Greenway
526dba5824bSPhil Greenwayvoid
5279d3f15c6SIngo WeinholdVideoConsumer::HandleEvent(const media_timed_event* event, bigtime_t lateness,
528dba5824bSPhil Greenway	bool realTimeEvent)
529dba5824bSPhil Greenway{
530dba5824bSPhil Greenway	LOOP("VideoConsumer::HandleEvent\n");
531476fad7fSMatt Madia
5329d3f15c6SIngo Weinhold	BBuffer* buffer;
5339d3f15c6SIngo Weinhold
5349d3f15c6SIngo Weinhold	switch (event->type) {
535dba5824bSPhil Greenway		case BTimedEventQueue::B_START:
536dba5824bSPhil Greenway			PROGRESS("VideoConsumer::HandleEvent - START\n");
537dba5824bSPhil Greenway			break;
5389d3f15c6SIngo Weinhold
539dba5824bSPhil Greenway		case BTimedEventQueue::B_STOP:
540dba5824bSPhil Greenway			PROGRESS("VideoConsumer::HandleEvent - STOP\n");
5416a739773SCodeforEvolution			EventQueue()->FlushEvents(event->event_time,
5426a739773SCodeforEvolution				BTimedEventQueue::B_ALWAYS, true,
5436a739773SCodeforEvolution				BTimedEventQueue::B_HANDLE_BUFFER);
544dba5824bSPhil Greenway			break;
5459d3f15c6SIngo Weinhold
546dba5824bSPhil Greenway		case BTimedEventQueue::B_USER_EVENT:
547dba5824bSPhil Greenway			PROGRESS("VideoConsumer::HandleEvent - USER EVENT\n");
5489d3f15c6SIngo Weinhold			if (RunState() == B_STARTED) {
5499d3f15c6SIngo Weinhold				fTimeToFtp = true;
5509d3f15c6SIngo Weinhold				PROGRESS("Pushing user event for %.4f, time now %.4f\n",
5519d3f15c6SIngo Weinhold					(event->event_time + fRate) / M1, event->event_time/M1);
5529d3f15c6SIngo Weinhold				media_timed_event newEvent(event->event_time + fRate,
5539d3f15c6SIngo Weinhold					BTimedEventQueue::B_USER_EVENT);
554dba5824bSPhil Greenway				EventQueue()->AddEvent(newEvent);
555dba5824bSPhil Greenway			}
5569d3f15c6SIngo Weinhold			break;
5579d3f15c6SIngo Weinhold
558dba5824bSPhil Greenway		case BTimedEventQueue::B_HANDLE_BUFFER:
5599d3f15c6SIngo Weinhold		{
560dba5824bSPhil Greenway			LOOP("VideoConsumer::HandleEvent - HANDLE BUFFER\n");
5616a739773SCodeforEvolution			buffer = (BBuffer*)event->pointer;
5629d3f15c6SIngo Weinhold			if (RunState() == B_STARTED && fConnectionActive) {
563dba5824bSPhil Greenway				// see if this is one of our buffers
564dba5824bSPhil Greenway				uint32 index = 0;
5659d3f15c6SIngo Weinhold				fOurBuffers = true;
5669d3f15c6SIngo Weinhold				while (index < 3)
567afcbccb9SJérôme Duval					if (buffer == fBufferMap[index])
568dba5824bSPhil Greenway						break;
569dba5824bSPhil Greenway					else
570dba5824bSPhil Greenway						index++;
5719d3f15c6SIngo Weinhold
5729d3f15c6SIngo Weinhold				if (index == 3) {
573dba5824bSPhil Greenway					// no, buffers belong to consumer
5749d3f15c6SIngo Weinhold					fOurBuffers = false;
575dba5824bSPhil Greenway					index = 0;
576dba5824bSPhil Greenway				}
577476fad7fSMatt Madia
5789d3f15c6SIngo Weinhold				if (fFtpComplete && fTimeToFtp) {
5796a739773SCodeforEvolution					PROGRESS("VidConsumer::HandleEvent - "
5806a739773SCodeforEvolution							 "SPAWNING FTP THREAD\n");
5819d3f15c6SIngo Weinhold					fTimeToFtp = false;
5829d3f15c6SIngo Weinhold					fFtpComplete = false;
5836a739773SCodeforEvolution					memcpy(fFtpBitmap->Bits(), buffer->Data(),
5846a739773SCodeforEvolution						fFtpBitmap->BitsLength());
5856a739773SCodeforEvolution					fFtpThread = spawn_thread(FtpRun, "Video Window Ftp",
5866a739773SCodeforEvolution						B_NORMAL_PRIORITY, this);
587476fad7fSMatt Madia					resume_thread(fFtpThread);
588dba5824bSPhil Greenway				}
589dba5824bSPhil Greenway
5909d3f15c6SIngo Weinhold				if ((RunMode() == B_OFFLINE)
5916a739773SCodeforEvolution					|| ((TimeSource()->Now() >
5926a739773SCodeforEvolution						(buffer->Header()->start_time - JITTER))
5936a739773SCodeforEvolution					&& (TimeSource()->Now() <
5946a739773SCodeforEvolution					   (buffer->Header()->start_time + JITTER)))) {
5959d3f15c6SIngo Weinhold					if (!fOurBuffers)
596dba5824bSPhil Greenway						// not our buffers, so we need to copy
5976a739773SCodeforEvolution						memcpy(fBitmap[index]->Bits(), buffer->Data(),
5986a739773SCodeforEvolution							fBitmap[index]->BitsLength());
5999d3f15c6SIngo Weinhold
6009d3f15c6SIngo Weinhold					if (fWindow->Lock()) {
601dba5824bSPhil Greenway						uint32 flags;
6029d3f15c6SIngo Weinhold						if ((fBitmap[index]->ColorSpace() == B_GRAY8) &&
6036a739773SCodeforEvolution							!bitmaps_support_space(fBitmap[index]->ColorSpace(),
6046a739773SCodeforEvolution								&flags)) {
6056a739773SCodeforEvolution							// handle mapping of GRAY8 until app server
6066a739773SCodeforEvolution							// knows how
6079d3f15c6SIngo Weinhold							uint32* start = (uint32*)fBitmap[index]->Bits();
6089d3f15c6SIngo Weinhold							int32 size = fBitmap[index]->BitsLength();
6099d3f15c6SIngo Weinhold							uint32* end = start + size / 4;
6109d3f15c6SIngo Weinhold							for (uint32* p = start; p < end; p++)
611476fad7fSMatt Madia								*p = (*p >> 3) & 0x1f1f1f1f;
612dba5824bSPhil Greenway						}
6139d3f15c6SIngo Weinhold
61445c2e6b8SFrançois Revol						fView->DrawBitmap(fBitmap[index], fView->Bounds());
6159d3f15c6SIngo Weinhold						fWindow->Unlock();
616dba5824bSPhil Greenway					}
617dba5824bSPhil Greenway				}
618dba5824bSPhil Greenway				else
619dba5824bSPhil Greenway					PROGRESS("VidConsumer::HandleEvent - DROPPED FRAME\n");
620dba5824bSPhil Greenway				buffer->Recycle();
621dba5824bSPhil Greenway			}
622dba5824bSPhil Greenway			else
623dba5824bSPhil Greenway				buffer->Recycle();
624dba5824bSPhil Greenway			break;
6259d3f15c6SIngo Weinhold		}
6269d3f15c6SIngo Weinhold
627dba5824bSPhil Greenway		default:
628dba5824bSPhil Greenway			ERROR("VideoConsumer::HandleEvent - BAD EVENT\n");
629dba5824bSPhil Greenway			break;
630476fad7fSMatt Madia	}
631dba5824bSPhil Greenway}
632dba5824bSPhil Greenway
633dba5824bSPhil Greenway
634dba5824bSPhil Greenwaystatus_t
6359d3f15c6SIngo WeinholdVideoConsumer::FtpRun(void* data)
636dba5824bSPhil Greenway{
637dba5824bSPhil Greenway	FUNCTION("VideoConsumer::FtpRun\n");
638476fad7fSMatt Madia
6396a739773SCodeforEvolution	((VideoConsumer*)data)->FtpThread();
640dba5824bSPhil Greenway
641dba5824bSPhil Greenway	return 0;
642dba5824bSPhil Greenway}
643dba5824bSPhil Greenway
644dba5824bSPhil Greenway
645dba5824bSPhil Greenwayvoid
646dba5824bSPhil GreenwayVideoConsumer::FtpThread()
647dba5824bSPhil Greenway{
648f5e3b474SStephan Aßmus	char fullPath[B_PATH_NAME_LENGTH];
649dba5824bSPhil Greenway	FUNCTION("VideoConsumer::FtpThread\n");
650f5e3b474SStephan Aßmus	if (fUploadClient == 2) {
651f5e3b474SStephan Aßmus		// 64 + 64 = 128 max
6526a739773SCodeforEvolution		snprintf(fullPath, B_PATH_NAME_LENGTH, "%s/%s", fDirectoryText,
6536a739773SCodeforEvolution			fFileNameText);
654f5e3b474SStephan Aßmus		LocalSave(fullPath, fFtpBitmap);
655f5e3b474SStephan Aßmus	} else if (LocalSave(fFileNameText, fFtpBitmap) == B_OK)
6569d3f15c6SIngo Weinhold		FtpSave(fFileNameText);
6579d3f15c6SIngo Weinhold
658dba5824bSPhil Greenway#if 0
659dba5824bSPhil Greenway	// save a small version, too
6609d3f15c6SIngo Weinhold	BBitmap* b = new BBitmap(BRect(0,0,159,119), B_RGB32, true, false);
6619d3f15c6SIngo Weinhold	BView* v = new BView(BRect(0,0,159,119), "SmallView 1", 0, B_WILL_DRAW);
662dba5824bSPhil Greenway	b->AddChild(v);
663dba5824bSPhil Greenway
664dba5824bSPhil Greenway	b->Lock();
6659d3f15c6SIngo Weinhold	v->DrawBitmap(fFtpBitmap, v->Frame());
666dba5824bSPhil Greenway	v->Sync();
667476fad7fSMatt Madia	b->Unlock();
668dba5824bSPhil Greenway
669476fad7fSMatt Madia	if (LocalSave("small.jpg", b) == B_OK)
670dba5824bSPhil Greenway		FtpSave("small.jpg");
671476fad7fSMatt Madia
672dba5824bSPhil Greenway	delete b;
673dba5824bSPhil Greenway#endif
674476fad7fSMatt Madia
675476fad7fSMatt Madia	fFtpComplete = true;
676dba5824bSPhil Greenway}
677dba5824bSPhil Greenway
678dba5824bSPhil Greenway
679dba5824bSPhil Greenwayvoid
680241dbd37SFrançois RevolVideoConsumer::UpdateFtpStatus(const char* status)
681dba5824bSPhil Greenway{
682dba5824bSPhil Greenway	printf("FTP STATUS: %s\n",status);
6839d3f15c6SIngo Weinhold	if (fView->Window()->Lock()) {
6849d3f15c6SIngo Weinhold		fStatusLine->SetText(status);
6859d3f15c6SIngo Weinhold		fView->Window()->Unlock();
686dba5824bSPhil Greenway	}
687dba5824bSPhil Greenway}
688dba5824bSPhil Greenway
689dba5824bSPhil Greenway
690dba5824bSPhil Greenwaystatus_t
6919d3f15c6SIngo WeinholdVideoConsumer::LocalSave(char* filename, BBitmap* bitmap)
692dba5824bSPhil Greenway{
6939d3f15c6SIngo Weinhold	BFile* output;
6949d3f15c6SIngo Weinhold
695c4f9b1d1SStephan Aßmus	UpdateFtpStatus(B_TRANSLATE("Capturing Image" B_UTF8_ELLIPSIS));
696dba5824bSPhil Greenway
697dba5824bSPhil Greenway	/* save a local copy of the image in the requested format */
6989d3f15c6SIngo Weinhold	output = new BFile();
6996a739773SCodeforEvolution	if (output->SetTo(filename, B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE)
7006a739773SCodeforEvolution		== B_NO_ERROR) {
701dba5824bSPhil Greenway		BBitmapStream input(bitmap);
7026a739773SCodeforEvolution		status_t err = BTranslatorRoster::Default()->Translate(&input, NULL,
7036a739773SCodeforEvolution			NULL, output, fImageFormat);
704a8aeb8a9SAdrien Destugues		if (err == B_OK) {
705a8aeb8a9SAdrien Destugues			err = SetFileType(output, fTranslator, fImageFormat);
706a8aeb8a9SAdrien Destugues			if (err != B_OK)
7076a739773SCodeforEvolution				UpdateFtpStatus(
7086a739773SCodeforEvolution					B_TRANSLATE("Error setting type of output file"));
709a8aeb8a9SAdrien Destugues		}
710a8aeb8a9SAdrien Destugues		else
711a8aeb8a9SAdrien Destugues			UpdateFtpStatus(B_TRANSLATE("Error writing output file"));
7129d3f15c6SIngo Weinhold
7139d3f15c6SIngo Weinhold		input.DetachBitmap(&bitmap);
7149d3f15c6SIngo Weinhold		output->Unset();
7159d3f15c6SIngo Weinhold		delete output;
7166a739773SCodeforEvolution
7179d3f15c6SIngo Weinhold		return B_OK;
718a8aeb8a9SAdrien Destugues	}
7196a739773SCodeforEvolution
7206a739773SCodeforEvolution	UpdateFtpStatus(B_TRANSLATE("Error creating output file"));
7216a739773SCodeforEvolution	return B_ERROR;
722dba5824bSPhil Greenway}
723dba5824bSPhil Greenway
724dba5824bSPhil Greenway
725dba5824bSPhil Greenwaystatus_t
7269d3f15c6SIngo WeinholdVideoConsumer::FtpSave(char* filename)
727dba5824bSPhil Greenway{
7286a739773SCodeforEvolution	FileUploadClient* ftp;
729476fad7fSMatt Madia
730e3145a8dSFrançois Revol	//XXX: make that cleaner
731e3145a8dSFrançois Revol	switch (fUploadClient) {
732e3145a8dSFrançois Revol		case 0:
733e3145a8dSFrançois Revol			ftp = new FtpClient;
734e3145a8dSFrançois Revol			break;
735e3145a8dSFrançois Revol		case 1:
736e3145a8dSFrançois Revol			ftp = new SftpClient;
737e3145a8dSFrançois Revol			break;
738f5e3b474SStephan Aßmus		case 2:
739f5e3b474SStephan Aßmus			return B_OK;
740e3145a8dSFrançois Revol		default:
741476fad7fSMatt Madia			fprintf(stderr, B_TRANSLATE("invalid upload client %ld\n"),
742c4f9b1d1SStephan Aßmus				fUploadClient);
743e3145a8dSFrançois Revol			return EINVAL;
744e3145a8dSFrançois Revol	}
7459d3f15c6SIngo Weinhold
746e3145a8dSFrançois Revol	ftp->SetPassive(fPassiveFtp);
7479d3f15c6SIngo Weinhold		// ftp the local file to our web site
748dba5824bSPhil Greenway
749c4f9b1d1SStephan Aßmus	UpdateFtpStatus(B_TRANSLATE("Logging in" B_UTF8_ELLIPSIS));
750476fad7fSMatt Madia	if (ftp->Connect((string)fServerText, (string)fLoginText,
751c4f9b1d1SStephan Aßmus		(string)fPasswordText)) {
7529d3f15c6SIngo Weinhold		// connect to server
753c4f9b1d1SStephan Aßmus		UpdateFtpStatus(B_TRANSLATE("Connected" B_UTF8_ELLIPSIS));
7549d3f15c6SIngo Weinhold
755e3145a8dSFrançois Revol		if (ftp->ChangeDir((string)fDirectoryText)) {
7569d3f15c6SIngo Weinhold			// cd to the desired directory
7572824c5d3SAdrien Destugues			UpdateFtpStatus(B_TRANSLATE("Upload" B_UTF8_ELLIPSIS));
7589d3f15c6SIngo Weinhold
759e3145a8dSFrançois Revol			if (ftp->PutFile((string)filename, (string)"temp")) {
7609d3f15c6SIngo Weinhold				// send the file to the server
7616298fd45SFrançois Revol
76261946f58SFrançois Revol				ftp->Chmod((string)"temp", (string)"644");
7636298fd45SFrançois Revol				// make it world readable
7646298fd45SFrançois Revol
765c4f9b1d1SStephan Aßmus				UpdateFtpStatus(B_TRANSLATE("Renaming" B_UTF8_ELLIPSIS));
7669d3f15c6SIngo Weinhold
767e3145a8dSFrançois Revol				if (ftp->MoveFile((string)"temp", (string)filename)) {
7689d3f15c6SIngo Weinhold					// change to the desired name
769dba5824bSPhil Greenway					uint32 time = real_time_clock();
770dba5824bSPhil Greenway					char s[80];
771c4f9b1d1SStephan Aßmus					strcpy(s, B_TRANSLATE("Last Capture: "));
772afcbccb9SJérôme Duval					strcat(s, ctime((const time_t*)&time));
7739d3f15c6SIngo Weinhold					s[strlen(s) - 1] = 0;
774dba5824bSPhil Greenway					UpdateFtpStatus(s);
775e3145a8dSFrançois Revol					delete ftp;
776dba5824bSPhil Greenway					return B_OK;
7772824c5d3SAdrien Destugues				} else
778c4f9b1d1SStephan Aßmus					UpdateFtpStatus(B_TRANSLATE("Rename failed"));
7792824c5d3SAdrien Destugues			} else
7802824c5d3SAdrien Destugues				UpdateFtpStatus(B_TRANSLATE("File upload failed"));
7812824c5d3SAdrien Destugues		} else
782c4f9b1d1SStephan Aßmus			UpdateFtpStatus(B_TRANSLATE("Couldn't find requested directory on "
783c4f9b1d1SStephan Aßmus				"server"));
7849d3f15c6SIngo Weinhold	}
7859d3f15c6SIngo Weinhold	else
786c4f9b1d1SStephan Aßmus		UpdateFtpStatus(B_TRANSLATE("Server login failed"));
7879d3f15c6SIngo Weinhold
788e3145a8dSFrançois Revol	delete ftp;
789dba5824bSPhil Greenway	return B_ERROR;
790dba5824bSPhil Greenway}
791dba5824bSPhil Greenway
792dba5824bSPhil Greenway
793dba5824bSPhil Greenwaystatus_t
794476fad7fSMatt MadiaSetFileType(BFile* file, int32 translator, uint32 type)
795476fad7fSMatt Madia{
7969d3f15c6SIngo Weinhold	translation_format* formats;
7979d3f15c6SIngo Weinhold	int32 count;
7989d3f15c6SIngo Weinhold
7999d3f15c6SIngo Weinhold	status_t err = BTranslatorRoster::Default()->GetOutputFormats(translator,
8006a739773SCodeforEvolution		(const translation_format**)&formats, &count);
8019d3f15c6SIngo Weinhold	if (err < B_OK)
8029d3f15c6SIngo Weinhold		return err;
8039d3f15c6SIngo Weinhold
8049d3f15c6SIngo Weinhold	const char* mime = NULL;
8059d3f15c6SIngo Weinhold	for (int ix = 0; ix < count; ix++) {
8069d3f15c6SIngo Weinhold		if (formats[ix].type == type) {
8079d3f15c6SIngo Weinhold			mime = formats[ix].MIME;
8089d3f15c6SIngo Weinhold			break;
8099d3f15c6SIngo Weinhold		}
8109d3f15c6SIngo Weinhold	}
811dba5824bSPhil Greenway
8129d3f15c6SIngo Weinhold	if (mime == NULL) {
8139d3f15c6SIngo Weinhold		/* this should not happen, but being defensive might be prudent */
8149d3f15c6SIngo Weinhold		return B_ERROR;
8159d3f15c6SIngo Weinhold	}
816dba5824bSPhil Greenway
8179d3f15c6SIngo Weinhold	/* use BNodeInfo to set the file type */
8189d3f15c6SIngo Weinhold	BNodeInfo ninfo(file);
8199d3f15c6SIngo Weinhold	return ninfo.SetType(mime);
8209d3f15c6SIngo Weinhold}
821