From: John F. <jo...@us...> - 2012-06-13 07:40:42
|
Update of /cvsroot/ingex/ingex/studio/ace-tao/Ingexgui/src In directory vz-cvs-4.sog:/tmp/cvs-serv5376 Modified Files: controller.cpp controller.h Log Message: Fix occasional incorrect timecode missing display Index: controller.h =================================================================== RCS file: /cvsroot/ingex/ingex/studio/ace-tao/Ingexgui/src/controller.h,v retrieving revision 1.12 retrieving revision 1.13 diff -C2 -d -r1.12 -r1.13 *** controller.h 11 May 2011 08:54:09 -0000 1.12 --- controller.h 13 Jun 2012 07:40:40 -0000 1.13 *************** *** 99,102 **** --- 99,103 ---- wxDateTime mLastTimecodeRequest; ProdAuto::MxfTimecode mLastTimecodeReceived; + Controller::TimecodeState mPrevTimecodeState; //simple vbls accessed in both contexts - don't need protecting bool mRouterRecorder; *************** *** 153,158 **** void SetStrings(CORBA::StringSeq_var); void SetTimecode(ProdAuto::MxfTimecode_var); void SetTimecodeState(Controller::TimecodeState); - void SetTimecodeStateChanged(bool = true); void SetRecordTimeAvailable(long); const wxString GetName(); --- 154,159 ---- void SetStrings(CORBA::StringSeq_var); void SetTimecode(ProdAuto::MxfTimecode_var); + void SetPrevTimecodeState(Controller::TimecodeState); void SetTimecodeState(Controller::TimecodeState); void SetRecordTimeAvailable(long); const wxString GetName(); *************** *** 178,182 **** ProdAuto::MxfTimecode mTimecode; //deletes itself Controller::TimecodeState mTimecodeState; ! bool mTimecodeStateChanged; long mRecordTimeAvailable; }; --- 179,183 ---- ProdAuto::MxfTimecode mTimecode; //deletes itself Controller::TimecodeState mTimecodeState; ! Controller::TimecodeState mPrevTimecodeState; long mRecordTimeAvailable; }; Index: controller.cpp =================================================================== RCS file: /cvsroot/ingex/ingex/studio/ace-tao/Ingexgui/src/controller.cpp,v retrieving revision 1.21 retrieving revision 1.22 diff -C2 -d -r1.21 -r1.22 *** controller.cpp 10 Feb 2012 15:12:55 -0000 1.21 --- controller.cpp 13 Jun 2012 07:40:40 -0000 1.22 *************** *** 44,48 **** /// @param handler The handler where events will be sent. Controller::Controller(const wxString & name, Comms * comms, wxEvtHandler * handler) ! : wxThread(wxTHREAD_JOINABLE), mComms(comms), mTimecodeRunning(false), mReconnecting(false), mPendingCommand(NONE), mPendingCommandSent(false), mName(name), mPrevCommand(NONE), mOK(false) //making the thread joinable means that we can start the deletion process without waiting for it to end, which might take a long time if there is a CORBA command waiting for a response. Instead, we issue an event to signal when the thread has exited and hence the object can be deleted. { mCondition = new wxCondition(mMutex); --- 44,48 ---- /// @param handler The handler where events will be sent. Controller::Controller(const wxString & name, Comms * comms, wxEvtHandler * handler) ! : wxThread(wxTHREAD_JOINABLE), mComms(comms), mTimecodeRunning(false), mReconnecting(false), mPendingCommand(NONE), mPendingCommandSent(false), mPrevTimecodeState(ABSENT), mName(name), mPrevCommand(NONE), mOK(false) //making the thread joinable means that we can start the deletion process without waiting for it to end, which might take a long time if there is a CORBA command waiting for a response. Instead, we issue an event to signal when the thread has exited and hence the object can be deleted. { mCondition = new wxCondition(mMutex); *************** *** 379,382 **** --- 379,383 ---- event.SetName(mName); event.SetCommand(mCommand); + event.SetPrevTimecodeState(mPrevTimecodeState); mCommand = NONE; //can now detect if another command is issued while busy (more frequently during abnormal situations) mMutex.Unlock(); *************** *** 389,395 **** wxString msg; CORBA::StringSeq_var strings; //deletes itself ! ProdAuto::MxfTimecode timecode = InvalidMxfTimecode; //structure so deletes itself //send a recorder command, if any ! for (int i = 0; i < 2; i++) { //always good to try things twice with CORBA event.SetResult(SUCCESS); //default switch (event.GetCommand()) --- 390,396 ---- wxString msg; CORBA::StringSeq_var strings; //deletes itself ! ProdAuto::MxfTimecode timecode = InvalidMxfTimecode; //send a recorder command, if any ! for (int i = 0; i < 2; i++) { //always good to try things twice with CORBA: second iteration will happen if event result is set to COMM_FAILURE event.SetResult(SUCCESS); //default switch (event.GetCommand()) *************** *** 401,406 **** ProdAuto::TrackList_var trackList; bool routerRecorder = false; //initialisation prevents compiler warning - unsigned long recordTimeAvailable = -1; - event.SetTimecodeStateChanged(); //always trigger action mLastTimecodeReceived.undefined = true; //guarantee that a valid timecode will be assumed to be running timecode mMutex.Lock(); --- 402,405 ---- *************** *** 408,524 **** mMutex.Unlock(); msg = mComms->SelectRecorder(name, mRecorder); - if (msg.IsEmpty()) { //OK so far - try { - trackList = mRecorder->Tracks(); - maxPreroll = mRecorder->MaxPreRoll(); - maxPostroll = mRecorder->MaxPostRoll(); - event.SetTrackStatusList(mRecorder->TracksStatus()); - routerRecorder = wxString(mRecorder->RecordingFormat(), wxConvLibc).MakeUpper().Matches(wxT("*ROUTER*")); - strings = mRecorder->ProjectNames(); - } - catch (const CORBA::Exception & e) { - //std::cerr << "connect/reconnect exception: " << e._name() << std::endl; - msg = wxT("Error communicating with this recorder: ") + wxString(e._name(), wxConvLibc) + wxT(". Is it operational and connected to the network? The problem may resolve itself if you try again."); - } - } if (!msg.IsEmpty()) { //failed to select event.SetResult(COMM_FAILURE); } ! else { //OK so far ! try { ! recordTimeAvailable = mRecorder->RecordTimeAvailable(); } ! catch (const CORBA::Exception & e) { ! //do nothing - ignore old recorders that don't understand this command, and other errors are likely to have been detected by the previous calls } ! mMutex.Lock(); ! if (CONNECT == event.GetCommand()) { ! //various checks on the data we've acquired ! if (!trackList->length() || !event.GetNTracks()) { ! msg = wxT("This recorder has no tracks."); ! } ! else if (maxPreroll.undefined) { ! msg = wxT("This recorder has no maximum preroll."); ! } ! else if (!maxPreroll.edit_rate.numerator || !maxPreroll.edit_rate.denominator) { ! msg = wxT("This recorder has invalid maximum preroll."); //don't want divide by zero errors ! } ! else if (maxPostroll.undefined) { //quite likely as postroll isn't dependent on buffer length ! mMaxPostroll = maxPreroll; //for the edit rate values ! mMaxPostroll.undefined = false; ! mMaxPostroll.samples = DEFAULT_MAX_POSTROLL; ! } ! else if (!maxPostroll.edit_rate.numerator || !maxPostroll.edit_rate.denominator) { ! msg = wxT("This recorder has invalid maximum postroll."); //don't want divide by zero errors ! } ! else { ! mMaxPostroll = maxPostroll; ! } ! mTrackList = trackList; ! mMaxPreroll = maxPreroll; ! mSourceList.length(mTrackList->length()); ! mRouterRecorder = routerRecorder; } ! else { //reconnecting ! //check nothing's changed after reconnection ! if (maxPreroll.undefined ! || maxPreroll.edit_rate.numerator != mMaxPreroll.edit_rate.numerator ! || maxPreroll.edit_rate.denominator != mMaxPreroll.edit_rate.denominator ! || maxPreroll.samples != mMaxPreroll.samples) { ! msg = wxT("the maximum preroll has changed"); ! } ! else if ((maxPostroll.undefined && mMaxPostroll.samples != DEFAULT_MAX_POSTROLL) || ! (!maxPostroll.undefined && ! (maxPostroll.edit_rate.numerator != mMaxPostroll.edit_rate.numerator ! || maxPostroll.edit_rate.denominator != mMaxPostroll.edit_rate.denominator ! || maxPostroll.samples != mMaxPostroll.samples))) { ! msg = wxT("the maximum postroll has changed"); ! } ! else if (trackList->length() != mTrackList->length()) { ! msg = wxT("the number of tracks has changed"); ! } ! else if (mRouterRecorder && !routerRecorder) { ! msg = wxT("it is no longer a router recorder"); ! } ! else if (!mRouterRecorder && routerRecorder) { ! msg = wxT("it now presents itself as a router recorder"); ! } ! else { ! for (unsigned int i = 0; i < trackList->length(); i++) { ! if (strcmp(trackList[i].name, mTrackList[i].name)) { ! msg = wxT("name"); ! } ! else if (trackList[i].type != mTrackList[i].type) { ! msg = wxT("type"); ! } ! else if (trackList[i].id != mTrackList[i].id) { ! msg = wxT("ID"); ! } ! else if (trackList[i].has_source != mTrackList[i].has_source) { ! msg = wxT("\"has_source\" status"); ! } ! else if (trackList[i].has_source && strcmp(trackList[i].src.package_name, mTrackList[i].src.package_name)) { ! msg = wxT("package name"); ! } ! else if (trackList[i].has_source && strcmp(trackList[i].src.track_name, mTrackList[i].src.track_name)) { ! msg = wxT("track name"); ! } ! if (msg.Length()) { ! msg = wxT("track \"") + wxString(mTrackList[i].name, wxConvLibc) + wxT("\" has changed ") + msg; ! break; ! } } } } - mMutex.Unlock(); - } - if (msg.IsEmpty()) { - rc = ProdAuto::Recorder::SUCCESS; - event.SetRecordTimeAvailable(mRouterRecorder ? -1 : recordTimeAvailable); } ! else { rc = ProdAuto::Recorder::FAILURE; event.SetMessage(msg); event.SetTrackStatusList(0); //track status not valid } break; --- 407,521 ---- mMutex.Unlock(); msg = mComms->SelectRecorder(name, mRecorder); if (!msg.IsEmpty()) { //failed to select event.SetResult(COMM_FAILURE); + break; } ! try { ! trackList = mRecorder->Tracks(); ! maxPreroll = mRecorder->MaxPreRoll(); ! maxPostroll = mRecorder->MaxPostRoll(); ! event.SetTrackStatusList(mRecorder->TracksStatus()); ! routerRecorder = wxString(mRecorder->RecordingFormat(), wxConvLibc).MakeUpper().Matches(wxT("*ROUTER*")); ! strings = mRecorder->ProjectNames(); ! } ! catch (const CORBA::Exception & e) { ! //std::cerr << "connect/reconnect exception: " << e._name() << std::endl; ! msg = wxT("Error communicating with this recorder: ") + wxString(e._name(), wxConvLibc) + wxT(". Is it operational and connected to the network? The problem may resolve itself if you try again."); ! event.SetResult(COMM_FAILURE); ! break; ! } ! mMutex.Lock(); ! if (CONNECT == event.GetCommand()) { ! //various checks on the data we've acquired ! if (!trackList->length() || !event.GetNTracks()) { ! msg = wxT("This recorder has no tracks."); } ! else if (maxPreroll.undefined) { ! msg = wxT("This recorder has no maximum preroll."); } ! else if (!maxPreroll.edit_rate.numerator || !maxPreroll.edit_rate.denominator) { ! msg = wxT("This recorder has invalid maximum preroll."); //don't want divide by zero errors } ! else if (maxPostroll.undefined) { //quite likely as postroll isn't dependent on buffer length ! mMaxPostroll = maxPreroll; //for the edit rate values ! mMaxPostroll.undefined = false; ! mMaxPostroll.samples = DEFAULT_MAX_POSTROLL; ! } ! else if (!maxPostroll.edit_rate.numerator || !maxPostroll.edit_rate.denominator) { ! msg = wxT("This recorder has invalid maximum postroll."); //don't want divide by zero errors ! } ! else { ! mMaxPostroll = maxPostroll; ! } ! mTrackList = trackList; ! mMaxPreroll = maxPreroll; ! mSourceList.length(mTrackList->length()); ! mRouterRecorder = routerRecorder; ! } ! else { //reconnecting ! //check nothing's changed after reconnection ! if (maxPreroll.undefined ! || maxPreroll.edit_rate.numerator != mMaxPreroll.edit_rate.numerator ! || maxPreroll.edit_rate.denominator != mMaxPreroll.edit_rate.denominator ! || maxPreroll.samples != mMaxPreroll.samples) { ! msg = wxT("the maximum preroll has changed"); ! } ! else if ((maxPostroll.undefined && mMaxPostroll.samples != DEFAULT_MAX_POSTROLL) || ! (!maxPostroll.undefined && ! (maxPostroll.edit_rate.numerator != mMaxPostroll.edit_rate.numerator ! || maxPostroll.edit_rate.denominator != mMaxPostroll.edit_rate.denominator ! || maxPostroll.samples != mMaxPostroll.samples))) { ! msg = wxT("the maximum postroll has changed"); ! } ! else if (trackList->length() != mTrackList->length()) { ! msg = wxT("the number of tracks has changed"); ! } ! else if (mRouterRecorder && !routerRecorder) { ! msg = wxT("it is no longer a router recorder"); ! } ! else if (!mRouterRecorder && routerRecorder) { ! msg = wxT("it now presents itself as a router recorder"); ! } ! else { ! for (unsigned int i = 0; i < trackList->length(); i++) { ! if (strcmp(trackList[i].name, mTrackList[i].name)) { ! msg = wxT("name"); ! } ! else if (trackList[i].type != mTrackList[i].type) { ! msg = wxT("type"); ! } ! else if (trackList[i].id != mTrackList[i].id) { ! msg = wxT("ID"); ! } ! else if (trackList[i].has_source != mTrackList[i].has_source) { ! msg = wxT("\"has_source\" status"); ! } ! else if (trackList[i].has_source && strcmp(trackList[i].src.package_name, mTrackList[i].src.package_name)) { ! msg = wxT("package name"); ! } ! else if (trackList[i].has_source && strcmp(trackList[i].src.track_name, mTrackList[i].src.track_name)) { ! msg = wxT("track name"); ! } ! if (!msg.IsEmpty()) { ! msg = wxT("track \"") + wxString(mTrackList[i].name, wxConvLibc) + wxT("\" has changed ") + msg; ! break; } } } } ! mMutex.Unlock(); ! if (!msg.IsEmpty()) { rc = ProdAuto::Recorder::FAILURE; event.SetMessage(msg); event.SetTrackStatusList(0); //track status not valid + break; + } + if (!mRouterRecorder) { + try { + event.SetRecordTimeAvailable(mRecorder->RecordTimeAvailable()); + } + catch (const CORBA::Exception & e) { + //do nothing - ignore old recorders that don't understand this command, and other errors are likely to have been detected by the previous calls + } } break; *************** *** 555,559 **** break; } ! case REC_TIME_AVAILABLE: { //already checked that this isn't a router recorder //std::cerr << "thread REC_TIME_AVAILABLE" << std::endl; long recordTimeAvailable = -1; --- 552,556 ---- break; } ! case REC_TIME_AVAILABLE: { //already checked in main thread that this isn't a router recorder //std::cerr << "thread REC_TIME_AVAILABLE" << std::endl; long recordTimeAvailable = -1; *************** *** 622,626 **** event.SetResult(COMM_FAILURE); } - event.SetTimecodeStateChanged(); //so that a timecode that was stuck during the recording will be reported as such break; } --- 619,622 ---- *************** *** 631,635 **** if (ProdAuto::Recorder::SUCCESS == rc) { event.SetStrings(strings); //only relevant for STOP (list of files), and CONNECT or GET_PROJECT_NAMES (list of project names) ! if (!timecode.edit_rate.numerator || !timecode.edit_rate.denominator) { timecode.undefined = true; } --- 627,631 ---- if (ProdAuto::Recorder::SUCCESS == rc) { event.SetStrings(strings); //only relevant for STOP (list of files), and CONNECT or GET_PROJECT_NAMES (list of project names) ! if (!timecode.edit_rate.numerator || !timecode.edit_rate.denominator) { //sanity check timecode.undefined = true; } *************** *** 643,703 **** } event.SetTrackList(mTrackList); ! //get status ! if (COMM_FAILURE != event.GetResult()) { for (int j = 0; j < 2; j++) { //always good to try things twice with CORBA try { ! if (CONNECT != event.GetCommand() && RECONNECT != event.GetCommand()) { //haven't already got track status list ! event.SetTrackStatusList(mRecorder->TracksStatus()); ! } ! //timecode situation ! if (!event.GetNTracks() || event.GetTrackStatusList()->operator[](0).timecode.undefined || !event.GetTrackStatusList()->operator[](0).timecode.edit_rate.numerator || !event.GetTrackStatusList()->operator[](0).timecode.edit_rate.denominator) { //no or invalid timecode ! if (!mLastTimecodeReceived.undefined) { //newly in this state ! mLastTimecodeReceived.undefined = true; //to allow future detection of state change ! event.SetTimecodeStateChanged(); ! //ABSENT is the default timecode state in the event ! } ! } ! else { //timecode value is OK ! ProdAuto::MxfTimecode timecode = event.GetTrackStatusList()->operator[](0).timecode; ! if (mLastTimecodeReceived.undefined) { //timecode has just appeared ! event.SetTimecodeState(UNCONFIRMED); ! if (!mTimecodeRunning) { //just started ! mTimecodeRunning = true; //to allow future detection of state change ! event.SetTimecodeStateChanged(); ! } ! } ! else if (!wxDateTime::Now().IsEqualUpTo(mLastTimecodeRequest, wxTimeSpan::Milliseconds(100))) { //long enough since the last stored value was received to assume that the timecode has changed ! if (timecode.samples != mLastTimecodeReceived.samples) { //timecode is running ! event.SetTimecodeState(RUNNING); ! if (!mTimecodeRunning) { //just started ! mTimecodeRunning = true; //to allow future detection of state change ! event.SetTimecodeStateChanged(); ! } ! } ! else { //timecode is stuck ! event.SetTimecodeState(STUCK); ! if (mTimecodeRunning) { //just stopped ! mTimecodeRunning = false; //to allow future detection of state change ! event.SetTimecodeStateChanged(); ! } ! } ! } ! else { ! //repeat previous status ! event.SetTimecodeState(mTimecodeRunning ? UNCONFIRMED : STUCK); ! } ! mLastTimecodeReceived = timecode; ! mLastTimecodeRequest = wxDateTime::Now(); //now or sometime before! ! } ! break; //successful: no need to try again } catch (const CORBA::Exception & e) { //std::cerr << "status exception: " << e._name() << std::endl; event.SetResult(COMM_FAILURE); ! //indicated by list size being zero } } } //communicate the results AddPendingEvent(event); mMutex.Lock(); --- 639,681 ---- } event.SetTrackList(mTrackList); ! //get track status list if we don't already have it ! if (COMM_FAILURE != event.GetResult() && !event.GetNTracks()) { for (int j = 0; j < 2; j++) { //always good to try things twice with CORBA + event.SetResult(SUCCESS); try { ! event.SetTrackStatusList(mRecorder->TracksStatus()); } catch (const CORBA::Exception & e) { //std::cerr << "status exception: " << e._name() << std::endl; event.SetResult(COMM_FAILURE); ! continue; //try once more } + break; } } + //timecode + timecode = InvalidMxfTimecode; + if (event.GetNTracks() && !event.GetTrackStatusList()->operator[](0).timecode.undefined && event.GetTrackStatusList()->operator[](0).timecode.edit_rate.numerator && event.GetTrackStatusList()->operator[](0).timecode.edit_rate.denominator) { //valid timecode + timecode = event.GetTrackStatusList()->operator[](0).timecode; + if (mLastTimecodeReceived.undefined) { //timecode has just appeared + event.SetTimecodeState(UNCONFIRMED); + } + else if (!wxDateTime::Now().IsEqualUpTo(mLastTimecodeRequest, wxTimeSpan::Milliseconds(100))) { //long enough since the last stored value was received to assume that the timecode has changed + if (timecode.samples != mLastTimecodeReceived.samples) { //timecode is running + event.SetTimecodeState(RUNNING); + } + else { //timecode is stuck + event.SetTimecodeState(STUCK); + } + } + else { + //repeat previous status + event.SetTimecodeState(mPrevTimecodeState); + } + mLastTimecodeRequest = wxDateTime::Now(); //now or sometime before! + } + mLastTimecodeReceived = timecode; //communicate the results + mPrevTimecodeState = event.GetTimecodeState(); AddPendingEvent(event); mMutex.Lock(); *************** *** 708,716 **** ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ! ControllerThreadEvent::ControllerThreadEvent() : mTrackStatusList(0), mTimecodeState(Controller::ABSENT), mTimecodeStateChanged(false) { } ! ControllerThreadEvent::ControllerThreadEvent(const wxEventType & type) : wxNotifyEvent(type), mTrackStatusList(0), mTimecodeState(Controller::ABSENT), mTimecodeStateChanged(false) { } --- 686,694 ---- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ! ControllerThreadEvent::ControllerThreadEvent() : mTrackStatusList(0), mTimecodeState(Controller::ABSENT), mPrevTimecodeState(Controller::ABSENT), mRecordTimeAvailable(-1) { } ! ControllerThreadEvent::ControllerThreadEvent(const wxEventType & type) : wxNotifyEvent(type), mTrackStatusList(0), mTimecodeState(Controller::ABSENT), mPrevTimecodeState(Controller::ABSENT), mRecordTimeAvailable(-1) { } *************** *** 770,781 **** } ! void ControllerThreadEvent::SetTimecodeState(Controller::TimecodeState state) { ! mTimecodeState = state; } ! void ControllerThreadEvent::SetTimecodeStateChanged(bool changed) { ! mTimecodeStateChanged = changed; } --- 748,759 ---- } ! void ControllerThreadEvent::SetPrevTimecodeState(Controller::TimecodeState state) { ! mPrevTimecodeState = state; } ! void ControllerThreadEvent::SetTimecodeState(Controller::TimecodeState state) { ! mTimecodeState = state; } *************** *** 831,835 **** bool ControllerThreadEvent::TimecodeStateHasChanged() { ! return mTimecodeStateChanged; } --- 809,813 ---- bool ControllerThreadEvent::TimecodeStateHasChanged() { ! return mTimecodeState != mPrevTimecodeState; } |