#include "CodyCam.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define VIDEO_SIZE_X 320 #define VIDEO_SIZE_Y 240 #define WINDOW_SIZE_X (VIDEO_SIZE_X + 80) #define WINDOW_SIZE_Y (VIDEO_SIZE_Y + 230) #define WINDOW_OFFSET_X 28 #define WINDOW_OFFSET_Y 28 const int32 kBtnHeight = 20; const int32 kBtnWidth = 60; const int32 kBtnBuffer = 25; const int32 kXBuffer = 10; const int32 kYBuffer = 10; const int32 kMenuHeight = 15; const int32 kButtonHeight = 15; const int32 kSliderViewRectHeight = 40; const rgb_color kViewGray = { 216, 216, 216, 255}; static void ErrorAlert(const char * message, status_t err); static status_t AddTranslationItems( BMenu * intoMenu, uint32 from_type); #define CALL printf #define ERROR printf #define FTPINFO printf #define INFO printf //--------------------------------------------------------------- // The Application //--------------------------------------------------------------- int main() { chdir("/boot/home"); CodyCam app; app.Run(); return 0; } //--------------------------------------------------------------- CodyCam::CodyCam() : BApplication("application/x-vnd.Be.CodyCam"), fMediaRoster(NULL), fVideoConsumer(NULL), fWindow(NULL), fPort(0), mVideoControlWindow(NULL) { } //--------------------------------------------------------------- CodyCam::~CodyCam() { CALL("CodyCam::~CodyCam\n"); // release the video consumer node // the consumer node cleans up the window if (fVideoConsumer) { fVideoConsumer->Release(); fVideoConsumer = NULL; } CALL("CodyCam::~CodyCam - EXIT\n"); } //--------------------------------------------------------------- void CodyCam::ReadyToRun() { /* create the window for the app */ fWindow = new VideoWindow(BRect(28, 28, 28 + (WINDOW_SIZE_X-1), 28 + (WINDOW_SIZE_Y-1)), (const char *)"CodyCam", B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE, &fPort); /* set up the node connections */ status_t status = SetUpNodes(); if (status != B_OK) { ErrorAlert("Error setting up nodes", status); return; } ((VideoWindow *)fWindow)->ApplyControls(); } //--------------------------------------------------------------- bool CodyCam::QuitRequested() { TearDownNodes(); snooze(100000); return true; } //--------------------------------------------------------------- void CodyCam::MessageReceived(BMessage *message) { switch (message->what) { case msg_start: { BTimeSource *timeSource = fMediaRoster->MakeTimeSourceFor(fTimeSourceNode); bigtime_t real = BTimeSource::RealTime(); bigtime_t perf = timeSource->PerformanceTimeFor(real) + 10000; status_t status = fMediaRoster->StartNode(fProducerNode, perf); if (status != B_OK) ERROR("error starting producer!"); timeSource->Release(); break; } case msg_stop: fMediaRoster->StopNode(fProducerNode, 0, true); break; case msg_video: { if (mVideoControlWindow) { mVideoControlWindow->Activate(); break; } BParameterWeb * web = NULL; BView * view = NULL; media_node node = fProducerNode; status_t err = fMediaRoster->GetParameterWebFor(node, &web); if ((err >= B_OK) && (web != NULL)) { view = BMediaTheme::ViewFor(web); mVideoControlWindow = new ControlWindow( BRect(2*WINDOW_OFFSET_X + WINDOW_SIZE_X, WINDOW_OFFSET_Y, 2*WINDOW_OFFSET_X + WINDOW_SIZE_X + view->Bounds().right, WINDOW_OFFSET_Y + view->Bounds().bottom), view, node); fMediaRoster->StartWatching(BMessenger(NULL, mVideoControlWindow), node, B_MEDIA_WEB_CHANGED); mVideoControlWindow->Show(); } break; } case msg_about: { (new BAlert("About CodyCam", "CodyCam\n\nThe Original BeOS WebCam", "Close"))->Go(); break; } case msg_control_win: { // our control window is being asked to go away // set our pointer to NULL mVideoControlWindow = NULL; break; } default: BApplication::MessageReceived(message); break; } } //--------------------------------------------------------------- status_t CodyCam::SetUpNodes() { status_t status = B_OK; /* find the media roster */ fMediaRoster = BMediaRoster::Roster(&status); if (status != B_OK) { ErrorAlert("Can't find the media roster", status); return status; } /* find the time source */ status = fMediaRoster->GetTimeSource(&fTimeSourceNode); if (status != B_OK) { ErrorAlert("Can't get a time source", status); return status; } /* find a video producer node */ INFO("CodyCam acquiring VideoInput node\n"); status = fMediaRoster->GetVideoInput(&fProducerNode); if (status != B_OK) { ErrorAlert("Can't find a video input!", status); return status; } /* create the video consumer node */ fVideoConsumer = new VideoConsumer("CodyCam", ((VideoWindow *)fWindow)->VideoView(), ((VideoWindow *)fWindow)->StatusLine(), NULL, 0); if (!fVideoConsumer) { ErrorAlert("Can't create a video window", B_ERROR); return B_ERROR; } /* register the node */ status = fMediaRoster->RegisterNode(fVideoConsumer); if (status != B_OK) { ErrorAlert("Can't register the video window", status); return status; } fPort = fVideoConsumer->ControlPort(); /* find free producer output */ int32 cnt = 0; status = fMediaRoster->GetFreeOutputsFor(fProducerNode, &fProducerOut, 1, &cnt, B_MEDIA_RAW_VIDEO); if (status != B_OK || cnt < 1) { status = B_RESOURCE_UNAVAILABLE; ErrorAlert("Can't find an available video stream", status); return status; } /* find free consumer input */ cnt = 0; status = fMediaRoster->GetFreeInputsFor(fVideoConsumer->Node(), &fConsumerIn, 1, &cnt, B_MEDIA_RAW_VIDEO); if (status != B_OK || cnt < 1) { status = B_RESOURCE_UNAVAILABLE; ErrorAlert("Can't find an available connection to the video window", status); return status; } /* Connect The Nodes!!! */ media_format format; format.type = B_MEDIA_RAW_VIDEO; media_raw_video_format vid_format = { 0, 1, 0, 239, B_VIDEO_TOP_LEFT_RIGHT, 1, 1, {B_RGB32, VIDEO_SIZE_X, VIDEO_SIZE_Y, VIDEO_SIZE_X*4, 0, 0}}; format.u.raw_video = vid_format; /* connect producer to consumer */ status = fMediaRoster->Connect(fProducerOut.source, fConsumerIn.destination, &format, &fProducerOut, &fConsumerIn); if (status != B_OK) { ErrorAlert("Can't connect the video source to the video window", status); return status; } /* set time sources */ status = fMediaRoster->SetTimeSourceFor(fProducerNode.node, fTimeSourceNode.node); if (status != B_OK) { ErrorAlert("Can't set the timesource for the video source", status); return status; } status = fMediaRoster->SetTimeSourceFor(fVideoConsumer->ID(), fTimeSourceNode.node); if (status != B_OK) { ErrorAlert("Can't set the timesource for the video window", status); return status; } /* figure out what recording delay to use */ bigtime_t latency = 0; status = fMediaRoster->GetLatencyFor(fProducerNode, &latency); status = fMediaRoster->SetProducerRunModeDelay(fProducerNode, latency); /* start the nodes */ bigtime_t initLatency = 0; status = fMediaRoster->GetInitialLatencyFor(fProducerNode, &initLatency); if (status < B_OK) { ErrorAlert("error getting initial latency for fCaptureNode", status); } initLatency += estimate_max_scheduling_latency(); BTimeSource *timeSource = fMediaRoster->MakeTimeSourceFor(fProducerNode); bool running = timeSource->IsRunning(); /* workaround for people without sound cards */ /* because the system time source won't be running */ bigtime_t real = BTimeSource::RealTime(); if (!running) { status = fMediaRoster->StartTimeSource(fTimeSourceNode, real); if (status != B_OK) { timeSource->Release(); ErrorAlert("cannot start time source!", status); return status; } status = fMediaRoster->SeekTimeSource(fTimeSourceNode, 0, real); if (status != B_OK) { timeSource->Release(); ErrorAlert("cannot seek time source!", status); return status; } } bigtime_t perf = timeSource->PerformanceTimeFor(real + latency + initLatency); timeSource->Release(); /* start the nodes */ status = fMediaRoster->StartNode(fProducerNode, perf); if (status != B_OK) { ErrorAlert("Can't start the video source", status); return status; } status = fMediaRoster->StartNode(fVideoConsumer->Node(), perf); if (status != B_OK) { ErrorAlert("Can't start the video window", status); return status; } return status; } //--------------------------------------------------------------- void CodyCam::TearDownNodes() { CALL("CodyCam::TearDownNodes\n"); if (!fMediaRoster) return; if (fVideoConsumer) { /* stop */ INFO("stopping nodes!\n"); // fMediaRoster->StopNode(fProducerNode, 0, true); fMediaRoster->StopNode(fVideoConsumer->Node(), 0, true); /* disconnect */ fMediaRoster->Disconnect(fProducerOut.node.node, fProducerOut.source, fConsumerIn.node.node, fConsumerIn.destination); if (fProducerNode != media_node::null) { INFO("CodyCam releasing fProducerNode\n"); fMediaRoster->ReleaseNode(fProducerNode); fProducerNode = media_node::null; } fMediaRoster->ReleaseNode(fVideoConsumer->Node()); fVideoConsumer = NULL; } } //--------------------------------------------------------------- // Utility functions //--------------------------------------------------------------- static void ErrorAlert(const char * message, status_t err) { char msg[256]; sprintf(msg, "%s\n%s [%lx]", message, strerror(err), err); (new BAlert("", msg, "Quit"))->Go(); be_app->PostMessage(B_QUIT_REQUESTED); } //--------------------------------------------------------------- status_t AddTranslationItems( BMenu * intoMenu, uint32 from_type) { BTranslatorRoster * use; char * translator_type_name; const char * translator_id_name; use = BTranslatorRoster::Default(); translator_id_name = "be:translator"; translator_type_name = "be:type"; translator_id * ids = NULL; int32 count = 0; status_t err = use->GetAllTranslators(&ids, &count); if (err < B_OK) return err; for (int tix=0; tixGetInputFormats(ids[tix], &formats, &num_formats); if (err == B_OK) for (int iix=0; iixGetOutputFormats(ids[tix], &formats, &num_formats); if (err == B_OK) for (int oix=0; oixAddInt32(translator_id_name, ids[tix]); itemmsg->AddInt32(translator_type_name, formats[oix].type); intoMenu->AddItem(new BMenuItem(formats[oix].name, itemmsg)); } } } delete[] ids; return B_OK; } //--------------------------------------------------------------- // Video Window Class //--------------------------------------------------------------- VideoWindow::VideoWindow (BRect frame, const char *title, window_type type, uint32 flags, port_id * consumerport) : BWindow(frame,title,type,flags), fPortPtr(consumerport), fView(NULL), fVideoView(NULL) { fFtpInfo.port = 0; fFtpInfo.rate = 0x7fffffff; fFtpInfo.imageFormat = 0; fFtpInfo.translator = 0; fFtpInfo.passiveFtp = true; strcpy(fFtpInfo.fileNameText, "filename"); strcpy(fFtpInfo.serverText, "server"); strcpy(fFtpInfo.loginText, "login"); strcpy(fFtpInfo.passwordText, "password"); strcpy(fFtpInfo.directoryText, "directory"); SetUpSettings("codycam", ""); BMenuBar* menuBar = new BMenuBar(BRect(0,0,0,0), "menu bar"); AddChild(menuBar); BMenuItem* menuItem; BMenu* menu = new BMenu("File"); menuItem = new BMenuItem("Video Preferences", new BMessage(msg_video), 'P'); menuItem->SetTarget(be_app); menu->AddItem(menuItem); menu->AddSeparatorItem(); menuItem = new BMenuItem("Start Video", new BMessage(msg_start), 'A'); menuItem->SetTarget(be_app); menu->AddItem(menuItem); menuItem = new BMenuItem("Stop Video", new BMessage(msg_stop), 'O'); menuItem->SetTarget(be_app); menu->AddItem(menuItem); menu->AddSeparatorItem(); menuItem = new BMenuItem("About Codycam", new BMessage(msg_about), 'B'); menuItem->SetTarget(be_app); menu->AddItem(menuItem); menu->AddSeparatorItem(); menuItem = new BMenuItem("Quit", new BMessage(B_QUIT_REQUESTED), 'Q'); menuItem->SetTarget(be_app); menu->AddItem(menuItem); menuBar->AddItem(menu); /* give it a gray background view */ BRect aRect; aRect = Frame(); aRect.OffsetTo(B_ORIGIN); aRect.top += menuBar->Frame().Height() + 1; fView = new BView(aRect, "Background View", B_FOLLOW_ALL, B_WILL_DRAW); fView->SetViewColor(kViewGray); AddChild(fView); /* add some controls */ BuildCaptureControls(fView); /* add another view to hold the video image */ aRect = BRect(0, 0, VIDEO_SIZE_X - 1, VIDEO_SIZE_Y - 1); aRect.OffsetBy((WINDOW_SIZE_X - VIDEO_SIZE_X)/2, kYBuffer); fVideoView = new BView(aRect, "Video View", B_FOLLOW_ALL, B_WILL_DRAW); fView->AddChild(fVideoView); Show(); } //--------------------------------------------------------------- VideoWindow::~VideoWindow() { QuitSettings(); } //--------------------------------------------------------------- bool VideoWindow::QuitRequested() { be_app->PostMessage(B_QUIT_REQUESTED); return false; } //--------------------------------------------------------------- void VideoWindow::MessageReceived(BMessage *message) { BControl *p; p = NULL; message->FindPointer((const char *)"source",(void **)&p); switch (message->what) { case msg_filename: if (p != NULL) { strncpy(fFtpInfo.fileNameText, ((BTextControl *)p)->Text(), 63); FTPINFO("file is '%s'\n", fFtpInfo.fileNameText); } break; case msg_rate_15s: FTPINFO("fifteen seconds\n"); fFtpInfo.rate = (bigtime_t)(15 * 1000000); break; case msg_rate_30s: FTPINFO("thirty seconds\n"); fFtpInfo.rate = (bigtime_t)(30 * 1000000); break; case msg_rate_1m: FTPINFO("one minute\n"); fFtpInfo.rate = (bigtime_t)(1 * 60 * 1000000); break; case msg_rate_5m: FTPINFO("five minute\n"); fFtpInfo.rate = (bigtime_t)(5 * 60 * 1000000); break; case msg_rate_10m: FTPINFO("ten minute\n"); fFtpInfo.rate = (bigtime_t)(10 * 60 * 1000000); break; case msg_rate_15m: FTPINFO("fifteen minute\n"); fFtpInfo.rate = (bigtime_t)(15 * 60 * 1000000); break; case msg_rate_30m: FTPINFO("thirty minute\n"); fFtpInfo.rate = (bigtime_t)(30 * 60 * 1000000); break; case msg_rate_1h: FTPINFO("one hour\n"); fFtpInfo.rate = (bigtime_t)(60LL * 60LL * 1000000LL); break; case msg_rate_2h: FTPINFO("two hour\n"); fFtpInfo.rate = (bigtime_t)(2LL * 60LL * 60LL * 1000000LL); break; case msg_rate_4h: FTPINFO("four hour\n"); fFtpInfo.rate = (bigtime_t)(4LL * 60LL * 60LL * 1000000LL); break; case msg_rate_8h: FTPINFO("eight hour\n"); fFtpInfo.rate = (bigtime_t)(8LL * 60LL * 60LL * 1000000LL); break; case msg_rate_24h: FTPINFO("24 hour\n"); fFtpInfo.rate = (bigtime_t)(24LL * 60LL * 60LL * 1000000LL); break; case msg_rate_never: FTPINFO("never\n"); fFtpInfo.rate = (bigtime_t)(B_INFINITE_TIMEOUT); break; case msg_translate: message->FindInt32("be:type", (int32 *)&(fFtpInfo.imageFormat)); message->FindInt32("be:translator", &(fFtpInfo.translator)); break; case msg_server: if (p != NULL) { strncpy(fFtpInfo.serverText, ((BTextControl *)p)->Text(), 64); FTPINFO("server = '%s'\n", fFtpInfo.serverText); } break; case msg_login: if (p != NULL) { strncpy(fFtpInfo.loginText, ((BTextControl *)p)->Text(), 64); FTPINFO("login = '%s'\n", fFtpInfo.loginText); } break; case msg_password: if (p != NULL) { strncpy(fFtpInfo.passwordText, ((BTextControl *)p)->Text(), 64); FTPINFO("password = '%s'\n", fFtpInfo.passwordText); if (Lock()) { ((BTextControl *)p)->SetText(""); Unlock(); } } break; case msg_directory: if (p != NULL) { strncpy(fFtpInfo.directoryText, ((BTextControl *)p)->Text(), 64); FTPINFO("directory = '%s'\n", fFtpInfo.directoryText); } break; case msg_passiveftp: if (p != NULL) { fFtpInfo.passiveFtp = ((BCheckBox *)p)->Value(); if (fFtpInfo.passiveFtp) FTPINFO("using passive ftp\n"); } break; default: BWindow::MessageReceived(message); return; } if (*fPortPtr) write_port(*fPortPtr, FTP_INFO, (void *)&fFtpInfo, sizeof(ftp_msg_info)); } //--------------------------------------------------------------- BView * VideoWindow::VideoView() { return fVideoView; } //--------------------------------------------------------------- BStringView * VideoWindow::StatusLine() { return fStatusLine; } //--------------------------------------------------------------- void VideoWindow::BuildCaptureControls(BView *theView) { BRect aFrame, theFrame; theFrame = theView->Bounds(); theFrame.top += VIDEO_SIZE_Y + 2*kYBuffer + 40; theFrame.left += kXBuffer; theFrame.right -= (WINDOW_SIZE_X/2 + 5); theFrame.bottom -= kXBuffer; fCaptureSetupBox = new BBox( theFrame, "Capture Controls", B_FOLLOW_ALL, B_WILL_DRAW); fCaptureSetupBox->SetLabel("Capture Controls"); theView->AddChild(fCaptureSetupBox); aFrame = fCaptureSetupBox->Bounds(); aFrame.InsetBy(kXBuffer,kYBuffer); aFrame.top += kYBuffer/2; aFrame.bottom = aFrame.top + kMenuHeight; fFileName = new BTextControl(aFrame, "File Name", "File Name:", fFilenameSetting->Value(), new BMessage(msg_filename)); fFileName->SetTarget(BMessenger(NULL, this)); fFileName->SetDivider(fFileName->Divider() - 30); fCaptureSetupBox->AddChild(fFileName); aFrame.top = aFrame.bottom + kYBuffer; aFrame.bottom = aFrame.top + kMenuHeight; fImageFormatMenu = new BPopUpMenu("Image Format Menu"); AddTranslationItems(fImageFormatMenu, B_TRANSLATOR_BITMAP); fImageFormatMenu->SetTargetForItems(this); if (fImageFormatMenu->FindItem("JPEG Image") != NULL) fImageFormatMenu->FindItem("JPEG Image")->SetMarked(true); else fImageFormatMenu->ItemAt(0)->SetMarked(true); fImageFormatSelector = new BMenuField(aFrame, "Format", "Format:", fImageFormatMenu); fImageFormatSelector->SetDivider(fImageFormatSelector->Divider() - 30); fCaptureSetupBox->AddChild(fImageFormatSelector); aFrame.top = aFrame.bottom + kYBuffer; aFrame.bottom = aFrame.top + kMenuHeight; fCaptureRateMenu = new BPopUpMenu("Capture Rate Menu"); fCaptureRateMenu->AddItem(new BMenuItem("Every 15 seconds",new BMessage(msg_rate_15s))); fCaptureRateMenu->AddItem(new BMenuItem("Every 30 seconds",new BMessage(msg_rate_30s))); fCaptureRateMenu->AddItem(new BMenuItem("Every minute",new BMessage(msg_rate_1m))); fCaptureRateMenu->AddItem(new BMenuItem("Every 5 minutes",new BMessage(msg_rate_5m))); fCaptureRateMenu->AddItem(new BMenuItem("Every 10 minutes",new BMessage(msg_rate_10m))); fCaptureRateMenu->AddItem(new BMenuItem("Every 15 minutes",new BMessage(msg_rate_15m))); fCaptureRateMenu->AddItem(new BMenuItem("Every 30 minutes",new BMessage(msg_rate_30m))); fCaptureRateMenu->AddItem(new BMenuItem("Every hour",new BMessage(msg_rate_1h))); fCaptureRateMenu->AddItem(new BMenuItem("Every 2 hours",new BMessage(msg_rate_2h))); fCaptureRateMenu->AddItem(new BMenuItem("Every 4 hours",new BMessage(msg_rate_4h))); fCaptureRateMenu->AddItem(new BMenuItem("Every 8 hours",new BMessage(msg_rate_8h))); fCaptureRateMenu->AddItem(new BMenuItem("Every 24 hours",new BMessage(msg_rate_24h))); fCaptureRateMenu->AddItem(new BMenuItem("Never",new BMessage(msg_rate_never))); fCaptureRateMenu->SetTargetForItems(this); fCaptureRateMenu->FindItem(fCaptureRateSetting->Value())->SetMarked(true); fCaptureRateSelector = new BMenuField(aFrame, "Rate", "Rate:", fCaptureRateMenu); fCaptureRateSelector->SetDivider(fCaptureRateSelector->Divider() - 30); fCaptureSetupBox->AddChild(fCaptureRateSelector); aFrame = theView->Bounds(); aFrame.top += VIDEO_SIZE_Y + 2*kYBuffer + 40; aFrame.left += WINDOW_SIZE_X/2 + 5; aFrame.right -= kXBuffer; aFrame.bottom -= kYBuffer; fFtpSetupBox = new BBox( aFrame, "Ftp Setup", B_FOLLOW_ALL, B_WILL_DRAW); fFtpSetupBox->SetLabel("Ftp Setup"); theView->AddChild(fFtpSetupBox); aFrame = fFtpSetupBox->Bounds(); aFrame.InsetBy(kXBuffer,kYBuffer); aFrame.top += kYBuffer/2; aFrame.bottom = aFrame.top + kMenuHeight; aFrame.right = aFrame.left + 160; fServerName = new BTextControl(aFrame, "Server", "Server:", fServerSetting->Value(), new BMessage(msg_server)); fServerName->SetTarget(this); fServerName->SetDivider(fServerName->Divider() - 30); fFtpSetupBox->AddChild(fServerName); aFrame.top = aFrame.bottom + kYBuffer; aFrame.bottom = aFrame.top + kMenuHeight; fLoginId = new BTextControl(aFrame, "Login", "Login:", fLoginSetting->Value(), new BMessage(msg_login)); fLoginId->SetTarget(this); fLoginId->SetDivider(fLoginId->Divider() - 30); fFtpSetupBox->AddChild(fLoginId); aFrame.top = aFrame.bottom + kYBuffer; aFrame.bottom = aFrame.top + kMenuHeight; fPassword = new BTextControl(aFrame, "Password", "Password:", fPasswordSetting->Value(), new BMessage(msg_password)); fPassword->SetTarget(this); fPassword->SetDivider(fPassword->Divider() - 30); fFtpSetupBox->AddChild(fPassword); aFrame.top = aFrame.bottom + kYBuffer; aFrame.bottom = aFrame.top + kMenuHeight; fDirectory = new BTextControl(aFrame, "Directory", "Directory:", fDirectorySetting->Value(), new BMessage(msg_directory)); fDirectory->SetTarget(this); fDirectory->SetDivider(fDirectory->Divider() - 30); fFtpSetupBox->AddChild(fDirectory); aFrame.top = aFrame.bottom + kYBuffer; aFrame.bottom = aFrame.top + kMenuHeight; fPassiveFtp = new BCheckBox(aFrame, "Passive ftp", "Passive ftp", new BMessage(msg_passiveftp)); fPassiveFtp->SetTarget(this); fPassiveFtp->SetValue(fPassiveFtpSetting->Value()); fFtpSetupBox->AddChild(fPassiveFtp); aFrame = theView->Bounds(); aFrame.top += VIDEO_SIZE_Y + 2*kYBuffer; aFrame.left += kXBuffer; aFrame.right -= kXBuffer; aFrame.bottom = aFrame.top + kMenuHeight + 2*kYBuffer; fStatusBox = new BBox( aFrame, "Status", B_FOLLOW_ALL, B_WILL_DRAW); fStatusBox->SetLabel("Status"); theView->AddChild(fStatusBox); aFrame = fStatusBox->Bounds(); aFrame.InsetBy(kXBuffer,kYBuffer); fStatusLine = new BStringView(aFrame,"Status Line","Waiting ..."); fStatusBox->AddChild(fStatusLine); } //--------------------------------------------------------------- void VideoWindow::ApplyControls() { // apply controls fFileName->Invoke(); PostMessage(fImageFormatMenu->FindMarked()->Message()); PostMessage(fCaptureRateMenu->FindMarked()->Message()); fServerName->Invoke(); fLoginId->Invoke(); fPassword->Invoke(); fDirectory->Invoke(); fPassiveFtp->Invoke(); } //--------------------------------------------------------------- void VideoWindow::SetUpSettings(const char *filename, const char *dirname) { fSettings = new Settings(filename, dirname); fSettings->Add(fServerSetting = new StringValueSetting("Server", "ftp.my.server", "server address expected", "")); fSettings->Add(fLoginSetting = new StringValueSetting("Login", "loginID", "login ID expected", "")); fSettings->Add(fPasswordSetting = new StringValueSetting("Password", "password", "password expected", "")); fSettings->Add(fDirectorySetting = new StringValueSetting("Directory", "web/images", "destination directory expected", "")); fSettings->Add(fPassiveFtpSetting = new BooleanValueSetting("PassiveFtp", 1)); fSettings->Add(fFilenameSetting = new StringValueSetting("StillImageFilename", "codycam.jpg", "still image filename expected", "")); fSettings->Add(fCaptureRateSetting = new EnumeratedStringValueSetting("CaptureRate", "Every 5 minutes", kCaptureRate, "capture rate expected", "unrecognized capture rate specified")); fSettings->TryReadingSettings(); } //--------------------------------------------------------------- void VideoWindow::QuitSettings() { fServerSetting->ValueChanged(fServerName->Text()); fLoginSetting->ValueChanged(fLoginId->Text()); fPasswordSetting->ValueChanged(fFtpInfo.passwordText); fDirectorySetting->ValueChanged(fDirectory->Text()); fPassiveFtpSetting->ValueChanged(fPassiveFtp->Value()); fFilenameSetting->ValueChanged(fFileName->Text()); fCaptureRateSetting->ValueChanged(fCaptureRateMenu->FindMarked()->Label()); fSettings->SaveSettings(); delete fSettings; } //--------------------------------------------------------------- ControlWindow::ControlWindow( const BRect & frame, BView * controls, media_node node) : BWindow(frame, "Video Preferences", B_TITLED_WINDOW, B_ASYNCHRONOUS_CONTROLS) { fView = controls; fNode = node; AddChild(fView); } //--------------------------------------------------------------- void ControlWindow::MessageReceived(BMessage * message) { BParameterWeb * web = NULL; status_t err; switch (message->what) { case B_MEDIA_WEB_CHANGED: { // If this is a tab view, find out which tab // is selected BTabView *tabView = dynamic_cast(fView); int32 tabNum = -1; if (tabView) tabNum = tabView->Selection(); RemoveChild(fView); delete fView; err = BMediaRoster::Roster()->GetParameterWebFor(fNode, &web); if ((err >= B_OK) && (web != NULL)) { fView = BMediaTheme::ViewFor(web); AddChild(fView); // Another tab view? Restore previous selection if (tabNum > 0) { BTabView *newTabView = dynamic_cast(fView); if (newTabView) newTabView->Select(tabNum); } } break; } default: BWindow::MessageReceived(message); } } //--------------------------------------------------------------- bool ControlWindow::QuitRequested() { be_app->PostMessage(msg_control_win); return true; }