10 #include <FindDirectory.h>
11 #include <LayoutBuilder.h>
12 #include <MediaDefs.h>
13 #include <MediaNode.h>
14 #include <MediaRoster.h>
15 #include <MediaTheme.h>
20 #include <PopUpMenu.h>
21 #include <scheduler.h>
23 #include <TextControl.h>
24 #include <TimeSource.h>
25 #include <TranslationUtils.h>
27 #undef B_TRANSLATION_CONTEXT
28 #define B_TRANSLATION_CONTEXT "CodyCam"
30 #define VIDEO_SIZE_X 320
31 #define VIDEO_SIZE_Y 240
33 #define WINDOW_SIZE_X (VIDEO_SIZE_X + 80)
34 #define WINDOW_SIZE_Y (VIDEO_SIZE_Y + 230)
36 #define WINDOW_OFFSET_X 28
37 #define WINDOW_OFFSET_Y 28
41 #define FTPINFO printf
49 // functions for EnumeratedStringValueSettings
52 CaptureRateAt(int32 i
)
54 return (i
>= 0 && i
< kCaptureRatesCount
) ? kCaptureRates
[i
].name
: NULL
;
59 UploadClientAt(int32 i
)
61 return (i
>= 0 && i
< kUploadClientsCount
) ? kUploadClients
[i
] : NULL
;
65 }; // end anonymous namespace
74 BApplication("application/x-vnd.Haiku-CodyCam"),
79 fVideoControlWindow(NULL
)
82 kCaptureRates
[index
++].name
= B_TRANSLATE("Every 15 seconds");
83 kCaptureRates
[index
++].name
= B_TRANSLATE("Every 30 seconds");
84 kCaptureRates
[index
++].name
= B_TRANSLATE("Every minute");
85 kCaptureRates
[index
++].name
= B_TRANSLATE("Every 5 minutes");
86 kCaptureRates
[index
++].name
= B_TRANSLATE("Every 10 minutes");
87 kCaptureRates
[index
++].name
= B_TRANSLATE("Every 15 minutes");
88 kCaptureRates
[index
++].name
= B_TRANSLATE("Every 30 minutes");
89 kCaptureRates
[index
++].name
= B_TRANSLATE("Every hour");
90 kCaptureRates
[index
++].name
= B_TRANSLATE("Every 2 hours");
91 kCaptureRates
[index
++].name
= B_TRANSLATE("Every 4 hours");
92 kCaptureRates
[index
++].name
= B_TRANSLATE("Every 8 hours");
93 kCaptureRates
[index
++].name
= B_TRANSLATE("Every 24 hours");
94 kCaptureRates
[index
++].name
= B_TRANSLATE("Never");
97 kUploadClients
[index
++] = B_TRANSLATE("FTP");
98 kUploadClients
[index
++] = B_TRANSLATE("SFTP");
99 kUploadClients
[index
++] = B_TRANSLATE("Local");
102 if (find_directory(B_USER_DIRECTORY
, &homeDir
) != B_OK
)
103 homeDir
.SetTo("/boot/home");
105 chdir(homeDir
.Path());
111 CALL("CodyCam::~CodyCam\n");
113 // release the video consumer node
114 // the consumer node cleans up the window
115 if (fVideoConsumer
) {
116 fVideoConsumer
->Release();
117 fVideoConsumer
= NULL
;
120 CALL("CodyCam::~CodyCam - EXIT\n");
125 CodyCam::ReadyToRun()
127 fWindow
= new VideoWindow(
128 (const char*) B_TRANSLATE_SYSTEM_NAME("CodyCam"), B_TITLED_WINDOW
,
129 B_NOT_ZOOMABLE
| B_NOT_V_RESIZABLE
130 | B_AUTO_UPDATE_SIZE_LIMITS
, &fPort
);
132 if (_SetUpNodes() != B_OK
)
133 fWindow
->ToggleMenuOnOff();
135 ((VideoWindow
*)fWindow
)->ApplyControls();
140 CodyCam::QuitRequested()
150 CodyCam::MessageReceived(BMessage
*message
)
152 switch (message
->what
) {
155 BTimeSource
* timeSource
= fMediaRoster
->MakeTimeSourceFor(
157 bigtime_t real
= BTimeSource::RealTime();
158 bigtime_t perf
= timeSource
->PerformanceTimeFor(real
) + 10000;
159 status_t status
= fMediaRoster
->StartNode(fProducerNode
, perf
);
161 ERROR("error starting producer!");
162 timeSource
->Release();
167 fMediaRoster
->StopNode(fProducerNode
, 0, true);
172 if (fVideoControlWindow
) {
173 fVideoControlWindow
->Activate();
176 BParameterWeb
* web
= NULL
;
178 media_node node
= fProducerNode
;
179 status_t err
= fMediaRoster
->GetParameterWebFor(node
, &web
);
180 if (err
>= B_OK
&& web
!= NULL
) {
181 view
= BMediaTheme::ViewFor(web
);
182 fVideoControlWindow
= new ControlWindow(view
, node
);
183 fMediaRoster
->StartWatching(BMessenger(NULL
,
184 fVideoControlWindow
), node
, B_MEDIA_WEB_CHANGED
);
185 fVideoControlWindow
->Show();
190 case msg_control_win
:
191 // our control window is being asked to go away
192 // set our pointer to NULL
193 fVideoControlWindow
= NULL
;
197 BApplication::MessageReceived(message
);
204 CodyCam::_SetUpNodes()
206 status_t status
= B_OK
;
208 /* find the media roster */
209 fMediaRoster
= BMediaRoster::Roster(&status
);
210 if (status
!= B_OK
) {
211 fWindow
->ErrorAlert(B_TRANSLATE("Cannot find the media roster"),
216 /* find the time source */
217 status
= fMediaRoster
->GetTimeSource(&fTimeSourceNode
);
218 if (status
!= B_OK
) {
219 fWindow
->ErrorAlert(B_TRANSLATE("Cannot get a time source"), status
);
223 /* find a video producer node */
224 INFO("CodyCam acquiring VideoInput node\n");
225 status
= fMediaRoster
->GetVideoInput(&fProducerNode
);
226 if (status
!= B_OK
) {
227 fWindow
->ErrorAlert(B_TRANSLATE("Cannot find a video source.\n"
228 "You need a webcam to use CodyCam."), status
);
232 /* create the video consumer node */
233 fVideoConsumer
= new VideoConsumer("CodyCam",
234 ((VideoWindow
*)fWindow
)->VideoView(),
235 ((VideoWindow
*)fWindow
)->StatusLine(), NULL
, 0);
236 if (!fVideoConsumer
) {
237 fWindow
->ErrorAlert(B_TRANSLATE("Cannot create a video window"),
242 /* register the node */
243 status
= fMediaRoster
->RegisterNode(fVideoConsumer
);
244 if (status
!= B_OK
) {
245 fWindow
->ErrorAlert(B_TRANSLATE("Cannot register the video window"),
249 fPort
= fVideoConsumer
->ControlPort();
251 /* find free producer output */
253 status
= fMediaRoster
->GetFreeOutputsFor(fProducerNode
, &fProducerOut
, 1,
254 &cnt
, B_MEDIA_RAW_VIDEO
);
255 if (status
!= B_OK
|| cnt
< 1) {
256 status
= B_RESOURCE_UNAVAILABLE
;
257 fWindow
->ErrorAlert(B_TRANSLATE("Cannot find an available video stream"),
262 /* find free consumer input */
264 status
= fMediaRoster
->GetFreeInputsFor(fVideoConsumer
->Node(),
265 &fConsumerIn
, 1, &cnt
, B_MEDIA_RAW_VIDEO
);
266 if (status
!= B_OK
|| cnt
< 1) {
267 status
= B_RESOURCE_UNAVAILABLE
;
268 fWindow
->ErrorAlert(B_TRANSLATE("Can't find an available connection to "
269 "the video window"), status
);
273 /* Connect The Nodes!!! */
275 format
.type
= B_MEDIA_RAW_VIDEO
;
276 media_raw_video_format vid_format
= {0, 1, 0, 239, B_VIDEO_TOP_LEFT_RIGHT
,
277 1, 1, {B_RGB32
, VIDEO_SIZE_X
, VIDEO_SIZE_Y
, VIDEO_SIZE_X
* 4, 0, 0}};
278 format
.u
.raw_video
= vid_format
;
280 /* connect producer to consumer */
281 status
= fMediaRoster
->Connect(fProducerOut
.source
,
282 fConsumerIn
.destination
, &format
, &fProducerOut
, &fConsumerIn
);
283 if (status
!= B_OK
) {
284 fWindow
->ErrorAlert(B_TRANSLATE("Cannot connect the video source to "
285 "the video window"), status
);
290 /* set time sources */
291 status
= fMediaRoster
->SetTimeSourceFor(fProducerNode
.node
,
292 fTimeSourceNode
.node
);
293 if (status
!= B_OK
) {
294 fWindow
->ErrorAlert(B_TRANSLATE("Cannot set the time source for the "
295 "video source"), status
);
299 status
= fMediaRoster
->SetTimeSourceFor(fVideoConsumer
->ID(),
300 fTimeSourceNode
.node
);
301 if (status
!= B_OK
) {
302 fWindow
->ErrorAlert(B_TRANSLATE("Cannot set the time source for the "
303 "video window"), status
);
307 /* figure out what recording delay to use */
308 bigtime_t latency
= 0;
309 status
= fMediaRoster
->GetLatencyFor(fProducerNode
, &latency
);
310 status
= fMediaRoster
->SetProducerRunModeDelay(fProducerNode
, latency
);
312 /* start the nodes */
313 bigtime_t initLatency
= 0;
314 status
= fMediaRoster
->GetInitialLatencyFor(fProducerNode
, &initLatency
);
316 fWindow
->ErrorAlert(B_TRANSLATE("Error getting initial latency for the "
317 "capture node"), status
);
321 initLatency
+= estimate_max_scheduling_latency();
323 BTimeSource
* timeSource
= fMediaRoster
->MakeTimeSourceFor(fProducerNode
);
324 bool running
= timeSource
->IsRunning();
326 /* workaround for people without sound cards */
327 /* because the system time source won't be running */
328 bigtime_t real
= BTimeSource::RealTime();
330 status
= fMediaRoster
->StartTimeSource(fTimeSourceNode
, real
);
331 if (status
!= B_OK
) {
332 timeSource
->Release();
333 fWindow
->ErrorAlert(B_TRANSLATE("Cannot start time source!"),
337 status
= fMediaRoster
->SeekTimeSource(fTimeSourceNode
, 0, real
);
338 if (status
!= B_OK
) {
339 timeSource
->Release();
340 fWindow
->ErrorAlert(B_TRANSLATE("Cannot seek time source!"),
346 bigtime_t perf
= timeSource
->PerformanceTimeFor(real
+ latency
348 timeSource
->Release();
350 /* start the nodes */
351 status
= fMediaRoster
->StartNode(fProducerNode
, perf
);
352 if (status
!= B_OK
) {
353 fWindow
->ErrorAlert(B_TRANSLATE("Cannot start the video source"),
357 status
= fMediaRoster
->StartNode(fVideoConsumer
->Node(), perf
);
358 if (status
!= B_OK
) {
359 fWindow
->ErrorAlert(B_TRANSLATE("Cannot start the video window"),
369 CodyCam::_TearDownNodes()
371 CALL("CodyCam::_TearDownNodes\n");
375 if (fVideoConsumer
) {
377 INFO("stopping nodes!\n");
378 // fMediaRoster->StopNode(fProducerNode, 0, true);
379 fMediaRoster
->StopNode(fVideoConsumer
->Node(), 0, true);
382 fMediaRoster
->Disconnect(fProducerOut
.node
.node
, fProducerOut
.source
,
383 fConsumerIn
.node
.node
, fConsumerIn
.destination
);
385 if (fProducerNode
!= media_node::null
) {
386 INFO("CodyCam releasing fProducerNode\n");
387 fMediaRoster
->ReleaseNode(fProducerNode
);
388 fProducerNode
= media_node::null
;
390 fMediaRoster
->ReleaseNode(fVideoConsumer
->Node());
391 fVideoConsumer
= NULL
;
396 // #pragma mark - Video Window Class
399 VideoWindow::VideoWindow(const char* title
, window_type type
,
400 uint32 flags
, port_id
* consumerPort
)
402 BWindow(BRect(50, 50, 50, 50), title
, type
, flags
),
403 fPortPtr(consumerPort
),
407 fFtpInfo
.rate
= 0x7fffffff;
408 fFtpInfo
.imageFormat
= 0;
409 fFtpInfo
.translator
= 0;
410 fFtpInfo
.passiveFtp
= true;
411 fFtpInfo
.uploadClient
= 0;
412 strcpy(fFtpInfo
.fileNameText
, "filename");
413 strcpy(fFtpInfo
.serverText
, "server");
414 strcpy(fFtpInfo
.loginText
, "login");
415 strcpy(fFtpInfo
.passwordText
, "password");
416 strcpy(fFtpInfo
.directoryText
, "directory");
418 _SetUpSettings("codycam", "");
420 BMenuBar
* menuBar
= new BMenuBar("menu bar");
423 fMenu
= new BMenu(B_TRANSLATE("File"));
425 menuItem
= new BMenuItem(B_TRANSLATE("Video settings"),
426 new BMessage(msg_video
), 'P');
427 menuItem
->SetTarget(be_app
);
428 fMenu
->AddItem(menuItem
);
430 fMenu
->AddSeparatorItem();
432 menuItem
= new BMenuItem(B_TRANSLATE("Start video"),
433 new BMessage(msg_start
), 'A');
434 menuItem
->SetTarget(be_app
);
435 fMenu
->AddItem(menuItem
);
437 menuItem
= new BMenuItem(B_TRANSLATE("Stop video"),
438 new BMessage(msg_stop
), 'O');
439 menuItem
->SetTarget(be_app
);
440 fMenu
->AddItem(menuItem
);
442 fMenu
->AddSeparatorItem();
444 menuItem
= new BMenuItem(B_TRANSLATE("Quit"),
445 new BMessage(B_QUIT_REQUESTED
), 'Q');
446 menuItem
->SetTarget(be_app
);
447 fMenu
->AddItem(menuItem
);
449 menuBar
->AddItem(fMenu
);
451 /* add some controls */
452 _BuildCaptureControls();
454 BBox
* box
= new BBox("box");
455 BGroupLayout
* layout
= new BGroupLayout(B_VERTICAL
);
456 box
->SetLayout(layout
);
457 layout
->SetInsets(2, 2, 2, 2);
458 box
->AddChild(fVideoView
);
459 box
->AddChild(fErrorView
);
461 BLayoutBuilder::Group
<>(this, B_VERTICAL
, 0)
463 .AddGroup(B_VERTICAL
)
464 .SetInsets(B_USE_WINDOW_SPACING
)
465 .AddGroup(B_HORIZONTAL
)
470 .AddGroup(B_HORIZONTAL
, B_USE_DEFAULT_SPACING
)
471 .Add(fCaptureSetupBox
)
482 VideoWindow::~VideoWindow()
489 VideoWindow::QuitRequested()
491 be_app
->PostMessage(B_QUIT_REQUESTED
);
497 VideoWindow::MessageReceived(BMessage
* message
)
499 BControl
* control
= NULL
;
500 message
->FindPointer((const char*)"source", (void **)&control
);
502 switch (message
->what
) {
504 if (control
!= NULL
) {
505 strlcpy(fFtpInfo
.fileNameText
,
506 ((BTextControl
*)control
)->Text(), 64);
507 FTPINFO("file is '%s'\n", fFtpInfo
.fileNameText
);
511 case msg_rate_changed
: {
513 message
->FindInt32("seconds", &seconds
);
516 fFtpInfo
.rate
= (bigtime_t
)(B_INFINITE_TIMEOUT
);
518 FTPINFO("%ld seconds\n", (long)seconds
);
519 fFtpInfo
.rate
= (bigtime_t
)(seconds
* 1000000LL);
525 message
->FindInt32("be:type", (int32
*)&(fFtpInfo
.imageFormat
));
526 message
->FindInt32("be:translator", &(fFtpInfo
.translator
));
530 message
->FindInt32("client", &(fFtpInfo
.uploadClient
));
531 FTPINFO("upl client = %" B_PRId32
"\n", fFtpInfo
.uploadClient
);
532 _UploadClientChanged();
536 if (control
!= NULL
) {
537 strlcpy(fFtpInfo
.serverText
,
538 ((BTextControl
*)control
)->Text(), 64);
539 FTPINFO("server = '%s'\n", fFtpInfo
.serverText
);
544 if (control
!= NULL
) {
545 strlcpy(fFtpInfo
.loginText
,
546 ((BTextControl
*)control
)->Text(), 64);
547 FTPINFO("login = '%s'\n", fFtpInfo
.loginText
);
552 if (control
!= NULL
) {
553 strlcpy(fFtpInfo
.passwordText
,
554 ((BTextControl
*)control
)->Text(), 64);
555 FTPINFO("password = '%s'\n", fFtpInfo
.passwordText
);
560 if (control
!= NULL
) {
561 strlcpy(fFtpInfo
.directoryText
,
562 ((BTextControl
*)control
)->Text(), 64);
563 FTPINFO("directory = '%s'\n", fFtpInfo
.directoryText
);
568 if (control
!= NULL
) {
569 fFtpInfo
.passiveFtp
= ((BCheckBox
*)control
)->Value();
570 if (fFtpInfo
.passiveFtp
)
571 FTPINFO("using passive ftp\n");
576 BWindow::MessageReceived(message
);
581 write_port(*fPortPtr
, FTP_INFO
, (void*)&fFtpInfo
, sizeof(ftp_msg_info
));
587 VideoWindow::VideoView()
594 VideoWindow::StatusLine()
601 VideoWindow::_BuildCaptureControls()
603 // a view to hold the video image
604 fVideoView
= new BView("Video preview", B_WILL_DRAW
);
605 fVideoView
->SetExplicitMinSize(BSize(VIDEO_SIZE_X
, VIDEO_SIZE_Y
));
606 fVideoView
->SetExplicitMaxSize(BSize(VIDEO_SIZE_X
, VIDEO_SIZE_Y
));
608 fErrorView
= new BTextView("error");
609 fErrorView
->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR
));
612 BGridLayout
*controlsLayout
= new BGridLayout(B_USE_DEFAULT_SPACING
,
613 B_USE_SMALL_SPACING
);
614 controlsLayout
->SetInsets(B_USE_SMALL_SPACING
);
616 BView
* controlView
= new BView("Controls", B_SUPPORTS_LAYOUT
, NULL
);
617 controlView
->SetLayout(controlsLayout
);
619 fCaptureSetupBox
= new BBox("Capture Controls", B_WILL_DRAW
);
620 fCaptureSetupBox
->SetLabel(B_TRANSLATE("Capture controls"));
621 fCaptureSetupBox
->AddChild(controlView
);
624 fFileName
= new BTextControl("File Name", B_TRANSLATE("File name:"),
625 fFilenameSetting
->Value(), new BMessage(msg_filename
));
626 fFileName
->SetTarget(BMessenger(NULL
, this));
629 fImageFormatMenu
= new BPopUpMenu(B_TRANSLATE("Image Format Menu"));
630 BTranslationUtils::AddTranslationItems(fImageFormatMenu
, B_TRANSLATOR_BITMAP
);
631 fImageFormatMenu
->SetTargetForItems(this);
633 if (fImageFormatSettings
->Value()
634 && fImageFormatMenu
->FindItem(fImageFormatSettings
->Value()) != NULL
) {
635 fImageFormatMenu
->FindItem(
636 fImageFormatSettings
->Value())->SetMarked(true);
637 } else if (fImageFormatMenu
->FindItem("JPEG image") != NULL
)
638 fImageFormatMenu
->FindItem("JPEG image")->SetMarked(true);
640 fImageFormatMenu
->ItemAt(0)->SetMarked(true);
642 fImageFormatSelector
= new BMenuField("Format", B_TRANSLATE("Format:"),
646 fCaptureRateMenu
= new BPopUpMenu(B_TRANSLATE("Capture Rate Menu"));
647 for (int32 i
= 0; i
< kCaptureRatesCount
; i
++) {
648 BMessage
* itemMessage
= new BMessage(msg_rate_changed
);
649 itemMessage
->AddInt32("seconds", kCaptureRates
[i
].seconds
);
650 fCaptureRateMenu
->AddItem(new BMenuItem(kCaptureRates
[i
].name
,
653 fCaptureRateMenu
->SetTargetForItems(this);
654 fCaptureRateMenu
->FindItem(fCaptureRateSetting
->Value())->SetMarked(true);
655 fCaptureRateSelector
= new BMenuField("Rate", B_TRANSLATE("Rate:"),
658 BLayoutBuilder::Grid
<>(controlsLayout
)
659 .AddTextControl(fFileName
, 0, 0)
660 .AddMenuField(fImageFormatSelector
, 0, 1)
661 .AddMenuField(fCaptureRateSelector
, 0, 2)
662 .Add(BSpaceLayoutItem::CreateGlue(), 0, 3, 2, 1);
665 BGridLayout
* ftpLayout
= new BGridLayout(B_USE_DEFAULT_SPACING
,
666 B_USE_SMALL_SPACING
);
667 ftpLayout
->SetInsets(B_USE_SMALL_SPACING
);
669 BView
* outputView
= new BView("Output", B_SUPPORTS_LAYOUT
, NULL
);
670 outputView
->SetLayout(ftpLayout
);
672 fFtpSetupBox
= new BBox("FTP Setup", B_WILL_DRAW
);
673 fFtpSetupBox
->SetLabel(B_TRANSLATE("Output"));
674 fFtpSetupBox
->AddChild(outputView
);
675 float minWidth
= be_plain_font
->StringWidth(
676 "The server label plus ftp.reasonably.com");
677 fFtpSetupBox
->SetExplicitMinSize(BSize(minWidth
, B_SIZE_UNSET
));
678 fFtpSetupBox
->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED
, B_SIZE_UNSET
));
680 fUploadClientMenu
= new BPopUpMenu(B_TRANSLATE("Send to" B_UTF8_ELLIPSIS
));
681 for (int i
= 0; i
< kUploadClientsCount
; i
++) {
682 BMessage
*m
= new BMessage(msg_upl_client
);
683 m
->AddInt32("client", i
);
684 fUploadClientMenu
->AddItem(new BMenuItem(kUploadClients
[i
], m
));
687 fUploadClientMenu
->SetTargetForItems(this);
688 fUploadClientMenu
->FindItem(fUploadClientSetting
->Value())->SetMarked(true);
690 fUploadClientSelector
= new BMenuField("UploadClient", NULL
,
693 fUploadClientSelector
->SetLabel(B_TRANSLATE("Type:"));
695 fServerName
= new BTextControl("Server", B_TRANSLATE("Server:"),
696 fServerSetting
->Value(), new BMessage(msg_server
));
697 fServerName
->SetTarget(this);
699 fLoginId
= new BTextControl("Login", B_TRANSLATE("Login:"),
700 fLoginSetting
->Value(), new BMessage(msg_login
));
701 fLoginId
->SetTarget(this);
703 fPassword
= new BTextControl("Password", B_TRANSLATE("Password:"),
704 fPasswordSetting
->Value(), new BMessage(msg_password
));
705 fPassword
->SetTarget(this);
706 fPassword
->TextView()->HideTyping(true);
707 // BeOS HideTyping() seems broken, it empties the text
708 fPassword
->SetText(fPasswordSetting
->Value());
710 fDirectory
= new BTextControl("Directory", B_TRANSLATE("Directory:"),
711 fDirectorySetting
->Value(), new BMessage(msg_directory
));
712 fDirectory
->SetTarget(this);
714 fPassiveFtp
= new BCheckBox("Passive FTP", B_TRANSLATE("Passive FTP"),
715 new BMessage(msg_passiveftp
));
716 fPassiveFtp
->SetTarget(this);
717 fPassiveFtp
->SetValue(fPassiveFtpSetting
->Value());
718 fPassiveFtp
->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED
, B_SIZE_UNSET
));
720 BLayoutBuilder::Grid
<>(ftpLayout
)
721 .AddMenuField(fUploadClientSelector
, 0, 0)
722 .AddTextControl(fServerName
, 0, 1)
723 .AddTextControl(fLoginId
, 0, 2)
724 .AddTextControl(fPassword
, 0, 3)
725 .AddTextControl(fDirectory
, 0, 4)
726 .Add(fPassiveFtp
, 0, 5, 2, 1);
728 fStatusLine
= new BStringView("Status Line",
729 B_TRANSLATE("Waiting" B_UTF8_ELLIPSIS
));
730 fStatusLine
->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED
, B_SIZE_UNSET
));
735 VideoWindow::ApplyControls()
742 PostMessage(fImageFormatMenu
->FindMarked()->Message());
743 PostMessage(fCaptureRateMenu
->FindMarked()->Message());
744 PostMessage(fUploadClientMenu
->FindMarked()->Message());
745 fServerName
->Invoke();
748 fDirectory
->Invoke();
749 fPassiveFtp
->Invoke();
756 VideoWindow::ErrorAlert(const char* message
, status_t err
)
759 fErrorView
->SetText(message
);
760 fErrorView
->MakeEditable(false);
761 fErrorView
->MakeSelectable(false);
762 fErrorView
->SetWordWrap(true);
763 fErrorView
->SetExplicitMinSize(BSize(VIDEO_SIZE_X
, VIDEO_SIZE_Y
));
764 fErrorView
->SetExplicitMaxSize(BSize(VIDEO_SIZE_X
, VIDEO_SIZE_Y
));
769 printf("%s\n%s [%" B_PRIx32
"]", message
, strerror(err
), err
);
774 VideoWindow::_SetUpSettings(const char* filename
, const char* dirname
)
776 fSettings
= new Settings(filename
, dirname
);
778 fServerSetting
= new StringValueSetting("Server", "ftp.my.server",
779 B_TRANSLATE("server address expected"));
781 fLoginSetting
= new StringValueSetting("Login", "loginID",
782 B_TRANSLATE("login ID expected"));
784 fPasswordSetting
= new StringValueSetting("Password",
785 B_TRANSLATE("password"), B_TRANSLATE("password expected"));
787 fDirectorySetting
= new StringValueSetting("Directory", "web/images",
788 B_TRANSLATE("destination directory expected"));
790 fPassiveFtpSetting
= new BooleanValueSetting("PassiveFtp", 1);
792 fFilenameSetting
= new StringValueSetting("StillImageFilename",
793 "codycam.jpg", B_TRANSLATE("still image filename expected"));
795 fImageFormatSettings
= new StringValueSetting("ImageFileFormat",
796 B_TRANSLATE("JPEG image"), B_TRANSLATE("image file format expected"));
798 fCaptureRateSetting
= new EnumeratedStringValueSetting("CaptureRate",
799 kCaptureRates
[3].name
, &CaptureRateAt
,
800 B_TRANSLATE("capture rate expected"),
801 "unrecognized capture rate specified");
803 fUploadClientSetting
= new EnumeratedStringValueSetting("UploadClient",
804 B_TRANSLATE("FTP"), &UploadClientAt
,
805 B_TRANSLATE("upload client name expected"),
806 B_TRANSLATE("unrecognized upload client specified"));
808 fSettings
->Add(fServerSetting
);
809 fSettings
->Add(fLoginSetting
);
810 fSettings
->Add(fPasswordSetting
);
811 fSettings
->Add(fDirectorySetting
);
812 fSettings
->Add(fPassiveFtpSetting
);
813 fSettings
->Add(fFilenameSetting
);
814 fSettings
->Add(fImageFormatSettings
);
815 fSettings
->Add(fCaptureRateSetting
);
816 fSettings
->Add(fUploadClientSetting
);
818 fSettings
->TryReadingSettings();
823 VideoWindow::_UploadClientChanged()
825 bool enableServerControls
= fFtpInfo
.uploadClient
< 2;
826 fServerName
->SetEnabled(enableServerControls
);
827 fLoginId
->SetEnabled(enableServerControls
);
828 fPassword
->SetEnabled(enableServerControls
);
829 fDirectory
->SetEnabled(enableServerControls
);
830 fPassiveFtp
->SetEnabled(enableServerControls
);
835 VideoWindow::_QuitSettings()
837 fServerSetting
->ValueChanged(fServerName
->Text());
838 fLoginSetting
->ValueChanged(fLoginId
->Text());
839 fPasswordSetting
->ValueChanged(fFtpInfo
.passwordText
);
840 fDirectorySetting
->ValueChanged(fDirectory
->Text());
841 fPassiveFtpSetting
->ValueChanged(fPassiveFtp
->Value());
842 fFilenameSetting
->ValueChanged(fFileName
->Text());
843 fImageFormatSettings
->ValueChanged(fImageFormatMenu
->FindMarked()->Label());
844 fCaptureRateSetting
->ValueChanged(fCaptureRateMenu
->FindMarked()->Label());
845 fUploadClientSetting
->ValueChanged(fUploadClientMenu
->FindMarked()->Label());
847 fSettings
->SaveSettings();
853 VideoWindow::ToggleMenuOnOff()
855 BMenuItem
* item
= fMenu
->FindItem(msg_video
);
856 item
->SetEnabled(!item
->IsEnabled());
858 item
= fMenu
->FindItem(msg_start
);
859 item
->SetEnabled(!item
->IsEnabled());
861 item
= fMenu
->FindItem(msg_stop
);
862 item
->SetEnabled(!item
->IsEnabled());
869 ControlWindow::ControlWindow(BView
* controls
,
872 BWindow(BRect(), B_TRANSLATE("Video settings"), B_TITLED_WINDOW
,
873 B_ASYNCHRONOUS_CONTROLS
)
883 ControlWindow::MessageReceived(BMessage
* message
)
885 BParameterWeb
* web
= NULL
;
888 switch (message
->what
) {
889 case B_MEDIA_WEB_CHANGED
:
891 // If this is a tab view, find out which tab
893 BTabView
* tabView
= dynamic_cast<BTabView
*>(fView
);
896 tabNum
= tabView
->Selection();
901 err
= BMediaRoster::Roster()->GetParameterWebFor(fNode
, &web
);
903 if (err
>= B_OK
&& web
!= NULL
) {
904 fView
= BMediaTheme::ViewFor(web
);
907 // Another tab view? Restore previous selection
909 BTabView
* newTabView
= dynamic_cast<BTabView
*>(fView
);
911 newTabView
->Select(tabNum
);
918 BWindow::MessageReceived(message
);
924 ControlWindow::QuitRequested()
926 be_app
->PostMessage(msg_control_win
);