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 */
66a739773SCodeforEvolution
76a739773SCodeforEvolution
8dba5824bSPhil Greenway#include "CodyCam.h"
9dba5824bSPhil Greenway
10dba5824bSPhil Greenway#include <stdio.h>
11dba5824bSPhil Greenway#include <string.h>
129d3f15c6SIngo Weinhold#include <unistd.h>
139d3f15c6SIngo Weinhold
149d3f15c6SIngo Weinhold#include <Alert.h>
15dba5824bSPhil Greenway#include <Button.h>
16b90c8010SJonas Sundström#include <Catalog.h>
17fc4d98a2SPhilippe Saint-Pierre#include <FindDirectory.h>
188ceeae63SAlex Wilson#include <LayoutBuilder.h>
199d3f15c6SIngo Weinhold#include <MediaDefs.h>
209d3f15c6SIngo Weinhold#include <MediaNode.h>
219d3f15c6SIngo Weinhold#include <MediaRoster.h>
229d3f15c6SIngo Weinhold#include <MediaTheme.h>
23dba5824bSPhil Greenway#include <Menu.h>
24dba5824bSPhil Greenway#include <MenuBar.h>
259d3f15c6SIngo Weinhold#include <MenuItem.h>
26b78760b9SPhilippe Saint-Pierre#include <Path.h>
27dba5824bSPhil Greenway#include <PopUpMenu.h>
28dba5824bSPhil Greenway#include <scheduler.h>
299d3f15c6SIngo Weinhold#include <TabView.h>
30dba5824bSPhil Greenway#include <TextControl.h>
319d3f15c6SIngo Weinhold#include <TimeSource.h>
329c250a42SRyan Leavengood#include <TranslationUtils.h>
336a739773SCodeforEvolution#include <TranslatorFormats.h>
34dba5824bSPhil Greenway
35546208a5SOliver Tappe#undef B_TRANSLATION_CONTEXT
36546208a5SOliver Tappe#define B_TRANSLATION_CONTEXT "CodyCam"
37c4f9b1d1SStephan Aßmus
38dba5824bSPhil Greenway#define VIDEO_SIZE_X 320
39dba5824bSPhil Greenway#define VIDEO_SIZE_Y 240
40dba5824bSPhil Greenway
41dba5824bSPhil Greenway#define WINDOW_SIZE_X (VIDEO_SIZE_X + 80)
42dba5824bSPhil Greenway#define WINDOW_SIZE_Y (VIDEO_SIZE_Y + 230)
43dba5824bSPhil Greenway
44dba5824bSPhil Greenway#define WINDOW_OFFSET_X 28
45dba5824bSPhil Greenway#define WINDOW_OFFSET_Y 28
46dba5824bSPhil Greenway
47dba5824bSPhil Greenway#define	CALL		printf
48dba5824bSPhil Greenway#define ERROR		printf
49dba5824bSPhil Greenway#define FTPINFO		printf
50dba5824bSPhil Greenway#define	INFO		printf
51dba5824bSPhil Greenway
52dba5824bSPhil Greenway
539d3f15c6SIngo Weinhold// Utility functions
549d3f15c6SIngo Weinhold
558ceeae63SAlex Wilsonnamespace {
568ceeae63SAlex Wilson
578ceeae63SAlex Wilson// functions for EnumeratedStringValueSettings
588ceeae63SAlex Wilson
591615cec9SFredrik Modéenconst char*
601615cec9SFredrik ModéenCaptureRateAt(int32 i)
618ceeae63SAlex Wilson{
628ceeae63SAlex Wilson	return (i >= 0 && i < kCaptureRatesCount) ? kCaptureRates[i].name : NULL;
638ceeae63SAlex Wilson}
648ceeae63SAlex Wilson
658ceeae63SAlex Wilson
661615cec9SFredrik Modéenconst char*
671615cec9SFredrik ModéenUploadClientAt(int32 i)
688ceeae63SAlex Wilson{
698ceeae63SAlex Wilson	return (i >= 0 && i < kUploadClientsCount) ? kUploadClients[i] : NULL;
708ceeae63SAlex Wilson}
718ceeae63SAlex Wilson
728ceeae63SAlex Wilson
738ceeae63SAlex Wilson}; // end anonymous namespace
748ceeae63SAlex Wilson
758ceeae63SAlex Wilson
768ceeae63SAlex Wilson
779d3f15c6SIngo Weinhold//	#pragma mark -
789d3f15c6SIngo Weinhold
799d3f15c6SIngo Weinhold
809d3f15c6SIngo WeinholdCodyCam::CodyCam()
818ceeae63SAlex Wilson	:
82560ff447SJonas Sundström	BApplication("application/x-vnd.Haiku-CodyCam"),
83dba5824bSPhil Greenway	fMediaRoster(NULL),
84dba5824bSPhil Greenway	fVideoConsumer(NULL),
85dba5824bSPhil Greenway	fWindow(NULL),
86dba5824bSPhil Greenway	fPort(0),
87be8fa2fbSAdrien Destugues	fVideoControlWindow(NULL)
88dba5824bSPhil Greenway{
89c4f9b1d1SStephan Aßmus	int32 index = 0;
908ceeae63SAlex Wilson	kCaptureRates[index++].name = B_TRANSLATE("Every 15 seconds");
918ceeae63SAlex Wilson	kCaptureRates[index++].name = B_TRANSLATE("Every 30 seconds");
928ceeae63SAlex Wilson	kCaptureRates[index++].name = B_TRANSLATE("Every minute");
938ceeae63SAlex Wilson	kCaptureRates[index++].name = B_TRANSLATE("Every 5 minutes");
948ceeae63SAlex Wilson	kCaptureRates[index++].name = B_TRANSLATE("Every 10 minutes");
958ceeae63SAlex Wilson	kCaptureRates[index++].name = B_TRANSLATE("Every 15 minutes");
968ceeae63SAlex Wilson	kCaptureRates[index++].name = B_TRANSLATE("Every 30 minutes");
978ceeae63SAlex Wilson	kCaptureRates[index++].name = B_TRANSLATE("Every hour");
988ceeae63SAlex Wilson	kCaptureRates[index++].name = B_TRANSLATE("Every 2 hours");
998ceeae63SAlex Wilson	kCaptureRates[index++].name = B_TRANSLATE("Every 4 hours");
1008ceeae63SAlex Wilson	kCaptureRates[index++].name = B_TRANSLATE("Every 8 hours");
1018ceeae63SAlex Wilson	kCaptureRates[index++].name = B_TRANSLATE("Every 24 hours");
1028ceeae63SAlex Wilson	kCaptureRates[index++].name = B_TRANSLATE("Never");
103c4f9b1d1SStephan Aßmus
104c4f9b1d1SStephan Aßmus	index = 0;
1058ceeae63SAlex Wilson	kUploadClients[index++] = B_TRANSLATE("FTP");
1068ceeae63SAlex Wilson	kUploadClients[index++] = B_TRANSLATE("SFTP");
1078ceeae63SAlex Wilson	kUploadClients[index++] = B_TRANSLATE("Local");
108c4f9b1d1SStephan Aßmus
109b78760b9SPhilippe Saint-Pierre	BPath homeDir;
110b78760b9SPhilippe Saint-Pierre	if (find_directory(B_USER_DIRECTORY, &homeDir) != B_OK)
111b78760b9SPhilippe Saint-Pierre		homeDir.SetTo("/boot/home");
112b78760b9SPhilippe Saint-Pierre
113b78760b9SPhilippe Saint-Pierre	chdir(homeDir.Path());
114dba5824bSPhil Greenway}
115dba5824bSPhil Greenway
116dba5824bSPhil Greenway
117dba5824bSPhil GreenwayCodyCam::~CodyCam()
118dba5824bSPhil Greenway{
119dba5824bSPhil Greenway	CALL("CodyCam::~CodyCam\n");
120dba5824bSPhil Greenway
121dba5824bSPhil Greenway	// release the video consumer node
122dba5824bSPhil Greenway	// the consumer node cleans up the window
123dba5824bSPhil Greenway	if (fVideoConsumer) {
124dba5824bSPhil Greenway		fVideoConsumer->Release();
125dba5824bSPhil Greenway		fVideoConsumer = NULL;
126dba5824bSPhil Greenway	}
1277974d3dcSStephan Aßmus
128dba5824bSPhil Greenway	CALL("CodyCam::~CodyCam - EXIT\n");
129dba5824bSPhil Greenway}
130dba5824bSPhil Greenway
131dba5824bSPhil Greenway
1327974d3dcSStephan Aßmusvoid
133dba5824bSPhil GreenwayCodyCam::ReadyToRun()
134dba5824bSPhil Greenway{
1353c5208e4SHumdinger	fWindow = new VideoWindow(
136560ff447SJonas Sundström		(const char*) B_TRANSLATE_SYSTEM_NAME("CodyCam"), B_TITLED_WINDOW,
137a325242dSHumdinger		B_NOT_ZOOMABLE | B_NOT_V_RESIZABLE
138a325242dSHumdinger		| B_AUTO_UPDATE_SIZE_LIMITS, &fPort);
1399d3f15c6SIngo Weinhold
140b3b96925SAdrien Destugues	if (_SetUpNodes() != B_OK)
1411615cec9SFredrik Modéen		fWindow->ToggleMenuOnOff();
1429d3f15c6SIngo Weinhold
1439d3f15c6SIngo Weinhold	((VideoWindow*)fWindow)->ApplyControls();
144dba5824bSPhil Greenway}
145dba5824bSPhil Greenway
1469d3f15c6SIngo Weinhold
1477974d3dcSStephan Aßmusbool
148dba5824bSPhil GreenwayCodyCam::QuitRequested()
149dba5824bSPhil Greenway{
1509d3f15c6SIngo Weinhold	_TearDownNodes();
151dba5824bSPhil Greenway	snooze(100000);
1527974d3dcSStephan Aßmus
153dba5824bSPhil Greenway	return true;
154dba5824bSPhil Greenway}
155dba5824bSPhil Greenway
156dba5824bSPhil Greenway
157dba5824bSPhil Greenwayvoid
1586a739773SCodeforEvolutionCodyCam::MessageReceived(BMessage* message)
159dba5824bSPhil Greenway{
1609d3f15c6SIngo Weinhold	switch (message->what) {
161dba5824bSPhil Greenway		case msg_start:
162dba5824bSPhil Greenway		{
163c4f9b1d1SStephan Aßmus			BTimeSource* timeSource = fMediaRoster->MakeTimeSourceFor(
164c4f9b1d1SStephan Aßmus				fTimeSourceNode);
165dba5824bSPhil Greenway			bigtime_t real = BTimeSource::RealTime();
166dba5824bSPhil Greenway			bigtime_t perf = timeSource->PerformanceTimeFor(real) + 10000;
167dba5824bSPhil Greenway			status_t status = fMediaRoster->StartNode(fProducerNode, perf);
168dba5824bSPhil Greenway			if (status != B_OK)
169dba5824bSPhil Greenway				ERROR("error starting producer!");
170dba5824bSPhil Greenway			timeSource->Release();
171dba5824bSPhil Greenway			break;
172dba5824bSPhil Greenway		}
1739d3f15c6SIngo Weinhold
174dba5824bSPhil Greenway		case msg_stop:
175dba5824bSPhil Greenway			fMediaRoster->StopNode(fProducerNode, 0, true);
176dba5824bSPhil Greenway			break;
1779d3f15c6SIngo Weinhold
178dba5824bSPhil Greenway		case msg_video:
179dba5824bSPhil Greenway		{
1809d3f15c6SIngo Weinhold			if (fVideoControlWindow) {
1819d3f15c6SIngo Weinhold				fVideoControlWindow->Activate();
182dba5824bSPhil Greenway				break;
183dba5824bSPhil Greenway			}
1849d3f15c6SIngo Weinhold			BParameterWeb* web = NULL;
1859d3f15c6SIngo Weinhold			BView* view = NULL;
186dba5824bSPhil Greenway			media_node node = fProducerNode;
187dba5824bSPhil Greenway			status_t err = fMediaRoster->GetParameterWebFor(node, &web);
1889d3f15c6SIngo Weinhold			if (err >= B_OK && web != NULL) {
189dba5824bSPhil Greenway				view = BMediaTheme::ViewFor(web);
1903c5208e4SHumdinger				fVideoControlWindow = new ControlWindow(view, node);
191476fad7fSMatt Madia				fMediaRoster->StartWatching(BMessenger(NULL,
192c4f9b1d1SStephan Aßmus					fVideoControlWindow), node,	B_MEDIA_WEB_CHANGED);
1939d3f15c6SIngo Weinhold				fVideoControlWindow->Show();
194dba5824bSPhil Greenway			}
195dba5824bSPhil Greenway			break;
196dba5824bSPhil Greenway		}
1979d3f15c6SIngo Weinhold
198dba5824bSPhil Greenway		case msg_control_win:
199dba5824bSPhil Greenway			// our control window is being asked to go away
200dba5824bSPhil Greenway			// set our pointer to NULL
2019d3f15c6SIngo Weinhold			fVideoControlWindow = NULL;
202dba5824bSPhil Greenway			break;
2039d3f15c6SIngo Weinhold
204dba5824bSPhil Greenway		default:
205dba5824bSPhil Greenway			BApplication::MessageReceived(message);
206dba5824bSPhil Greenway			break;
207dba5824bSPhil Greenway	}
208dba5824bSPhil Greenway}
209dba5824bSPhil Greenway
210dba5824bSPhil Greenway
2117974d3dcSStephan Aßmusstatus_t
2129d3f15c6SIngo WeinholdCodyCam::_SetUpNodes()
213dba5824bSPhil Greenway{
214dba5824bSPhil Greenway	status_t status = B_OK;
215dba5824bSPhil Greenway
216dba5824bSPhil Greenway	/* find the media roster */
217dba5824bSPhil Greenway	fMediaRoster = BMediaRoster::Roster(&status);
218dba5824bSPhil Greenway	if (status != B_OK) {
219b3b96925SAdrien Destugues		fWindow->ErrorAlert(B_TRANSLATE("Cannot find the media roster"),
220b3b96925SAdrien Destugues			status);
221dba5824bSPhil Greenway		return status;
2229d3f15c6SIngo Weinhold	}
2239d3f15c6SIngo Weinhold
224dba5824bSPhil Greenway	/* find the time source */
225dba5824bSPhil Greenway	status = fMediaRoster->GetTimeSource(&fTimeSourceNode);
226dba5824bSPhil Greenway	if (status != B_OK) {
227b3b96925SAdrien Destugues		fWindow->ErrorAlert(B_TRANSLATE("Cannot get a time source"), status);
228dba5824bSPhil Greenway		return status;
229dba5824bSPhil Greenway	}
2309d3f15c6SIngo Weinhold
231dba5824bSPhil Greenway	/* find a video producer node */
232dba5824bSPhil Greenway	INFO("CodyCam acquiring VideoInput node\n");
233dba5824bSPhil Greenway	status = fMediaRoster->GetVideoInput(&fProducerNode);
234dba5824bSPhil Greenway	if (status != B_OK) {
235a325242dSHumdinger		fWindow->ErrorAlert(B_TRANSLATE("Cannot find a video source.\n"
236a325242dSHumdinger			"You need a webcam to use CodyCam."), status);
237dba5824bSPhil Greenway		return status;
238dba5824bSPhil Greenway	}
239dba5824bSPhil Greenway
240dba5824bSPhil Greenway	/* create the video consumer node */
241476fad7fSMatt Madia	fVideoConsumer = new VideoConsumer("CodyCam",
242c4f9b1d1SStephan Aßmus		((VideoWindow*)fWindow)->VideoView(),
2439d3f15c6SIngo Weinhold		((VideoWindow*)fWindow)->StatusLine(), NULL, 0);
2446a739773SCodeforEvolution	if (fVideoConsumer == NULL) {
245b3b96925SAdrien Destugues		fWindow->ErrorAlert(B_TRANSLATE("Cannot create a video window"),
246b3b96925SAdrien Destugues			B_ERROR);
247dba5824bSPhil Greenway		return B_ERROR;
248dba5824bSPhil Greenway	}
2499d3f15c6SIngo Weinhold
250dba5824bSPhil Greenway	/* register the node */
251dba5824bSPhil Greenway	status = fMediaRoster->RegisterNode(fVideoConsumer);
252dba5824bSPhil Greenway	if (status != B_OK) {
253b3b96925SAdrien Destugues		fWindow->ErrorAlert(B_TRANSLATE("Cannot register the video window"),
254b3b96925SAdrien Destugues			status);
255dba5824bSPhil Greenway		return status;
256dba5824bSPhil Greenway	}
257dba5824bSPhil Greenway	fPort = fVideoConsumer->ControlPort();
2587974d3dcSStephan Aßmus
259dba5824bSPhil Greenway	/* find free producer output */
260dba5824bSPhil Greenway	int32 cnt = 0;
261476fad7fSMatt Madia	status = fMediaRoster->GetFreeOutputsFor(fProducerNode, &fProducerOut, 1,
262c4f9b1d1SStephan Aßmus		&cnt, B_MEDIA_RAW_VIDEO);
263dba5824bSPhil Greenway	if (status != B_OK || cnt < 1) {
264dba5824bSPhil Greenway		status = B_RESOURCE_UNAVAILABLE;
2656a739773SCodeforEvolution		fWindow->ErrorAlert(
2666a739773SCodeforEvolution			B_TRANSLATE("Cannot find an available video stream"), status);
267dba5824bSPhil Greenway		return status;
268dba5824bSPhil Greenway	}
269dba5824bSPhil Greenway
270dba5824bSPhil Greenway	/* find free consumer input */
271dba5824bSPhil Greenway	cnt = 0;
272476fad7fSMatt Madia	status = fMediaRoster->GetFreeInputsFor(fVideoConsumer->Node(),
273c4f9b1d1SStephan Aßmus		&fConsumerIn, 1, &cnt, B_MEDIA_RAW_VIDEO);
274dba5824bSPhil Greenway	if (status != B_OK || cnt < 1) {
275dba5824bSPhil Greenway		status = B_RESOURCE_UNAVAILABLE;
276b3b96925SAdrien Destugues		fWindow->ErrorAlert(B_TRANSLATE("Can't find an available connection to "
277b3b96925SAdrien Destugues			"the video window"), status);
278dba5824bSPhil Greenway		return status;
279dba5824bSPhil Greenway	}
280dba5824bSPhil Greenway
281dba5824bSPhil Greenway	/* Connect The Nodes!!! */
282dba5824bSPhil Greenway	media_format format;
283dba5824bSPhil Greenway	format.type = B_MEDIA_RAW_VIDEO;
2849d3f15c6SIngo Weinhold	media_raw_video_format vid_format = {0, 1, 0, 239, B_VIDEO_TOP_LEFT_RIGHT,
2859d3f15c6SIngo Weinhold		1, 1, {B_RGB32, VIDEO_SIZE_X, VIDEO_SIZE_Y, VIDEO_SIZE_X * 4, 0, 0}};
2867974d3dcSStephan Aßmus	format.u.raw_video = vid_format;
2879d3f15c6SIngo Weinhold
288dba5824bSPhil Greenway	/* connect producer to consumer */
289476fad7fSMatt Madia	status = fMediaRoster->Connect(fProducerOut.source,
290c4f9b1d1SStephan Aßmus		fConsumerIn.destination, &format, &fProducerOut, &fConsumerIn);
291dba5824bSPhil Greenway	if (status != B_OK) {
292b3b96925SAdrien Destugues		fWindow->ErrorAlert(B_TRANSLATE("Cannot connect the video source to "
293b3b96925SAdrien Destugues			"the video window"), status);
294dba5824bSPhil Greenway		return status;
295dba5824bSPhil Greenway	}
2969d3f15c6SIngo Weinhold
2979d3f15c6SIngo Weinhold
298dba5824bSPhil Greenway	/* set time sources */
299476fad7fSMatt Madia	status = fMediaRoster->SetTimeSourceFor(fProducerNode.node,
300c4f9b1d1SStephan Aßmus		fTimeSourceNode.node);
301dba5824bSPhil Greenway	if (status != B_OK) {
302b3b96925SAdrien Destugues		fWindow->ErrorAlert(B_TRANSLATE("Cannot set the time source for the "
303b3b96925SAdrien Destugues			"video source"), status);
304dba5824bSPhil Greenway		return status;
305dba5824bSPhil Greenway	}
3069d3f15c6SIngo Weinhold
307476fad7fSMatt Madia	status = fMediaRoster->SetTimeSourceFor(fVideoConsumer->ID(),
308c4f9b1d1SStephan Aßmus		fTimeSourceNode.node);
309dba5824bSPhil Greenway	if (status != B_OK) {
310b3b96925SAdrien Destugues		fWindow->ErrorAlert(B_TRANSLATE("Cannot set the time source for the "
311b3b96925SAdrien Destugues			"video window"), status);
312dba5824bSPhil Greenway		return status;
313dba5824bSPhil Greenway	}
3149d3f15c6SIngo Weinhold
315dba5824bSPhil Greenway	/* figure out what recording delay to use */
316dba5824bSPhil Greenway	bigtime_t latency = 0;
317dba5824bSPhil Greenway	status = fMediaRoster->GetLatencyFor(fProducerNode, &latency);
318dba5824bSPhil Greenway	status = fMediaRoster->SetProducerRunModeDelay(fProducerNode, latency);
319dba5824bSPhil Greenway
320dba5824bSPhil Greenway	/* start the nodes */
321dba5824bSPhil Greenway	bigtime_t initLatency = 0;
322dba5824bSPhil Greenway	status = fMediaRoster->GetInitialLatencyFor(fProducerNode, &initLatency);
323dba5824bSPhil Greenway	if (status < B_OK) {
324b3b96925SAdrien Destugues		fWindow->ErrorAlert(B_TRANSLATE("Error getting initial latency for the "
325b3b96925SAdrien Destugues			"capture node"), status);
3269d3f15c6SIngo Weinhold		return status;
327dba5824bSPhil Greenway	}
3289d3f15c6SIngo Weinhold
329dba5824bSPhil Greenway	initLatency += estimate_max_scheduling_latency();
3307974d3dcSStephan Aßmus
3319d3f15c6SIngo Weinhold	BTimeSource* timeSource = fMediaRoster->MakeTimeSourceFor(fProducerNode);
332dba5824bSPhil Greenway	bool running = timeSource->IsRunning();
3339d3f15c6SIngo Weinhold
334dba5824bSPhil Greenway	/* workaround for people without sound cards */
335dba5824bSPhil Greenway	/* because the system time source won't be running */
336dba5824bSPhil Greenway	bigtime_t real = BTimeSource::RealTime();
3379d3f15c6SIngo Weinhold	if (!running) {
338dba5824bSPhil Greenway		status = fMediaRoster->StartTimeSource(fTimeSourceNode, real);
339dba5824bSPhil Greenway		if (status != B_OK) {
340dba5824bSPhil Greenway			timeSource->Release();
341b3b96925SAdrien Destugues			fWindow->ErrorAlert(B_TRANSLATE("Cannot start time source!"),
342b3b96925SAdrien Destugues				status);
343dba5824bSPhil Greenway			return status;
344dba5824bSPhil Greenway		}
345dba5824bSPhil Greenway		status = fMediaRoster->SeekTimeSource(fTimeSourceNode, 0, real);
346dba5824bSPhil Greenway		if (status != B_OK) {
347dba5824bSPhil Greenway			timeSource->Release();
348b3b96925SAdrien Destugues			fWindow->ErrorAlert(B_TRANSLATE("Cannot seek time source!"),
349b3b96925SAdrien Destugues				status);
350dba5824bSPhil Greenway			return status;
351dba5824bSPhil Greenway		}
352dba5824bSPhil Greenway	}
353dba5824bSPhil Greenway
354476fad7fSMatt Madia	bigtime_t perf = timeSource->PerformanceTimeFor(real + latency
355c4f9b1d1SStephan Aßmus		+ initLatency);
356dba5824bSPhil Greenway	timeSource->Release();
3577974d3dcSStephan Aßmus
358dba5824bSPhil Greenway	/* start the nodes */
359dba5824bSPhil Greenway	status = fMediaRoster->StartNode(fProducerNode, perf);
360dba5824bSPhil Greenway	if (status != B_OK) {
361b3b96925SAdrien Destugues		fWindow->ErrorAlert(B_TRANSLATE("Cannot start the video source"),
362b3b96925SAdrien Destugues			status);
363dba5824bSPhil Greenway		return status;
364dba5824bSPhil Greenway	}
365dba5824bSPhil Greenway	status = fMediaRoster->StartNode(fVideoConsumer->Node(), perf);
366dba5824bSPhil Greenway	if (status != B_OK) {
367b3b96925SAdrien Destugues		fWindow->ErrorAlert(B_TRANSLATE("Cannot start the video window"),
368b3b96925SAdrien Destugues			status);
369dba5824bSPhil Greenway		return status;
370dba5824bSPhil Greenway	}
3717974d3dcSStephan Aßmus
372dba5824bSPhil Greenway	return status;
373dba5824bSPhil Greenway}
374dba5824bSPhil Greenway
375dba5824bSPhil Greenway
3767974d3dcSStephan Aßmusvoid
3779d3f15c6SIngo WeinholdCodyCam::_TearDownNodes()
378dba5824bSPhil Greenway{
3799d3f15c6SIngo Weinhold	CALL("CodyCam::_TearDownNodes\n");
3806a739773SCodeforEvolution	if (fMediaRoster == NULL)
381dba5824bSPhil Greenway		return;
3827974d3dcSStephan Aßmus
3839d3f15c6SIngo Weinhold	if (fVideoConsumer) {
3847974d3dcSStephan Aßmus		/* stop */
385dba5824bSPhil Greenway		INFO("stopping nodes!\n");
386dba5824bSPhil Greenway//		fMediaRoster->StopNode(fProducerNode, 0, true);
387dba5824bSPhil Greenway		fMediaRoster->StopNode(fVideoConsumer->Node(), 0, true);
3887974d3dcSStephan Aßmus
389dba5824bSPhil Greenway		/* disconnect */
390dba5824bSPhil Greenway		fMediaRoster->Disconnect(fProducerOut.node.node, fProducerOut.source,
3919d3f15c6SIngo Weinhold			fConsumerIn.node.node, fConsumerIn.destination);
3927974d3dcSStephan Aßmus
393dba5824bSPhil Greenway		if (fProducerNode != media_node::null) {
394dba5824bSPhil Greenway			INFO("CodyCam releasing fProducerNode\n");
395dba5824bSPhil Greenway			fMediaRoster->ReleaseNode(fProducerNode);
396dba5824bSPhil Greenway			fProducerNode = media_node::null;
397dba5824bSPhil Greenway		}
3987974d3dcSStephan Aßmus		fMediaRoster->ReleaseNode(fVideoConsumer->Node());
399dba5824bSPhil Greenway		fVideoConsumer = NULL;
400dba5824bSPhil Greenway	}
401dba5824bSPhil Greenway}
402dba5824bSPhil Greenway
403dba5824bSPhil Greenway
4049d3f15c6SIngo Weinhold//	#pragma mark - Video Window Class
405dba5824bSPhil Greenway
406dba5824bSPhil Greenway
4073c5208e4SHumdingerVideoWindow::VideoWindow(const char* title, window_type type,
408f5e3b474SStephan Aßmus		uint32 flags, port_id* consumerPort)
409f5e3b474SStephan Aßmus	:
4103c5208e4SHumdinger	BWindow(BRect(50, 50, 50, 50), title, type, flags),
4119d3f15c6SIngo Weinhold	fPortPtr(consumerPort),
412859c1f01SNiels Sascha Reedijk	fVideoView(NULL)
413dba5824bSPhil Greenway{
414dba5824bSPhil Greenway	fFtpInfo.port = 0;
415dba5824bSPhil Greenway	fFtpInfo.rate = 0x7fffffff;
416dba5824bSPhil Greenway	fFtpInfo.imageFormat = 0;
417dba5824bSPhil Greenway	fFtpInfo.translator = 0;
418dba5824bSPhil Greenway	fFtpInfo.passiveFtp = true;
41971814054SFrançois Revol	fFtpInfo.uploadClient = 0;
420dba5824bSPhil Greenway	strcpy(fFtpInfo.fileNameText, "filename");
421dba5824bSPhil Greenway	strcpy(fFtpInfo.serverText, "server");
422dba5824bSPhil Greenway	strcpy(fFtpInfo.loginText, "login");
423dba5824bSPhil Greenway	strcpy(fFtpInfo.passwordText, "password");
424dba5824bSPhil Greenway	strcpy(fFtpInfo.directoryText, "directory");
425dba5824bSPhil Greenway
4267974d3dcSStephan Aßmus	_SetUpSettings("codycam", "");
427dba5824bSPhil Greenway
4283c5208e4SHumdinger	BMenuBar* menuBar = new BMenuBar("menu bar");
4297974d3dcSStephan Aßmus
430dba5824bSPhil Greenway	BMenuItem* menuItem;
4311615cec9SFredrik Modéen	fMenu = new BMenu(B_TRANSLATE("File"));
432dba5824bSPhil Greenway
433476fad7fSMatt Madia	menuItem = new BMenuItem(B_TRANSLATE("Video settings"),
434c4f9b1d1SStephan Aßmus		new BMessage(msg_video), 'P');
435dba5824bSPhil Greenway	menuItem->SetTarget(be_app);
4361615cec9SFredrik Modéen	fMenu->AddItem(menuItem);
437dba5824bSPhil Greenway
4381615cec9SFredrik Modéen	fMenu->AddSeparatorItem();
439dba5824bSPhil Greenway
440476fad7fSMatt Madia	menuItem = new BMenuItem(B_TRANSLATE("Start video"),
441c4f9b1d1SStephan Aßmus		new BMessage(msg_start), 'A');
442dba5824bSPhil Greenway	menuItem->SetTarget(be_app);
4431615cec9SFredrik Modéen	fMenu->AddItem(menuItem);
444dba5824bSPhil Greenway
445476fad7fSMatt Madia	menuItem = new BMenuItem(B_TRANSLATE("Stop video"),
446c4f9b1d1SStephan Aßmus		new BMessage(msg_stop), 'O');
447dba5824bSPhil Greenway	menuItem->SetTarget(be_app);
4481615cec9SFredrik Modéen	fMenu->AddItem(menuItem);
449dba5824bSPhil Greenway
4501615cec9SFredrik Modéen	fMenu->AddSeparatorItem();
451dba5824bSPhil Greenway
452476fad7fSMatt Madia	menuItem = new BMenuItem(B_TRANSLATE("Quit"),
453c4f9b1d1SStephan Aßmus		new BMessage(B_QUIT_REQUESTED), 'Q');
454dba5824bSPhil Greenway	menuItem->SetTarget(be_app);
4551615cec9SFredrik Modéen	fMenu->AddItem(menuItem);
456dba5824bSPhil Greenway
4571615cec9SFredrik Modéen	menuBar->AddItem(fMenu);
458dba5824bSPhil Greenway
459dba5824bSPhil Greenway	/* add some controls */
4608ceeae63SAlex Wilson	_BuildCaptureControls();
4618ceeae63SAlex Wilson
462b3b96925SAdrien Destugues	BBox* box = new BBox("box");
463070c8b72SAdrien Destugues	BGroupLayout* layout = new BGroupLayout(B_VERTICAL);
464070c8b72SAdrien Destugues	box->SetLayout(layout);
465070c8b72SAdrien Destugues	layout->SetInsets(2, 2, 2, 2);
466b3b96925SAdrien Destugues	box->AddChild(fVideoView);
467070c8b72SAdrien Destugues	box->AddChild(fErrorView);
468b3b96925SAdrien Destugues
4698ceeae63SAlex Wilson	BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
4708ceeae63SAlex Wilson		.Add(menuBar)
4713c5208e4SHumdinger		.AddGroup(B_VERTICAL)
4723c5208e4SHumdinger			.SetInsets(B_USE_WINDOW_SPACING)
473070c8b72SAdrien Destugues			.AddGroup(B_HORIZONTAL)
474070c8b72SAdrien Destugues				.AddGlue()
475070c8b72SAdrien Destugues				.Add(box)
476070c8b72SAdrien Destugues				.AddGlue()
477070c8b72SAdrien Destugues			.End()
4783c5208e4SHumdinger			.AddGroup(B_HORIZONTAL, B_USE_DEFAULT_SPACING)
4798ceeae63SAlex Wilson				.Add(fCaptureSetupBox)
4808ceeae63SAlex Wilson				.Add(fFtpSetupBox)
4818ceeae63SAlex Wilson				.End()
4823c5208e4SHumdinger			.Add(fStatusLine)
4833c5208e4SHumdinger			.End()
4843c5208e4SHumdinger		.AddGlue();
485dba5824bSPhil Greenway
486dba5824bSPhil Greenway	Show();
487dba5824bSPhil Greenway}
488dba5824bSPhil Greenway
4899d3f15c6SIngo Weinhold
490dba5824bSPhil GreenwayVideoWindow::~VideoWindow()
491dba5824bSPhil Greenway{
4929d3f15c6SIngo Weinhold	_QuitSettings();
493dba5824bSPhil Greenway}
494dba5824bSPhil Greenway
4959d3f15c6SIngo Weinhold
496dba5824bSPhil Greenwaybool
497dba5824bSPhil GreenwayVideoWindow::QuitRequested()
498dba5824bSPhil Greenway{
499dba5824bSPhil Greenway	be_app->PostMessage(B_QUIT_REQUESTED);
500dba5824bSPhil Greenway	return false;
501dba5824bSPhil Greenway}
502dba5824bSPhil Greenway
503dba5824bSPhil Greenway
504dba5824bSPhil Greenwayvoid
5059d3f15c6SIngo WeinholdVideoWindow::MessageReceived(BMessage* message)
506dba5824bSPhil Greenway{
507f5e3b474SStephan Aßmus	BControl* control = NULL;
5086a739773SCodeforEvolution	message->FindPointer((const char*)"source", (void**)&control);
5099d3f15c6SIngo Weinhold
5109d3f15c6SIngo Weinhold	switch (message->what) {
511dba5824bSPhil Greenway		case msg_filename:
5129d3f15c6SIngo Weinhold			if (control != NULL) {
51308a75021SJonas Sundström				strlcpy(fFtpInfo.fileNameText,
51408a75021SJonas Sundström					((BTextControl*)control)->Text(), 64);
515dba5824bSPhil Greenway				FTPINFO("file is '%s'\n", fFtpInfo.fileNameText);
516dba5824bSPhil Greenway			}
517dba5824bSPhil Greenway			break;
5189d3f15c6SIngo Weinhold
5198ceeae63SAlex Wilson		case msg_rate_changed: {
5208ceeae63SAlex Wilson			int32 seconds;
5218ceeae63SAlex Wilson			message->FindInt32("seconds", &seconds);
5228ceeae63SAlex Wilson			if (seconds == 0) {
5238ceeae63SAlex Wilson				FTPINFO("never\n");
5248ceeae63SAlex Wilson				fFtpInfo.rate = (bigtime_t)(B_INFINITE_TIMEOUT);
5258ceeae63SAlex Wilson			} else {
5266a739773SCodeforEvolution				FTPINFO("%" B_PRId32 " seconds\n", seconds);
5278ceeae63SAlex Wilson				fFtpInfo.rate = (bigtime_t)(seconds * 1000000LL);
5288ceeae63SAlex Wilson			}
529dba5824bSPhil Greenway			break;
5308ceeae63SAlex Wilson		}
5319d3f15c6SIngo Weinhold
5327974d3dcSStephan Aßmus		case msg_translate:
5339d3f15c6SIngo Weinhold			message->FindInt32("be:type", (int32*)&(fFtpInfo.imageFormat));
5347974d3dcSStephan Aßmus			message->FindInt32("be:translator", &(fFtpInfo.translator));
535dba5824bSPhil Greenway			break;
5369d3f15c6SIngo Weinhold
537e3145a8dSFrançois Revol		case msg_upl_client:
538f5e3b474SStephan Aßmus			message->FindInt32("client", &(fFtpInfo.uploadClient));
539afcbccb9SJérôme Duval			FTPINFO("upl client = %" B_PRId32 "\n", fFtpInfo.uploadClient);
540f5e3b474SStephan Aßmus			_UploadClientChanged();
541e3145a8dSFrançois Revol			break;
542e3145a8dSFrançois Revol
543dba5824bSPhil Greenway		case msg_server:
5449d3f15c6SIngo Weinhold			if (control != NULL) {
54508a75021SJonas Sundström				strlcpy(fFtpInfo.serverText,
5468ceeae63SAlex Wilson					((BTextControl*)control)->Text(), 64);
547dba5824bSPhil Greenway				FTPINFO("server = '%s'\n", fFtpInfo.serverText);
548dba5824bSPhil Greenway			}
549dba5824bSPhil Greenway			break;
5509d3f15c6SIngo Weinhold
551dba5824bSPhil Greenway		case msg_login:
5529d3f15c6SIngo Weinhold			if (control != NULL) {
55308a75021SJonas Sundström				strlcpy(fFtpInfo.loginText,
5548ceeae63SAlex Wilson					((BTextControl*)control)->Text(), 64);
555dba5824bSPhil Greenway				FTPINFO("login = '%s'\n", fFtpInfo.loginText);
556dba5824bSPhil Greenway			}
557dba5824bSPhil Greenway			break;
5589d3f15c6SIngo Weinhold
559dba5824bSPhil Greenway		case msg_password:
5609d3f15c6SIngo Weinhold			if (control != NULL) {
56108a75021SJonas Sundström				strlcpy(fFtpInfo.passwordText,
5628ceeae63SAlex Wilson					((BTextControl*)control)->Text(), 64);
563dba5824bSPhil Greenway				FTPINFO("password = '%s'\n", fFtpInfo.passwordText);
564dba5824bSPhil Greenway			}
565dba5824bSPhil Greenway			break;
5669d3f15c6SIngo Weinhold
567dba5824bSPhil Greenway		case msg_directory:
5689d3f15c6SIngo Weinhold			if (control != NULL) {
56908a75021SJonas Sundström				strlcpy(fFtpInfo.directoryText,
5708ceeae63SAlex Wilson					((BTextControl*)control)->Text(), 64);
571dba5824bSPhil Greenway				FTPINFO("directory = '%s'\n", fFtpInfo.directoryText);
572dba5824bSPhil Greenway			}
573dba5824bSPhil Greenway			break;
5749d3f15c6SIngo Weinhold
575dba5824bSPhil Greenway		case msg_passiveftp:
5769d3f15c6SIngo Weinhold			if (control != NULL) {
5779d3f15c6SIngo Weinhold				fFtpInfo.passiveFtp = ((BCheckBox*)control)->Value();
578dba5824bSPhil Greenway				if (fFtpInfo.passiveFtp)
579dba5824bSPhil Greenway					FTPINFO("using passive ftp\n");
580dba5824bSPhil Greenway			}
581dba5824bSPhil Greenway			break;
5829d3f15c6SIngo Weinhold
583dba5824bSPhil Greenway		default:
584dba5824bSPhil Greenway			BWindow::MessageReceived(message);
585dba5824bSPhil Greenway			return;
586dba5824bSPhil Greenway	}
587dba5824bSPhil Greenway
588dba5824bSPhil Greenway	if (*fPortPtr)
5899d3f15c6SIngo Weinhold		write_port(*fPortPtr, FTP_INFO, (void*)&fFtpInfo, sizeof(ftp_msg_info));
590dba5824bSPhil Greenway
591dba5824bSPhil Greenway}
592dba5824bSPhil Greenway
593dba5824bSPhil Greenway
5949d3f15c6SIngo WeinholdBView*
595dba5824bSPhil GreenwayVideoWindow::VideoView()
596dba5824bSPhil Greenway{
597dba5824bSPhil Greenway	return fVideoView;
598dba5824bSPhil Greenway}
599dba5824bSPhil Greenway
600dba5824bSPhil Greenway
6019d3f15c6SIngo WeinholdBStringView*
602dba5824bSPhil GreenwayVideoWindow::StatusLine()
603dba5824bSPhil Greenway{
604dba5824bSPhil Greenway	return fStatusLine;
605dba5824bSPhil Greenway}
606dba5824bSPhil Greenway
607dba5824bSPhil Greenway
608dba5824bSPhil Greenwayvoid
6098ceeae63SAlex WilsonVideoWindow::_BuildCaptureControls()
610dba5824bSPhil Greenway{
61189d04738SStephan Aßmus	// a view to hold the video image
612070c8b72SAdrien Destugues	fVideoView = new BView("Video preview", B_WILL_DRAW);
61389d04738SStephan Aßmus	fVideoView->SetExplicitMinSize(BSize(VIDEO_SIZE_X, VIDEO_SIZE_Y));
61489d04738SStephan Aßmus	fVideoView->SetExplicitMaxSize(BSize(VIDEO_SIZE_X, VIDEO_SIZE_Y));
615070c8b72SAdrien Destugues
616070c8b72SAdrien Destugues	fErrorView = new BTextView("error");
617070c8b72SAdrien Destugues	fErrorView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
61889d04738SStephan Aßmus
61989d04738SStephan Aßmus	// Capture controls
6206a739773SCodeforEvolution	BGridLayout* controlsLayout = new BGridLayout(B_USE_DEFAULT_SPACING,
621a325242dSHumdinger		B_USE_SMALL_SPACING);
622a325242dSHumdinger	controlsLayout->SetInsets(B_USE_SMALL_SPACING);
623a325242dSHumdinger
624a325242dSHumdinger	BView* controlView = new BView("Controls", B_SUPPORTS_LAYOUT, NULL);
625a325242dSHumdinger	controlView->SetLayout(controlsLayout);
626a325242dSHumdinger
62789d04738SStephan Aßmus	fCaptureSetupBox = new BBox("Capture Controls", B_WILL_DRAW);
628c4f9b1d1SStephan Aßmus	fCaptureSetupBox->SetLabel(B_TRANSLATE("Capture controls"));
629a325242dSHumdinger	fCaptureSetupBox->AddChild(controlView);
6307974d3dcSStephan Aßmus
6318ceeae63SAlex Wilson	// file name
632c4f9b1d1SStephan Aßmus	fFileName = new BTextControl("File Name", B_TRANSLATE("File name:"),
6339d3f15c6SIngo Weinhold		fFilenameSetting->Value(), new BMessage(msg_filename));
634dba5824bSPhil Greenway	fFileName->SetTarget(BMessenger(NULL, this));
635dba5824bSPhil Greenway
6368ceeae63SAlex Wilson	// format menu
637c4f9b1d1SStephan Aßmus	fImageFormatMenu = new BPopUpMenu(B_TRANSLATE("Image Format Menu"));
6386a739773SCodeforEvolution	BTranslationUtils::AddTranslationItems(fImageFormatMenu,
6396a739773SCodeforEvolution		B_TRANSLATOR_BITMAP);
640dba5824bSPhil Greenway	fImageFormatMenu->SetTargetForItems(this);
6419d3f15c6SIngo Weinhold
642f5e3b474SStephan Aßmus	if (fImageFormatSettings->Value()
643f5e3b474SStephan Aßmus		&& fImageFormatMenu->FindItem(fImageFormatSettings->Value()) != NULL) {
644f5e3b474SStephan Aßmus		fImageFormatMenu->FindItem(
645f5e3b474SStephan Aßmus			fImageFormatSettings->Value())->SetMarked(true);
6467974d3dcSStephan Aßmus	} else if (fImageFormatMenu->FindItem("JPEG image") != NULL)
647d5147499SFrançois Revol		fImageFormatMenu->FindItem("JPEG image")->SetMarked(true);
648dba5824bSPhil Greenway	else
6499d3f15c6SIngo Weinhold		fImageFormatMenu->ItemAt(0)->SetMarked(true);
6509d3f15c6SIngo Weinhold
651c4f9b1d1SStephan Aßmus	fImageFormatSelector = new BMenuField("Format", B_TRANSLATE("Format:"),
65210dfe897SAxel Dörfler		fImageFormatMenu);
6537974d3dcSStephan Aßmus
6548ceeae63SAlex Wilson	// capture rate
655c4f9b1d1SStephan Aßmus	fCaptureRateMenu = new BPopUpMenu(B_TRANSLATE("Capture Rate Menu"));
6568ceeae63SAlex Wilson	for (int32 i = 0; i < kCaptureRatesCount; i++) {
6578ceeae63SAlex Wilson		BMessage* itemMessage = new BMessage(msg_rate_changed);
6588ceeae63SAlex Wilson		itemMessage->AddInt32("seconds", kCaptureRates[i].seconds);
6598ceeae63SAlex Wilson		fCaptureRateMenu->AddItem(new BMenuItem(kCaptureRates[i].name,
6608ceeae63SAlex Wilson			itemMessage));
6618ceeae63SAlex Wilson	}
662dba5824bSPhil Greenway	fCaptureRateMenu->SetTargetForItems(this);
663dba5824bSPhil Greenway	fCaptureRateMenu->FindItem(fCaptureRateSetting->Value())->SetMarked(true);
664c4f9b1d1SStephan Aßmus	fCaptureRateSelector = new BMenuField("Rate", B_TRANSLATE("Rate:"),
66510dfe897SAxel Dörfler		fCaptureRateMenu);
666dba5824bSPhil Greenway
6678ceeae63SAlex Wilson	BLayoutBuilder::Grid<>(controlsLayout)
6688ceeae63SAlex Wilson		.AddTextControl(fFileName, 0, 0)
6698ceeae63SAlex Wilson		.AddMenuField(fImageFormatSelector, 0, 1)
6708ceeae63SAlex Wilson		.AddMenuField(fCaptureRateSelector, 0, 2)
6718ceeae63SAlex Wilson		.Add(BSpaceLayoutItem::CreateGlue(), 0, 3, 2, 1);
67289d04738SStephan Aßmus
67389d04738SStephan Aßmus	// FTP setup box
674a325242dSHumdinger	BGridLayout* ftpLayout = new BGridLayout(B_USE_DEFAULT_SPACING,
675a325242dSHumdinger		B_USE_SMALL_SPACING);
676a325242dSHumdinger	ftpLayout->SetInsets(B_USE_SMALL_SPACING);
677a325242dSHumdinger
678a325242dSHumdinger	BView* outputView = new BView("Output", B_SUPPORTS_LAYOUT, NULL);
679a325242dSHumdinger	outputView->SetLayout(ftpLayout);
680a325242dSHumdinger
6818ceeae63SAlex Wilson	fFtpSetupBox = new BBox("FTP Setup", B_WILL_DRAW);
6821615cec9SFredrik Modéen	fFtpSetupBox->SetLabel(B_TRANSLATE("Output"));
683a325242dSHumdinger	fFtpSetupBox->AddChild(outputView);
684a325242dSHumdinger	float minWidth = be_plain_font->StringWidth(
685a325242dSHumdinger		"The server label plus ftp.reasonably.com");
686a325242dSHumdinger	fFtpSetupBox->SetExplicitMinSize(BSize(minWidth, B_SIZE_UNSET));
687a325242dSHumdinger	fFtpSetupBox->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
6889d3f15c6SIngo Weinhold
689c4f9b1d1SStephan Aßmus	fUploadClientMenu = new BPopUpMenu(B_TRANSLATE("Send to" B_UTF8_ELLIPSIS));
6908ceeae63SAlex Wilson	for (int i = 0; i < kUploadClientsCount; i++) {
6916a739773SCodeforEvolution		BMessage* m = new BMessage(msg_upl_client);
692e3145a8dSFrançois Revol		m->AddInt32("client", i);
6938ceeae63SAlex Wilson		fUploadClientMenu->AddItem(new BMenuItem(kUploadClients[i], m));
694e3145a8dSFrançois Revol	}
6956f3ad852SAdrien Destugues
696e3145a8dSFrançois Revol	fUploadClientMenu->SetTargetForItems(this);
69771814054SFrançois Revol	fUploadClientMenu->FindItem(fUploadClientSetting->Value())->SetMarked(true);
698a325242dSHumdinger
69989d04738SStephan Aßmus	fUploadClientSelector = new BMenuField("UploadClient", NULL,
70010dfe897SAxel Dörfler		fUploadClientMenu);
701e3145a8dSFrançois Revol
702c4f9b1d1SStephan Aßmus	fUploadClientSelector->SetLabel(B_TRANSLATE("Type:"));
7039d3f15c6SIngo Weinhold
704c4f9b1d1SStephan Aßmus	fServerName = new BTextControl("Server", B_TRANSLATE("Server:"),
70589d04738SStephan Aßmus		fServerSetting->Value(), new BMessage(msg_server));
706dba5824bSPhil Greenway	fServerName->SetTarget(this);
7079d3f15c6SIngo Weinhold
708c4f9b1d1SStephan Aßmus	fLoginId = new BTextControl("Login", B_TRANSLATE("Login:"),
70989d04738SStephan Aßmus		fLoginSetting->Value(), new BMessage(msg_login));
710dba5824bSPhil Greenway	fLoginId->SetTarget(this);
711dba5824bSPhil Greenway
712c4f9b1d1SStephan Aßmus	fPassword = new BTextControl("Password", B_TRANSLATE("Password:"),
7139d3f15c6SIngo Weinhold		fPasswordSetting->Value(), new BMessage(msg_password));
714dba5824bSPhil Greenway	fPassword->SetTarget(this);
7156b6bfc7bSFrançois Revol	fPassword->TextView()->HideTyping(true);
7166b6bfc7bSFrançois Revol	// BeOS HideTyping() seems broken, it empties the text
7176b6bfc7bSFrançois Revol	fPassword->SetText(fPasswordSetting->Value());
7189d3f15c6SIngo Weinhold
719c4f9b1d1SStephan Aßmus	fDirectory = new BTextControl("Directory", B_TRANSLATE("Directory:"),
7209d3f15c6SIngo Weinhold		fDirectorySetting->Value(), new BMessage(msg_directory));
721dba5824bSPhil Greenway	fDirectory->SetTarget(this);
7229d3f15c6SIngo Weinhold
723c4f9b1d1SStephan Aßmus	fPassiveFtp = new BCheckBox("Passive FTP", B_TRANSLATE("Passive FTP"),
7249d3f15c6SIngo Weinhold		new BMessage(msg_passiveftp));
725dba5824bSPhil Greenway	fPassiveFtp->SetTarget(this);
726dba5824bSPhil Greenway	fPassiveFtp->SetValue(fPassiveFtpSetting->Value());
727a325242dSHumdinger	fPassiveFtp->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
7289d3f15c6SIngo Weinhold
7298ceeae63SAlex Wilson	BLayoutBuilder::Grid<>(ftpLayout)
7308ceeae63SAlex Wilson		.AddMenuField(fUploadClientSelector, 0, 0)
7318ceeae63SAlex Wilson		.AddTextControl(fServerName, 0, 1)
7328ceeae63SAlex Wilson		.AddTextControl(fLoginId, 0, 2)
7338ceeae63SAlex Wilson		.AddTextControl(fPassword, 0, 3)
7348ceeae63SAlex Wilson		.AddTextControl(fDirectory, 0, 4)
7358ceeae63SAlex Wilson		.Add(fPassiveFtp, 0, 5, 2, 1);
7368ceeae63SAlex Wilson
7378ceeae63SAlex Wilson	fStatusLine = new BStringView("Status Line",
7388ceeae63SAlex Wilson		B_TRANSLATE("Waiting" B_UTF8_ELLIPSIS));
739a325242dSHumdinger	fStatusLine->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET));
740dba5824bSPhil Greenway}
741dba5824bSPhil Greenway
742dba5824bSPhil Greenway
743dba5824bSPhil Greenwayvoid
744dba5824bSPhil GreenwayVideoWindow::ApplyControls()
745dba5824bSPhil Greenway{
746f5e3b474SStephan Aßmus	if (!Lock())
747f5e3b474SStephan Aßmus		return;
748f5e3b474SStephan Aßmus
749dba5824bSPhil Greenway	// apply controls
750f5e3b474SStephan Aßmus	fFileName->Invoke();
751dba5824bSPhil Greenway	PostMessage(fImageFormatMenu->FindMarked()->Message());
752dba5824bSPhil Greenway	PostMessage(fCaptureRateMenu->FindMarked()->Message());
75371814054SFrançois Revol	PostMessage(fUploadClientMenu->FindMarked()->Message());
754dba5824bSPhil Greenway	fServerName->Invoke();
755dba5824bSPhil Greenway	fLoginId->Invoke();
756dba5824bSPhil Greenway	fPassword->Invoke();
757dba5824bSPhil Greenway	fDirectory->Invoke();
758dba5824bSPhil Greenway	fPassiveFtp->Invoke();
759f5e3b474SStephan Aßmus
760f5e3b474SStephan Aßmus	Unlock();
761dba5824bSPhil Greenway}
762dba5824bSPhil Greenway
763dba5824bSPhil Greenway
7646f3ad852SAdrien Destuguesvoid
7656f3ad852SAdrien DestuguesVideoWindow::ErrorAlert(const char* message, status_t err)
7666f3ad852SAdrien Destugues{
7676f3ad852SAdrien Destugues	Lock();
768070c8b72SAdrien Destugues	fErrorView->SetText(message);
769070c8b72SAdrien Destugues	fErrorView->MakeEditable(false);
770070c8b72SAdrien Destugues	fErrorView->MakeSelectable(false);
771070c8b72SAdrien Destugues	fErrorView->SetWordWrap(true);
772f42d4b5cSSergei Reznikov	fErrorView->SetAlignment(B_ALIGN_CENTER);
773070c8b72SAdrien Destugues	fErrorView->SetExplicitMinSize(BSize(VIDEO_SIZE_X, VIDEO_SIZE_Y));
774070c8b72SAdrien Destugues	fErrorView->SetExplicitMaxSize(BSize(VIDEO_SIZE_X, VIDEO_SIZE_Y));
775070c8b72SAdrien Destugues	fErrorView->Show();
776070c8b72SAdrien Destugues	fVideoView->Hide();
7776f3ad852SAdrien Destugues	Unlock();
7786f3ad852SAdrien Destugues
7796f3ad852SAdrien Destugues	printf("%s\n%s [%" B_PRIx32 "]", message, strerror(err), err);
7806f3ad852SAdrien Destugues}
7816f3ad852SAdrien Destugues
7826f3ad852SAdrien Destugues
783dba5824bSPhil Greenwayvoid
7849d3f15c6SIngo WeinholdVideoWindow::_SetUpSettings(const char* filename, const char* dirname)
785dba5824bSPhil Greenway{
786dba5824bSPhil Greenway	fSettings = new Settings(filename, dirname);
787dba5824bSPhil Greenway
78818ba9ea5SJonas Sundström	fServerSetting = new StringValueSetting("Server", "ftp.my.server",
7898ceeae63SAlex Wilson		B_TRANSLATE("server address expected"));
7908ceeae63SAlex Wilson
79118ba9ea5SJonas Sundström	fLoginSetting = new StringValueSetting("Login", "loginID",
7928ceeae63SAlex Wilson		B_TRANSLATE("login ID expected"));
7938ceeae63SAlex Wilson
794476fad7fSMatt Madia	fPasswordSetting = new StringValueSetting("Password",
7958ceeae63SAlex Wilson		B_TRANSLATE("password"), B_TRANSLATE("password expected"));
7968ceeae63SAlex Wilson
79718ba9ea5SJonas Sundström	fDirectorySetting = new StringValueSetting("Directory", "web/images",
7988ceeae63SAlex Wilson		B_TRANSLATE("destination directory expected"));
7998ceeae63SAlex Wilson
80018ba9ea5SJonas Sundström	fPassiveFtpSetting = new BooleanValueSetting("PassiveFtp", 1);
8018ceeae63SAlex Wilson
80218ba9ea5SJonas Sundström	fFilenameSetting = new StringValueSetting("StillImageFilename",
8038ceeae63SAlex Wilson		"codycam.jpg", B_TRANSLATE("still image filename expected"));
8048ceeae63SAlex Wilson
80518ba9ea5SJonas Sundström	fImageFormatSettings = new StringValueSetting("ImageFileFormat",
8068ceeae63SAlex Wilson		B_TRANSLATE("JPEG image"), B_TRANSLATE("image file format expected"));
8078ceeae63SAlex Wilson
80818ba9ea5SJonas Sundström	fCaptureRateSetting = new EnumeratedStringValueSetting("CaptureRate",
8098ceeae63SAlex Wilson		kCaptureRates[3].name, &CaptureRateAt,
8108ceeae63SAlex Wilson		B_TRANSLATE("capture rate expected"),
81118ba9ea5SJonas Sundström		"unrecognized capture rate specified");
8128ceeae63SAlex Wilson
81318ba9ea5SJonas Sundström	fUploadClientSetting = new EnumeratedStringValueSetting("UploadClient",
814476fad7fSMatt Madia		B_TRANSLATE("FTP"), &UploadClientAt,
815c4f9b1d1SStephan Aßmus		B_TRANSLATE("upload client name expected"),
816c4f9b1d1SStephan Aßmus		B_TRANSLATE("unrecognized upload client specified"));
81718ba9ea5SJonas Sundström
81818ba9ea5SJonas Sundström	fSettings->Add(fServerSetting);
81918ba9ea5SJonas Sundström	fSettings->Add(fLoginSetting);
82018ba9ea5SJonas Sundström	fSettings->Add(fPasswordSetting);
82118ba9ea5SJonas Sundström	fSettings->Add(fDirectorySetting);
82218ba9ea5SJonas Sundström	fSettings->Add(fPassiveFtpSetting);
82318ba9ea5SJonas Sundström	fSettings->Add(fFilenameSetting);
82418ba9ea5SJonas Sundström	fSettings->Add(fImageFormatSettings);
82518ba9ea5SJonas Sundström	fSettings->Add(fCaptureRateSetting);
82618ba9ea5SJonas Sundström	fSettings->Add(fUploadClientSetting);
827dba5824bSPhil Greenway
828dba5824bSPhil Greenway	fSettings->TryReadingSettings();
829dba5824bSPhil Greenway}
830dba5824bSPhil Greenway
831dba5824bSPhil Greenway
832f5e3b474SStephan Aßmusvoid
833f5e3b474SStephan AßmusVideoWindow::_UploadClientChanged()
834f5e3b474SStephan Aßmus{
835f5e3b474SStephan Aßmus	bool enableServerControls = fFtpInfo.uploadClient < 2;
836f5e3b474SStephan Aßmus	fServerName->SetEnabled(enableServerControls);
837f5e3b474SStephan Aßmus	fLoginId->SetEnabled(enableServerControls);
838f5e3b474SStephan Aßmus	fPassword->SetEnabled(enableServerControls);
839f5e3b474SStephan Aßmus	fDirectory->SetEnabled(enableServerControls);
840f5e3b474SStephan Aßmus	fPassiveFtp->SetEnabled(enableServerControls);
841f5e3b474SStephan Aßmus}
842f5e3b474SStephan Aßmus
843f5e3b474SStephan Aßmus
844dba5824bSPhil Greenwayvoid
8459d3f15c6SIngo WeinholdVideoWindow::_QuitSettings()
846dba5824bSPhil Greenway{
847dba5824bSPhil Greenway	fServerSetting->ValueChanged(fServerName->Text());
848dba5824bSPhil Greenway	fLoginSetting->ValueChanged(fLoginId->Text());
849dba5824bSPhil Greenway	fPasswordSetting->ValueChanged(fFtpInfo.passwordText);
850dba5824bSPhil Greenway	fDirectorySetting->ValueChanged(fDirectory->Text());
851dba5824bSPhil Greenway	fPassiveFtpSetting->ValueChanged(fPassiveFtp->Value());
852dba5824bSPhil Greenway	fFilenameSetting->ValueChanged(fFileName->Text());
853d5147499SFrançois Revol	fImageFormatSettings->ValueChanged(fImageFormatMenu->FindMarked()->Label());
854dba5824bSPhil Greenway	fCaptureRateSetting->ValueChanged(fCaptureRateMenu->FindMarked()->Label());
8556a739773SCodeforEvolution	fUploadClientSetting->ValueChanged(
8566a739773SCodeforEvolution		fUploadClientMenu->FindMarked()->Label());
8577974d3dcSStephan Aßmus
858dba5824bSPhil Greenway	fSettings->SaveSettings();
859dba5824bSPhil Greenway	delete fSettings;
860dba5824bSPhil Greenway}
861dba5824bSPhil Greenway
862dba5824bSPhil Greenway
8631615cec9