source: trunk/Obi/Obi/ProjectView/TransportBar.cs @ 7626

Revision 7626, 253.9 KB checked in by rohit_tandon, 7 months ago (diff)

-> Now comments can be added properly when Recorder is active.

Line 
1using System;
2using System.Collections.Generic;
3using System.Windows.Forms;
4using System.Threading;
5using urakawa.core;
6using urakawa.command;
7using urakawa.media.timing;
8using System.Drawing;
9using System.Resources;
10
11
12namespace Obi.ProjectView
13{
14    /// <summary>
15    /// The transport bar: transport buttons, scrubbing slide, time display, text vu meter display.
16    /// </summary>
17    public partial class TransportBar : UserControl
18    {
19        private ProjectView mView;                   // the parent project view
20        private bool m_IsProjectEmpty; // is true if project has no sections
21
22        private AudioLib.AudioPlayer mPlayer;           // the audio player
23        private AudioLib.AudioRecorder mRecorder;       // the audio recorder
24        private AudioLib.VuMeter mVuMeter;              // VU meter
25        //private bool m_AutoSaveOnNextRecordingEnd ; //flag to auto save whenever recording stops or pauses next time//@singleSection:commented
26
27        private RecordingSession mRecordingSession;  // current recording session
28        private SectionNode mRecordingSection;       // Section in which we are recording
29        private PhraseNode mResumeRecordingPhrase;   // last phrase recorded (?)
30        private PhraseNode mRecordingPhrase;         // Phrase which we are recording in (after start, before end)
31        private int mRecordingInitPhraseIndex;       // Phrase child in which we are recording
32       
33        private State mState;                        // transport bar state (composite of player/recorder states)
34        private bool m_CanMoveSelectionToPlaybackPhrase = true;//@singleSection
35        private List<string> m_RecordingElapsedRemainingList = new List<string>();
36        private List<string> m_PlayingElapsedRemainingList = new List<string>();
37        // Playlists
38        private Playlist mCurrentPlaylist;           // playlist currently playing, null when not playing
39        private Playlist mMasterPlaylist;            // master playlist (all phrases in the project)
40        private Playlist mQAMasterPlaylist;          // QA master playlist (all used phrases in the project)
41        private Playlist mLocalPlaylist;             // local playlist (only selected; may be null) TO BE REMOVED
42        private bool m_IsPlaySectionInspiteOfPhraseSelection = false;
43        private bool m_MonitorContinuously = false;
44        private string[] m_filePaths;
45        private ToolStripMenuItem m_CurrentCheckedProfile;
46        private Dictionary<string, ToolStripMenuItem> m_ListOfSwitchProfiles = new Dictionary<string, ToolStripMenuItem>();
47        private bool m_PreviewBeforeRecordingActive = false;
48        private bool m_IsElapsedInProjectSelectedBeforeStop = false; 
49        //public variables
50        //private bool IsPreviewBeforeRec = false;
51
52        Bitmap m_monitorButtonImage;
53        Bitmap m_recordButtonImage;
54        Bitmap m_recordOptionsButtonImage;
55
56        #region CAN WE REMOVE THIS?
57
58        private bool mPlayQAPlaylist = false; // this should be set from UI
59        private bool mSelectionChangedPlayEnable; // flag for enabling / disabling playback on change of selection
60        private Mutex m_PlayOnSelectionChangedMutex ;
61
62        private string mPrevSectionAccessibleName;   // Normal accessible name for the previous section button ???
63        private string mStopButtonAccessibleName;    // Normal accessible name for the stop button ???
64        private KeyboardShortcuts_Settings keyboardShortcuts=null;
65        private double m_ElapseBackInterval;
66        private double m_CursorTime=0.0;
67        private double m_TotalCursorTime; // used for Total Cursor time to Update Time desplay during stop stage
68
69        //private ContextMenuStrip m_RecordingOptionsContextMenuStrip;
70        //private ToolStripMenuItem m_MoniteringtoolStripMenuItem;
71        //private ToolStripMenuItem m_DeletePhrasestoolStripMenuItem;
72        //private Button m_btnRecordingOptions;
73
74
75        // Set the accessible name of previous section/stop buttons (???)
76        private void AddTransportBarAccessibleName()
77        {
78            mPrevSectionAccessibleName = mPrevSectionButton.AccessibleName;
79            mStopButtonAccessibleName = mStopButton.AccessibleName;
80            mPrevSectionButton.AccessibleName = string.Format("{0} {1}", Localizer.Message("transport_bar"), mPrevSectionAccessibleName);
81            mStopButton.AccessibleName = string.Format("{0} {1}", Localizer.Message("transport_bar"), mStopButtonAccessibleName);
82        }
83
84
85        private void TransportBar_Leave(object sender, EventArgs e)
86        {
87            mPrevSectionButton.AccessibleName = string.Format("{0} {1}", Localizer.Message("transport_bar"), mPrevSectionAccessibleName);
88            mStopButton.AccessibleName = string.Format("{0} {1}", Localizer.Message("transport_bar"), mStopButtonAccessibleName);
89        }
90
91
92        private void TransportBar_Enter(object sender, EventArgs e)
93        {
94            mPrevSectionButton.AccessibleName = string.Format("{0} {1}", Localizer.Message("transport_bar"), mPrevSectionAccessibleName);
95            mStopButton.AccessibleName = string.Format("{0} {1}", Localizer.Message("transport_bar"), mStopButtonAccessibleName);
96            Thread TrimAccessibleName = new Thread(new ThreadStart(TrimTransportBarAccessibleLabel));
97            TrimAccessibleName.Start();
98        }
99
100        private void TrimTransportBarAccessibleLabel()
101        {
102            Thread.Sleep(750);
103            mPrevSectionButton.AccessibleName = mPrevSectionAccessibleName;
104            mStopButton.AccessibleName = mStopButtonAccessibleName;
105        }
106
107        public bool SelectionChangedPlaybackEnabled
108        {
109            get { return mSelectionChangedPlayEnable; }
110            set { mSelectionChangedPlayEnable = value; }
111        }
112
113        #endregion
114
115
116        // Constants from the display combo box
117        private static readonly int ELAPSED_INDEX = 0;
118        private static readonly int ELAPSED_SECTION = 1;
119       // private static readonly int ELAPSED_SELECTION = 2;
120        private static int ELAPSED_TOTAL_INDEX = 2;
121        private static int ELAPSED_TOTAL_RECORDING_INDEX = 2;
122       // private static int REMAINING_IN_SECTION = 4;
123        private static readonly int REMAIN_INDEX = 3;
124        private readonly List<string> m_DisplayComboBoxItems;
125
126
127        // Pass the state change and playback rate change events from the playlist
128        public event AudioLib.AudioPlayer.StateChangedHandler StateChanged;
129        public event EventHandler PlaybackRateChanged;
130
131
132        // States of the transport bar:
133        // * Monitoring: recording is paused;
134        // * Paused: playback is paused;
135        // * Playing: playback is in progress;
136        // * Recording: recording is in progress;
137        // * Stopped: stopped.
138        public enum State { Monitoring, Paused, Playing, Recording, Stopped };
139
140
141        /// <summary>
142        /// Initialize the transport bar.
143        /// </summary>
144        public TransportBar()
145        {
146            InitializeComponent();
147            mView = null;
148            InitAudio();
149            InitPlaylists();
150            m_RecordingElapsedRemainingList.Add(Localizer.Message("Elapsed"));
151            m_RecordingElapsedRemainingList.Add(Localizer.Message("ElapsedInSection"));
152            m_RecordingElapsedRemainingList.Add(Localizer.Message("ElapsedInProject"));
153            m_PlayingElapsedRemainingList.Add(Localizer.Message("ElapsedInPhrase"));
154            m_PlayingElapsedRemainingList.Add(Localizer.Message("ElapsedInSection"));
155            m_PlayingElapsedRemainingList.Add(Localizer.Message("ElapsedInProject"));
156            m_PlayingElapsedRemainingList.Add(Localizer.Message("RemainingInPhrase"));
157          // m_PlayingElapsedRemainingList.Add("remaining in section");
158            m_PlayingElapsedRemainingList.Add(Localizer.Message("RemainingInSelection"));
159            mDisplayBox.Items.AddRange(m_PlayingElapsedRemainingList.ToArray ());
160            mDisplayBox.SelectedIndex = 0 ;
161            mTimeDisplayBox.AccessibleName = mDisplayBox.SelectedItem.ToString();
162            mFastPlayRateCombobox.SelectedIndex = 0;
163            mState = State.Stopped;
164            mSelectionChangedPlayEnable = true;
165            AddTransportBarAccessibleName();
166            m_PlayOnSelectionChangedMutex = new Mutex ();
167            m_DisplayComboBoxItems = new List<string>();
168            for (int i = 0; i < mDisplayBox.Items.Count; i++) m_DisplayComboBoxItems.Add(mDisplayBox.Items[i].ToString());
169           
170            ResourceManager resourceManager = new ResourceManager("Obi.ProjectView.TransportBar", GetType().Assembly);
171            m_monitorButtonImage = (Bitmap)resourceManager.GetObject("media-monitor.png");
172            m_recordButtonImage = (Bitmap)resourceManager.GetObject("mRecordButton.Image");
173            InitializeSwitchProfiles(); 
174
175         
176        }
177
178        /// <summary>
179        /// Get the audio player used by the transport bar.
180        /// </summary>
181        public AudioLib.AudioPlayer AudioPlayer { get { return mPlayer; } }
182
183        public bool CanFastForward { get { return Enabled && (IsPlayerActive || CanPlay) ; } }
184        public bool CanMarkCustomClass { get { return Enabled && mView.CanMarkPhrase; } }
185       
186        public bool CanPause { get { return Enabled && (mState == State.Playing || mState == State.Recording) ; } }
187        public bool CanPausePlayback { get { return Enabled && mState == State.Playing; } }
188        public bool CanPlay { get { return Enabled && mState == State.Stopped && !m_IsProjectEmpty && !mView.IsContentViewScrollActive; } }
189        public bool CanRecord { get { return Enabled &&( mState == State.Stopped || mState == State.Paused ||  mState == State.Monitoring 
190            ||  (mView.ObiForm.Settings.Audio_UseRecordBtnToRecordOverSubsequentAudio&& CurrentState == State.Playing && mCurrentPlaylist.PlaybackRate == 0)) 
191            &&  mView.IsPhraseCountWithinLimit && !mView.IsContentViewScrollActive && !mView.IsZoomWaveformActive; } } // @phraseLimit
192        public bool CanResumePlayback { get { return Enabled && mState == State.Paused   &&   !mView.IsContentViewScrollActive; } }
193        public bool CanResumeRecording { get { return Enabled && mResumeRecordingPhrase != null && mResumeRecordingPhrase.IsRooted    &&   (mState != State.Playing  ||   (mView.ObiForm.Settings.Audio_UseRecordBtnToRecordOverSubsequentAudio && CurrentState == State.Playing) )&& !mView.IsContentViewScrollActive && !mView.IsZoomWaveformActive; } }
194        public bool CanRewind { get { return Enabled && (IsPlayerActive || CanPlay) ; } }
195        public bool CanStop { get { return Enabled && (mState != State.Stopped || mView.Selection != null); } }
196
197
198        public bool CanNavigatePrevPhrase
199        {
200            get
201            {
202                return (!m_IsProjectEmpty && IsPlayerActive && mCurrentPlaylist.CanNavigatePrevPhrase && !IsRecorderActive) || CanPlay ;
203            }
204        }
205
206        public bool CanNavigateNextPhrase
207        {
208            get
209            {
210                return IsRecorderActive ||
211                    (mCurrentPlaylist != null && mCurrentPlaylist.CanNavigateNextPhrase) ;
212            }
213        }
214
215       
216       
217        public bool CanNavigatePrevPage
218        { 
219            get 
220            { return Enabled && !m_IsProjectEmpty && (mCurrentPlaylist != null && mCurrentPlaylist.CanNavigatePrevPage) && !IsRecorderActive; } 
221        }
222        public bool CanNavigateNextPage
223        {
224            get
225            {
226                return IsRecorderActive ||
227                   (mCurrentPlaylist != null && mCurrentPlaylist.CanNavigateNextPage) ;
228            }
229        }
230
231        public bool CanNavigatePrevSection { get { return Enabled && !m_IsProjectEmpty && (mCurrentPlaylist != null && mCurrentPlaylist.CanNavigatePrevSection) && !IsRecorderActive; } }
232
233        public bool CanNavigateNextSection
234        {
235            get
236            {
237                return IsRecorderActive ||
238                    (mCurrentPlaylist != null &&  mCurrentPlaylist.CanNavigateNextSection) ;
239            }
240        }
241
242        public bool CanEnterFineNavigationMode { get { return mView.Selection != null && mView.Selection.Node is PhraseNode && (IsPlayerActive || mView.Selection is AudioSelection) && !IsRecorderActive; } }
243
244        public bool CanPreview
245        {
246            get
247            {
248                return Enabled && (IsPlayerActive
249                    || (mView.Selection != null && mView.Selection is AudioSelection
250                    && !IsRecorderActive));
251            }
252        }
253       
254        public bool CanPreviewAudioSelection
255        {
256            get
257            {
258                return Enabled && mView.Selection != null &&  mView.Selection is AudioSelection
259                    && ((AudioSelection)mView.Selection).AudioRange != null && !((AudioSelection)mView.Selection).AudioRange.HasCursor && !IsRecorderActive;
260            }
261        }
262       
263        /// <summary>
264        /// A phrase can be split if there is an audio selection, or when audio is playing or paused.
265        /// </summary>
266        public bool CanSplitPhrase { get { return (IsPlayerActive
267            || ( mView.Selection != null  &&   mView.Selection is AudioSelection   &&   ((AudioSelection)mView.Selection).AudioRange != null))   
268            &&    IsPhraseCountWithinLimit; } } // @phraseLimit
269
270        //@singleSection
271        public bool CanMoveSelectionToPlaybackPhrase
272            {
273            get { return m_CanMoveSelectionToPlaybackPhrase; }
274            set { m_CanMoveSelectionToPlaybackPhrase = value; }
275        }
276
277        // @phraseLimit
278        /// <summary>
279        ///  Returns true if phrase count of  selected section is below below max visible phrase blocks count
280        /// it also consider active node w.r.t. recording / playback instead of selection if recording or playback is active
281                /// </summary>
282        public bool IsPhraseCountWithinLimit
283            {
284            get
285                {
286                if (IsRecorderActive && mRecordingSection != null && mRecordingSection.PhraseChildCount < mView.MaxVisibleBlocksCount)
287                    return true;
288                else if (IsPlayerActive && mCurrentPlaylist.CurrentPhrase != null && mCurrentPlaylist.CurrentPhrase.IsRooted  && mCurrentPlaylist.CurrentPhrase.ParentAs<SectionNode>().PhraseChildCount < mView.MaxVisibleBlocksCount)
289                    return true;
290                else
291                    return mView.IsPhraseCountWithinLimit;
292                }
293            }
294
295        //@deleterecording
296        public bool CanRecordOnFollowingAudio
297        {
298            get { return mView.ObiForm.Settings.Audio_RevertOverwriteBehaviourForRecordOnSelection || (mView.Selection == null || !(mView.Selection is AudioSelection) || ((AudioSelection)mView.Selection).AudioRange.HasCursor); }
299        }
300
301        public double ElapsedTimeInSection
302        {
303            get 
304            {
305                PhraseNode phrNode = mCurrentPlaylist.CurrentPhrase;
306                ObiNode nodeSel = phrNode.ParentAs<SectionNode>();
307                double time = 0;
308                for (int i = 0; i < nodeSel.PhraseChildCount; i++)
309                {
310                    if (nodeSel.PhraseChild(i) != mCurrentPlaylist.CurrentPhrase && nodeSel.PhraseChild(i) is PhraseNode)
311                        time = nodeSel.PhraseChild(i).Duration + time;
312                    else
313                        break;                   
314                }
315                return time + mCurrentPlaylist.CurrentTimeInAsset;
316            }
317        }
318
319        public double RemainingTimeInSection
320        {
321            get { return mCurrentPlaylist.CurrentSection.Duration - ElapsedTimeInSection;  }
322        }
323
324        /// <summary>
325        /// Set color settings for the transport bar.
326        /// </summary>
327        public ColorSettings ColorSettings
328        {
329            set
330            {
331                if (value != null)
332                {
333                    BackColor = value.TransportBarBackColor;
334                    mTransportBarTooltip.ForeColor = value.ToolTipForeColor;
335                    mTimeDisplayBox.BackColor = value.TransportBarLabelBackColor;
336                    mTimeDisplayBox.ForeColor = value.TransportBarLabelForeColor;
337                }
338            }
339        }
340
341        /// <summary>
342        /// Get the phrase currently playing (or paused) if playback is active; null otherwise.
343        /// </summary>
344        public PhraseNode PlaybackPhrase
345        {
346            get { return IsPlayerActive ? mCurrentPlaylist.CurrentPhrase : null; }
347        }
348
349        /// <summary>
350        /// Split time is either the current playback position, or when stopped, the selection position.
351        /// Will return 0.0 in case something goes wrong (which may be the actual split time, but we don't
352        /// want to split then anyway do we?)
353        /// </summary>
354        public double SplitBeginTime
355        {
356            get
357            {
358                if (IsPlayerActive && mCurrentPlaylist is PreviewPlaylist && !(mView.Selection is AudioSelection)) return ((PreviewPlaylist)mCurrentPlaylist).RevertTime;
359                return IsPlayerActive
360                    && !(mView.Selection is AudioSelection && (((AudioSelection)mView.Selection).AudioRange != null   && !((AudioSelection)mView.Selection).AudioRange.HasCursor) ) ?
361                    mCurrentPlaylist.CurrentTimeInAsset :
362                    mView.Selection is AudioSelection && ((AudioSelection)mView.Selection).AudioRange  != null?
363                        ((AudioSelection)mView.Selection).AudioRange.HasCursor ?
364                            ((AudioSelection)mView.Selection).AudioRange.CursorTime :
365                            ((AudioSelection)mView.Selection).AudioRange.SelectionBeginTime :
366                        0.0;
367            }
368        }
369
370        /// <summary>
371        /// Get the end time for splitting; this is only valid for audio selections when playback is not
372        /// underway. In all other cases return 0.0.
373        /// </summary>
374        public double SplitEndTime
375        {
376            get
377            {
378                return mPlayer.CurrentState != AudioLib.AudioPlayer.State.Playing &&
379                    mView.Selection is AudioSelection && ((AudioSelection)mView.Selection).AudioRange != null
380                    && !((AudioSelection)mView.Selection).AudioRange.HasCursor ?
381                    ((AudioSelection)mView.Selection).AudioRange.SelectionEndTime : 0.0;
382            }
383        }
384                   
385        /// <summary>
386        /// Get the current playlist.
387        /// </summary>
388        public Playlist CurrentPlaylist { get { return mCurrentPlaylist; } }
389
390        /// <summary>
391        /// Get the current composite state of the transport bar.
392        /// </summary>
393        public State CurrentState { get { return mState; } }
394
395        /// <summary>
396        /// The transport bar as a whole can be enabled/disabled when necessary.
397        /// Disabling the transport bar will also stop playback.
398        /// </summary>
399        public new bool Enabled
400        {
401            get { return base.Enabled; }
402            set
403            {
404                if (base.Enabled && !value && IsActive)
405                {
406                    if (MonitorContinuously) MonitorContinuously = false; //@MonitorContinuously
407                    Stop();
408                }
409                base.Enabled = value;
410            }
411        }
412
413        /// <summary>
414        /// Enable/disable tooltips.
415        /// </summary>
416        public bool EnableTooltips { set { mTransportBarTooltip.Active = value; } }
417
418        /// <summary>
419        /// The local playlist allows to only play a selection.
420        /// </summary>
421        public Playlist LocalPlaylist
422        {
423            get { return mLocalPlaylist; }
424            set
425            {
426                mLocalPlaylist = value;
427                if (value != null) SetPlaylistEvents(mLocalPlaylist);
428            }
429        }
430
431        /// <summary>
432        /// Mark the begin time/cursor of a selection.
433        /// </summary>
434        public bool MarkSelectionBeginTime()
435        {
436            if (mPlayer.CurrentState == AudioLib.AudioPlayer.State.Playing
437                || mPlayer.CurrentState == AudioLib.AudioPlayer.State.Paused)
438            {
439                mView.SelectedBlockNode = mCurrentPlaylist.CurrentPhrase;
440                mView.Selection = new AudioSelection((PhraseNode)mView.Selection.Node, mView.Selection.Control,
441                    new AudioRange(mCurrentPlaylist.CurrentTimeInAsset));
442
443                                PlayAudioClue (AudioCluesSelection.SelectionBegin ) ;
444                return true;
445            }
446            return false;
447        }
448
449        /// <summary>
450        /// Mark the end time of a selection. If no begin time is set, add a cursor/begin time.
451        /// If a selection is already set, make a new selection from the beginning of said
452        /// selection and the current cursor position.
453        /// </summary>
454        public bool MarkSelectionEndTime()
455        {
456            if (mPlayer.CurrentState == AudioLib.AudioPlayer.State.Playing
457                || mPlayer.CurrentState == AudioLib.AudioPlayer.State.Paused)
458            {
459                            AudioSelection selection = mView.Selection as AudioSelection;
460                double begin = 0.0;
461                double end = 0.0;
462                if (selection != null && selection.Node == mCurrentPlaylist.CurrentPhrase)
463                {
464                    double now = mCurrentPlaylist.CurrentTimeInAsset;
465                    double cursor = selection.AudioRange.HasCursor ? selection.AudioRange.CursorTime :
466                        selection.AudioRange.SelectionBeginTime;
467                    begin = cursor < now ? cursor : now;
468                    end = cursor > now ? cursor : now;
469                }
470                if (begin != end)
471                {
472                                                    mView.Selection = new AudioSelection((PhraseNode)selection.Node, selection.Control, new AudioRange(begin, end));
473                   
474                    PlayAudioClue ( AudioCluesSelection.SelectionEnd) ;
475                                        return true;
476                }
477                else
478                {
479                    // If nothing was set, behave as if we started a selection.
480                    return MarkSelectionBeginTime();
481                }
482            }
483            return false;
484        }
485
486        /// <summary>
487        /// Mark a selection from the beginning of the waveform to the current cursor position.
488        /// </summary>
489        public bool MarkSelectionFromBeginningToTheCursor()
490        {
491            if ((mPlayer.CurrentState == AudioLib.AudioPlayer.State.Playing
492                || mPlayer.CurrentState == AudioLib.AudioPlayer.State.Paused) &&
493                mCurrentPlaylist.CurrentTimeInAsset > 0.0)
494            {
495                mView.SelectedBlockNode = mCurrentPlaylist.CurrentPhrase;
496                mView.Selection = new AudioSelection((PhraseNode)mView.Selection.Node, mView.Selection.Control,
497                    new AudioRange(0.0, mCurrentPlaylist.CurrentTimeInAsset));
498                return true;
499            }
500            else if (CurrentState == State.Stopped && mView.Selection != null && mView.Selection is AudioSelection && ((AudioSelection)mView.Selection).AudioRange.HasCursor)
501            {
502                double time = ((AudioSelection)mView.Selection).AudioRange.CursorTime;
503                mView.Selection = new AudioSelection((PhraseNode)mView.Selection.Node, mView.Selection.Control,
504                    new AudioRange(0.0, time));
505                return true;
506            }
507            return false;
508        }
509
510        /// <summary>
511        /// Mark a selection from the current cursor position to the end of the cursor.
512        /// </summary>
513        public bool MarkSelectionFromCursorToTheEnd()
514        {
515            if ((mPlayer.CurrentState == AudioLib.AudioPlayer.State.Playing
516                || mPlayer.CurrentState == AudioLib.AudioPlayer.State.Paused) &&
517                mCurrentPlaylist.CurrentTimeInAsset < mCurrentPlaylist.CurrentPhrase.Audio.Duration.AsMilliseconds)
518            {
519                mView.SelectedBlockNode = mCurrentPlaylist.CurrentPhrase;
520                mView.Selection = new AudioSelection((PhraseNode)mView.Selection.Node, mView.Selection.Control,
521                    new AudioRange(mCurrentPlaylist.CurrentTimeInAsset,
522                        mCurrentPlaylist.CurrentPhrase.Audio.Duration.AsMilliseconds));
523                return true;
524            }
525            else if (CurrentState == State.Stopped && mView.Selection != null && mView.Selection is AudioSelection && ((AudioSelection)mView.Selection).AudioRange.HasCursor)
526            {   
527                double time = ((AudioSelection)mView.Selection).AudioRange.CursorTime;
528                mView.Selection = new AudioSelection((PhraseNode)mView.Selection.Node, mView.Selection.Control,
529                    new AudioRange(time ,
530                        ((PhraseNode)mView.Selection.Node).Audio.Duration.AsMilliseconds));
531                return true;
532            }
533            return false;
534        }
535
536        /// <summary>
537        /// Mark a selection for the whole phrase.
538        /// </summary>
539        public bool MarkSelectionWholePhrase()
540        {
541            if (mPlayer.CurrentState == AudioLib.AudioPlayer.State.Playing
542                || mPlayer.CurrentState == AudioLib.AudioPlayer.State.Paused)
543            {
544                mView.SelectedBlockNode = mCurrentPlaylist.CurrentPhrase;
545                mView.Selection = new AudioSelection((PhraseNode)mView.Selection.Node, mView.Selection.Control,
546                    new AudioRange(0.0, mCurrentPlaylist.CurrentPhrase.Audio.Duration.AsMilliseconds));
547                return true;
548            }
549            else if (mState == State.Stopped && mView.Selection != null && mView.Selection.Node is PhraseNode)
550            {
551                mView.Selection = new AudioSelection((PhraseNode)mView.Selection.Node, mView.Selection.Control,
552                    new AudioRange(0.0, ((PhraseNode)mView.Selection.Node).Audio.Duration.AsMilliseconds));
553                return true;
554            }
555            return false;
556        }
557
558        /// <summary>
559        /// Get the master playlist (automatically maintained.)
560        /// </summary>
561        public Playlist MasterPlaylist { get { return mMasterPlaylist; } }
562
563        /// <summary>
564        /// The presentation in the project view has changed, so update playlists and event handlers accordingly.
565        /// </summary>
566        public void NewPresentation()
567        {
568            mMasterPlaylist.Presentation = mView.Presentation;
569            mCurrentPlaylist = mMasterPlaylist;
570            mResumeRecordingPhrase = null;
571            mView.Presentation.Changed += new EventHandler<urakawa.events.DataModelChangedEventArgs>(Presentation_Changed);
572            mView.Presentation.UsedStatusChanged += new NodeEventHandler<ObiNode>(Presentation_UsedStatusChanged);
573            m_IsProjectEmpty = mView.Presentation.FirstSection == null;
574
575            //m_AutoSaveOnNextRecordingEnd = false;
576            UpdateButtons();
577            if (mView.ObiForm.Settings != null)
578            {
579                m_PlayerTimeComboIndex = mView.ObiForm.Settings.TransportBarCounterIndex;
580                m_RecorderTimeComboIndex = mView.ObiForm.Settings.TransportBarCounterIndex;
581                mDisplayBox.SelectedIndex = mView.ObiForm.Settings.TransportBarCounterIndex < mDisplayBox.Items.Count ? mView.ObiForm.Settings.TransportBarCounterIndex : 0;
582                ResetFastPlayForPreferencesChange();
583            }
584        }
585
586        /// <summary>
587        /// If true, play all when there is no selection; otherwise, play nothing.
588        /// </summary>
589        public bool PlayIfNoSelection { get { return mView.ObiForm.Settings.PlayIfNoSelection; } }
590        /*/// <summary>//@singleSection: commented
591        /// Auto save whenever recording pauses or stops next
592        ///</summary>
593        public bool AutoSaveOnNextRecordingEnd
594            { get { return m_AutoSaveOnNextRecordingEnd; }
595            set { m_AutoSaveOnNextRecordingEnd = value; }
596            }
597        */
598        /// <summary>
599        /// Set preview duration.
600        /// </summary>
601        public int PreviewDuration { get { return mView.ObiForm.Settings.Audio_PreviewDuration; } }
602
603        /// <summary>
604        ///  Empty node in which recording is taking place
605                /// </summary>
606        public EmptyNode RecordingPhrase { get { return mRecordingPhrase; } }
607
608        public int RecordingInitPhraseIndex { get { return mRecordingInitPhraseIndex; } }
609
610        /// <summary>
611        /// Section in which recording is going on
612        /// </summary>
613        public SectionNode RecordingSection { get { return mRecordingSection; } }
614        public string RecordingPhraseToString { get { 
615            return ( mState == State.Recording && mRecordingPhrase != null && mView.Selection != null && mView.Selection.Node == mRecordingPhrase )?
616            Localizer.Message("Selected_RecordingPhrase"): "" ; } }
617
618
619        /// <summary>
620        /// The parent project view. Should be set ASAP, and only once.
621        /// </summary>
622        public ProjectView ProjectView
623        {
624            set
625            {
626                if (mView != null) throw new Exception("Cannot set the project view again!");
627                mView = value;
628                UpdateButtons();
629               
630                mView.BlocksVisibilityChanged += new EventHandler(mView_BlocksVisibilityChanged);
631                mView.SelectionChanged += new EventHandler(delegate(object sender, EventArgs e) {
632                    if(mView.Selection == null || mView.Selection.Node != m_FineNavigationPhrase ) FineNavigationModeForPhrase = false;
633
634                    //@enforce single cursor
635                    if (mView.ObiForm != null && mView.ObiForm.Settings.Audio_EnforceSingleCursor
636                        && CurrentState == State.Paused &&  mView.Selection != null && mView.Selection is AudioSelection
637                    && ((AudioSelection)mView.Selection).AudioRange.HasCursor )
638                    {
639                        double time = ((AudioSelection)mView.Selection).AudioRange.CursorTime  ;
640                        mView.UpdateCursorPosition(time);
641                        mCurrentPlaylist.CurrentTimeInAsset = time;
642                    }
643
644                    UpdateButtons();
645                    //if (Enabled && mSelectionChangedPlayEnable &&  mView.ObiForm.Settings.PlayOnNavigate)   PlaybackOnSelectionChange();
646                    if (Enabled && mSelectionChangedPlayEnable ) PlaybackOnSelectionChange_Safe ();
647                });
648            }
649        }
650
651        /// <summary>
652        /// Get the recorder associated with the transport bar.
653        /// </summary>
654        public AudioLib.AudioRecorder Recorder { get { return mRecorder; } }
655
656        /// <summary>
657        /// Get the VU meter associated with the transport bar.
658        /// </summary>
659        public AudioLib.VuMeter VuMeter { get { return mVuMeter; } }
660
661        public RecordingSession RecordingSession { get { return mRecordingSession; } }
662
663        // Initialize audio (player, recorder, VU meter.)
664        private void InitAudio()
665        {
666            mPlayer = new AudioLib.AudioPlayer(false);
667            //mPlayer.AllowBackToBackPlayback = true;
668            mRecorder = new AudioLib.AudioRecorder();
669            mRecorder.StateChanged += new AudioLib.AudioRecorder.StateChangedHandler(Recorder_StateChanged);
670            mVuMeter = new AudioLib.VuMeter(mPlayer, mRecorder);
671            mVUMeterPanel.VuMeter = mVuMeter;
672            mRecorder.CircularBufferNotificationTimerMessage += new AudioLib.AudioRecorder.CircularBufferNotificationTimerMessageHandler(LogRecorderMissedNotificationMsg);
673        }
674
675        // Initialize playlists
676        private void InitPlaylists()
677        {
678            mMasterPlaylist = new Playlist(mPlayer , true);
679            mLocalPlaylist = null;
680            mCurrentPlaylist = mMasterPlaylist;
681            SetPlaylistEvents(mMasterPlaylist);
682        }
683
684        // Property set when the selection is an audio selection (range or cursor)
685        private bool IsInPhraseSelectionMarked
686        {
687            get
688            {
689                return mView.Selection != null && mView.Selection is AudioSelection;
690            }
691        }
692
693        // Synchronize accessible label of the the time display box.
694        private void mDisplayBox_SelectedIndexChanged(object sender, EventArgs e)
695        {
696            mTimeDisplayBox.AccessibleName = mDisplayBox.SelectedItem.ToString();
697            mTransportBarTooltip.SetToolTip(mDisplayBox, mDisplayBox.SelectedItem.ToString());
698            // selected index should go in settings only when presentation is not null because it is assigned only when new presentation is set
699            if (mView != null && mView.ObiForm.Settings != null && mView.Presentation != null) mView.ObiForm.Settings.TransportBarCounterIndex = mDisplayBox.SelectedIndex;
700            m_IsElapsedInProjectSelectedBeforeStop = false;
701        }
702
703        // Update the time display immediatly when the display mode changes.
704        private void mDisplayBox_SelectionChangeCommitted(object sender, EventArgs e)
705        {
706            mDisplayBox.Tag = null;
707            UpdateTimeDisplay();
708           
709        }
710
711        // Periodically update the time display and the audio cursor.
712        private void mDisplayTimer_Tick(object sender, EventArgs e)
713        {
714            UpdateTimeDisplay();
715            if (mPlayer.CurrentState == AudioLib.AudioPlayer.State.Playing)
716                {
717                mView.UpdateCursorPosition ( mCurrentPlaylist.CurrentTimeInAsset );
718                                                }
719        }
720
721        // Move the audio cursor to the phrase currently playing.
722
723        private delegate void Playlist_MovedToPhrase_Delegate(object sender, Events.Node.PhraseNodeEventArgs e);
724        private void Playlist_MovedToPhrase(object sender, Events.Node.PhraseNodeEventArgs e)
725        {
726            if (this.InvokeRequired)
727            {
728                this.Invoke(new Playlist_MovedToPhrase_Delegate(Playlist_MovedToPhrase), sender, e);
729            }
730            else
731            {
732                mView.SetPlaybackPhraseAndTime(e.Node, mCurrentPlaylist.CurrentTimeInAsset);
733                UpdateTimeDisplay();
734            }
735        }
736       
737        // Update the transport bar according to the player state.
738
739        private delegate void Playlist_PlayerStateChanged_Delegate(object sender, AudioLib.AudioPlayer.StateChangedEventArgs e);
740        private void Playlist_PlayerStateChanged(object sender, AudioLib.AudioPlayer.StateChangedEventArgs e)
741        {
742            if (this.InvokeRequired)
743            {
744                this.Invoke(new Playlist_PlayerStateChanged_Delegate(Playlist_PlayerStateChanged), sender, e);
745            }
746            else
747            {
748                mState = mPlayer.CurrentState == AudioLib.AudioPlayer.State.Paused ? State.Paused :
749                   mPlayer.CurrentState == AudioLib.AudioPlayer.State.Playing ? State.Playing : State.Stopped;
750
751                m_ElapsedTime_FromSectionToFirstRecordingPhraseOrPlaybackPhrase = -1;
752                m_ElapsedTime_Book = -1;
753                if (mState == State.Playing || mState == State.Recording)
754                {
755                    mDisplayTimer.Start();
756                    if (mState == State.Playing || mState == State.Paused) mView.SetPlaybackBlockIfRequired();
757                   
758                }
759                else if (mState == State.Stopped)
760                {
761                    mDisplayTimer.Stop();
762                    if (!(mCurrentPlaylist is PreviewPlaylist)) mView.SetPlaybackPhraseAndTime(null, 0);//added on 31 july ,2010
763                }
764                UpdateTimeDisplay();
765                UpdateButtons();
766                if (mState == State.Stopped && mView != null && mCurrentPlaylist != null && !mCurrentPlaylist.CanNavigateNextPhrase) mView.UpdateCursorPosition(0.0); // audio coursor returns to 0 position if the single phrase is being played
767                // if single cursor is enforced then the audioselection should be removed on starting playback
768                if (mView.ObiForm.Settings.Audio_EnforceSingleCursor)
769                {
770                    if (CurrentState == State.Playing && !(mLocalPlaylist is PreviewPlaylist )
771                        && mView.Selection != null && mView.Selection is AudioSelection
772                            && ((AudioSelection)mView.Selection).AudioRange != null && ((AudioSelection)mView.Selection).AudioRange.HasCursor )
773                    {   
774                        bool playbackOnSelection = this.SelectionChangedPlaybackEnabled;
775                        this.SelectionChangedPlaybackEnabled = false;
776                        mView.Selection = new NodeSelection (mView.Selection.Node, mView.Selection.Control ) ;
777                        this.SelectionChangedPlaybackEnabled = playbackOnSelection ;
778                }
779                }
780
781                if (StateChanged != null) StateChanged(this, e);
782
783                if (IsPlayerActive && !(mCurrentPlaylist is PreviewPlaylist) && MonitorContinuously) MonitorContinuously = false; //@MonitorContinuously
784                if (m_IsPreviewing && mCurrentPlaylist is PreviewPlaylist)
785                {
786                    if (mState == State.Paused) mView.UpdateCursorPosition(((PreviewPlaylist)mCurrentPlaylist).RevertTime);
787                    PostPreviewRestore();
788                }
789            }
790        }
791
792        // Simply pass the playback rate change event.
793
794        private delegate void Playlist_PlaybackRateChanged_Delegate(object sender, EventArgs e);
795        private void Playlist_PlaybackRateChanged(object sender, EventArgs e)
796        {
797            if (this.InvokeRequired)
798            {
799                this.Invoke(new Playlist_PlaybackRateChanged_Delegate(Playlist_PlaybackRateChanged), sender, e);
800            }
801            else
802            {
803                if (PlaybackRateChanged != null) PlaybackRateChanged(sender, e);
804            }
805        }
806
807
808        // Update the transport bar once the player has stopped.
809
810        private delegate void Playlist_PlayerStopped_Delegate(object sender, EventArgs e);
811        private void Playlist_PlayerStopped(object sender, EventArgs e)
812        {
813            if (this.InvokeRequired)
814            {
815                this.Invoke(new Playlist_PlayerStopped_Delegate(Playlist_PlayerStopped), sender, e);
816            }
817            else
818            {   
819               
820                if (mCurrentPlaylist != null && mCurrentPlaylist is PreviewPlaylist)
821                {
822                    mView.UpdateCursorPosition(mAfterPreviewRestoreTime);
823                }
824                else
825                {
826                    mView.SetPlaybackPhraseAndTime(null, 0.0);
827                    if (CurrentState == State.Stopped)//@masternewbehaviour
828                    {
829                        if (mView.ObiForm.Settings.Audio_SelectLastPhrasePlayed
830                    && mCurrentPlaylist != null
831                    && mCurrentPlaylist.LastPhrase != null
832                    && mView.Selection != null
833                            && mView.Selection.Node != mCurrentPlaylist.LastPhrase
834                            && mView.Selection.Control is ContentView)
835                        {
836                            bool isPlayOnSelectionChange = SelectionChangedPlaybackEnabled;
837                            SelectionChangedPlaybackEnabled = false;
838                            mView.SelectFromTransportBar(mCurrentPlaylist.LastPhrase, null);
839                            SelectionChangedPlaybackEnabled = isPlayOnSelectionChange;
840                        }
841                       
842                        mCurrentPlaylist = mMasterPlaylist;
843                        Console.WriteLine("Master Plalist is assigned aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
844                        PhraseNode currentPhrase = FindPlaybackStartNode(mView.Selection == null ? null : mView.Selection.Node);
845                        if (currentPhrase != null) mCurrentPlaylist.CurrentPhrase = currentPhrase;
846                        UpdateButtons();
847                        mView.ObiForm.UpdateRecordingToolBarButtons();
848                    //System.Media.SystemSounds.Asterisk.Play();
849                    }
850                }
851
852            }
853        }
854
855        // Adapt to changes in the presentation.
856        // At the moment, simply stop.
857        private void Presentation_Changed(object sender, urakawa.events.DataModelChangedEventArgs e)
858        {
859            // set project empty flag depending on zero sections in presentation
860        if (mView.Presentation != null)
861            {
862                m_IsProjectEmpty = mView.Presentation.FirstSection == null ;
863            }
864            if (FineNavigationModeForPhrase) FineNavigationModeForPhrase = false;
865        if (mState != State.Stopped)
866            {
867            if (IsPlayerActive && mView.ObiForm.IsAutoSaveActive)
868                {
869                // do not stop, auto save should not disturb playback
870                }
871            else
872                {
873                Stop ();
874                }
875           
876            }
877        }
878       
879        // Adapt to changes in used status.
880        // At the moment, simply stop.
881        private void Presentation_UsedStatusChanged(object sender, NodeEventArgs<ObiNode> e)
882        {
883            if (mState != State.Stopped) Stop();
884        }
885
886        private delegate void Recorder_StateChanged_Delegate();
887        // Update state from the recorder.
888        private void Recorder_StateChanged(object sender, AudioLib.AudioRecorder.StateChangedEventArgs e)
889        {
890            Recorder_StateChanged();
891        }
892
893        private int m_RecorderTimeComboIndex = 0;
894        private int m_PlayerTimeComboIndex = 0;
895        private void Recorder_StateChanged()
896        {
897
898    if (this.InvokeRequired)
899            {
900                this.Invoke(new Recorder_StateChanged_Delegate(Recorder_StateChanged));
901                return;
902            }
903            mState = mRecorder.CurrentState == AudioLib.AudioRecorder.State.Monitoring ? State.Monitoring :
904                mRecorder.CurrentState == AudioLib.AudioRecorder.State.Recording ? State.Recording : State.Stopped;
905            UpdateButtons();
906            if (IsRecorderActive && mView.IsZoomWaveformActive) mView.ZoomPanelClose(); //@zoomwaveform
907            //int selectedIndex = mDisplayBox.SelectedIndex;
908            if (mDisplayBox.Items.Count == m_RecordingElapsedRemainingList.Count)
909            {
910                m_RecorderTimeComboIndex = mDisplayBox.SelectedIndex;
911            }
912            else if (mDisplayBox.Items.Count == m_PlayingElapsedRemainingList.Count)
913            {
914                // following string indicate monitoring: rapid fix
915                if ( mTimeDisplayBox.Text != "--:--:--") m_PlayerTimeComboIndex = mDisplayBox.SelectedIndex;
916            }
917            if (mRecorder.CurrentState != AudioLib.AudioRecorder.State.Recording)
918            {
919                m_ElapsedTime_Book = -1;
920                m_ElapsedTime_FromSectionToFirstRecordingPhraseOrPlaybackPhrase = -1;
921               
922                mDisplayBox.Items.Clear () ;
923                mDisplayBox.Items.AddRange(m_PlayingElapsedRemainingList.ToArray ());
924              //  for (int i = 0; i < m_DisplayComboBoxItems.Count; i++) mDisplayBox.Items.Add(m_DisplayComboBoxItems[i]);
925                //mDisplayBox.SelectedIndex = selectedIndex > -1 ? selectedIndex: 0;
926                mDisplayBox.SelectedIndex = m_PlayerTimeComboIndex > -1 && m_PlayerTimeComboIndex < mDisplayBox.Items.Count ? m_PlayerTimeComboIndex : 0;
927            }
928            else
929            {
930               
931                mDisplayBox.Items.Clear();
932                mDisplayBox.Items.AddRange(m_RecordingElapsedRemainingList.ToArray () );
933               // for (int i = 0; i < 2; i++ ) mDisplayBox.Items.Add(m_DisplayComboBoxItems[i]);
934                //mDisplayBox.SelectedIndex = (selectedIndex < mDisplayBox.Items.Count) ? selectedIndex
935                mDisplayBox.SelectedIndex = (m_RecorderTimeComboIndex>= 0 &&  m_RecorderTimeComboIndex < mDisplayBox.Items.Count) ? m_RecorderTimeComboIndex
936                    : 0;   
937            }
938           
939            UpdateTimeDisplay();
940        }
941
942        // Initialize events for a new playlist.
943        private void SetPlaylistEvents(Playlist playlist)
944        {
945            Console.WriteLine("Events assigned :::::::::::::::::::::::::::::::::::::::::");
946            playlist.MovedToPhrase += new Playlist.MovedToPhraseHandler(Playlist_MovedToPhrase);
947            playlist.StateChanged += new AudioLib.AudioPlayer.StateChangedHandler(Playlist_PlayerStateChanged);
948            playlist.EndOfPlaylist += new Playlist.EndOfPlaylistHandler(Playlist_PlayerStopped);
949            playlist.PlaybackRateChanged += new Playlist.PlaybackRateChangedHandler(Playlist_PlaybackRateChanged);
950        }
951
952        // Update visibility and enabledness of buttons depending on the state of the recorder
953       
954        private delegate void UpdateButtons_Delegate();
955        public void UpdateButtons()
956        {         
957            if (this.InvokeRequired)
958            {
959                this.Invoke(new UpdateButtons_Delegate(UpdateButtons));
960            }
961            else
962            {
963                mPrevSectionButton.Enabled = CanNavigatePrevSection;
964                mPreviousPageButton.Enabled = CanNavigatePrevPage;
965                mPrevPhraseButton.Enabled = CanNavigatePrevPhrase;
966                mRewindButton.Enabled = CanRewind;
967                mPauseButton.Visible = CanPause;
968                mPlayButton.Visible = !mPauseButton.Visible;
969                mPlayButton.Enabled = CanPlay || CanResumePlayback;
970                mFastPlayRateCombobox.Enabled = !IsRecorderActive;
971                mRecordButton.Enabled = (CanRecord || CanResumeRecording
972                    || (CurrentState == State.Playing && (mView.ObiForm.Settings.Audio_UseRecordBtnToRecordOverSubsequentAudio || mView.ObiForm.Settings.Audio_Recording_PreviewBeforeStarting))) && !mView.IsZoomWaveformActive;
973                if (IsPlaying || IsRecorderActive)
974                {
975                    m_btnPlayingOptions.Enabled = false;
976                }
977                else
978                {
979                    m_btnPlayingOptions.Enabled = true;
980                }
981                if (IsPlayerActive)
982                {
983                    mMonitorContinuouslyToolStripMenuItem.Enabled = false;
984                }
985                else
986                {
987                    mMonitorContinuouslyToolStripMenuItem.Enabled = true;
988                }
989
990                bool recordDirectly = (mView.ObiForm  != null && mView.ObiForm.Settings.Audio_RecordDirectlyWithRecordButton) ? true : false;
991
992                if (recordDirectly)
993                {
994                    m_btnRecordingOptions.Enabled = CanRecord || CanResumeRecording;
995
996                    if (this.IsListening)
997                    {
998                        m_MonitoringtoolStripMenuItem.Visible = false;
999                        m_RecordingtoolStripMenuItem.Visible = true;
1000                    }
1001
1002                    else
1003                    {
1004                        m_MonitoringtoolStripMenuItem.Visible = true;                     
1005                        m_RecordingtoolStripMenuItem.Visible = false;                     
1006
1007                    }                   
1008                    if (mView.ObiForm.Settings.Audio_AllowOverwrite)
1009                    {
1010                        m_DeletePhrasestoolStripMenuItem.Enabled = !this.IsListening;
1011                    }
1012                    else
1013                    {
1014                        m_DeletePhrasestoolStripMenuItem.Enabled = false;
1015                    }
1016                }
1017                else
1018                {
1019                    m_btnRecordingOptions.Enabled = false;
1020                }
1021
1022               
1023
1024                if (mRecorder.CurrentState == AudioLib.AudioRecorder.State.Monitoring || recordDirectly || mRecorder.CurrentState == AudioLib.AudioRecorder.State.Recording || CanResumeRecording)
1025                {
1026                    mRecordButton.Image = m_recordButtonImage;
1027                    mRecordButton.Invalidate();
1028                }
1029                else
1030                {
1031                    mRecordButton.Image = m_monitorButtonImage;
1032                    mRecordButton.Invalidate();
1033                }
1034                if (keyboardShortcuts != null)
1035                {
1036                    mRecordButton.AccessibleName = Localizer.Message(
1037                        (mRecorder.CurrentState == AudioLib.AudioRecorder.State.Monitoring || (recordDirectly && CurrentState != State.Recording))
1038                            ? "start_recording"
1039                            : "start_monitoring"
1040                        ) + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mStartMonitoringToolStripMenuItem"].Value.ToString()) + ")";
1041                }
1042                else
1043                {
1044                    mRecordButton.AccessibleName = Localizer.Message(
1045                                           (mRecorder.CurrentState == AudioLib.AudioRecorder.State.Monitoring || (recordDirectly && CurrentState != State.Recording))
1046                                               ? "start_recording"
1047                                               : "start_monitoring"
1048                                           );
1049                }
1050                mStopButton.Enabled = CanStop;
1051                mFastForwardButton.Enabled = CanFastForward;
1052                mNextPhrase.Enabled = CanNavigateNextPhrase;
1053                mNextPageButton.Enabled = CanNavigateNextPage;
1054                mNextSectionButton.Enabled = CanNavigateNextSection;
1055                mToDo_CustomClassMarkButton.Enabled = mView.CanSetTODOStatus;
1056                if (MonitorContinuously && mView.Selection == null)
1057                {
1058                    m_btnRecordingOptions.Enabled = mView.Selection == null;
1059                    m_RecordingtoolStripMenuItem.Enabled = false;
1060                }
1061                else
1062                {
1063                    m_RecordingtoolStripMenuItem.Enabled = true;
1064                }
1065                if (mView != null && mView.ObiForm != null && mView.ObiForm.Settings != null)
1066                {
1067                    if (mView.ObiForm.Settings.Audio_PlaySectionUsingPlayBtn)
1068                    {
1069                        m_PlayAlltoolStripMenuItem.Text = Localizer.Message("TransportBar_PlaySelection");
1070                    }
1071                    else
1072                    {
1073                        m_PlayAlltoolStripMenuItem.Text = Localizer.Message("TransportBar_PlayAll");
1074                    }
1075                }
1076            }
1077        }
1078       
1079        private static string FormatDuration_hh_mm_ss(double durationMs)
1080        {
1081            double seconds = durationMs / 1000.0;
1082            int minutes = (int)Math.Floor(seconds / 60.0);
1083            int seconds_ = (int)Math.Floor(seconds - minutes * 60.0);
1084            return string.Format(Localizer.Message("duration_hh_mm_ss"), minutes / 60, minutes % 60, seconds_);
1085        }
1086
1087        /// <summary>
1088        /// Update the time display to show current time. Depends on the what kind of timing is selected.
1089        /// </summary>
1090
1091        private delegate void UpdateTimeDisplay_Delegate();
1092        private void UpdateTimeDisplay()
1093         {
1094             
1095                 if (this.InvokeRequired)
1096                 {
1097                     this.Invoke(new UpdateTimeDisplay_Delegate(UpdateTimeDisplay));
1098                 }
1099                 else
1100                 {
1101                     int selectedIndex = mDisplayBox.SelectedIndex;
1102                     if (mDisplayBox.DroppedDown)
1103                     {
1104                         if (mDisplayBox.Tag != null)
1105                         {
1106                             int index = -1;
1107                             int.TryParse(mDisplayBox.Tag.ToString(), out index);
1108                             if (index >= 0) selectedIndex = index;
1109                         }
1110                     }
1111
1112                     if (mState == State.Monitoring)
1113                     {   
1114                         mTimeDisplayBox.Text = "--:--:--";
1115                         mDisplayBox.SelectedIndex = ELAPSED_INDEX;
1116                     }
1117                     else if (mState == State.Recording && mRecordingSession.AudioRecorder.RecordingPCMFormat != null)
1118                     {
1119                         if (mView.ObiForm.Settings.Audio_ShowSelectionTimeInTransportBar && m_IsElapsedInProjectSelectedBeforeStop)
1120                         {
1121                             mDisplayBox.SelectedIndex = selectedIndex = ELAPSED_TOTAL_INDEX;
1122                         }
1123                         if(mRecordingSession == null ) return;
1124                         //mRecordingSession.AudioRecorder.TimeOfAsset
1125                         double timeOfAssetMilliseconds =
1126                            (double)mRecordingSession.AudioRecorder.RecordingPCMFormat.ConvertBytesToTime(Convert.ToInt64(mRecordingSession.AudioRecorder.CurrentDurationBytePosition)) /
1127                            Time.TIME_UNIT;
1128
1129                         //mTimeDisplayBox.Text = FormatDuration_hh_mm_ss(timeOfAssetMilliseconds);
1130                         //mDisplayBox.SelectedIndex = ELAPSED_INDEX;
1131                         mTimeDisplayBox.Text = FormatDuration_hh_mm_ss(
1132                             selectedIndex == ELAPSED_INDEX ?
1133                                 timeOfAssetMilliseconds :
1134                             selectedIndex == ELAPSED_SECTION ?
1135                             RecordingTimeElapsedSection :
1136                             selectedIndex == ELAPSED_TOTAL_RECORDING_INDEX ?
1137                               RecordingTimeElapsedTotal : 0.0);
1138
1139                     }
1140                     else if (mState == State.Stopped)
1141                     {
1142                         if (mView != null && mView.Selection != null && mView.ObiForm.Settings.Audio_ShowSelectionTimeInTransportBar && (mView.Selection is AudioSelection || mView.Selection.Node is PhraseNode))
1143                         {
1144                             PhraseNode phraseNode = (PhraseNode)mView.Selection.Node;
1145                             m_TotalCursorTime = 0.0;
1146                             if (mView.Selection is AudioSelection && ((AudioSelection)mView.Selection).AudioRange != null)
1147                             {
1148                                 if (selectedIndex == ELAPSED_INDEX || selectedIndex == ELAPSED_SECTION || selectedIndex == ELAPSED_TOTAL_INDEX)
1149                                 {
1150                                     if (((AudioSelection)mView.Selection).AudioRange.HasCursor)
1151                                     {
1152                                         m_TotalCursorTime += ((AudioSelection)mView.Selection).AudioRange.CursorTime;
1153                                     }
1154                                     else
1155                                     {
1156                                         m_TotalCursorTime += ((AudioSelection)mView.Selection).AudioRange.SelectionBeginTime;
1157                                     }
1158
1159                                 }
1160
1161                                 else if (selectedIndex == REMAIN_INDEX)
1162                                 {
1163                                     if (((AudioSelection)mView.Selection).AudioRange.HasCursor)
1164                                     {
1165                                         m_TotalCursorTime = ((AudioSelection)mView.Selection).AudioRange.CursorTime;
1166                                     }
1167                                     else
1168                                     {
1169                                         m_TotalCursorTime += ((AudioSelection)mView.Selection).AudioRange.SelectionEndTime;
1170                                     }
1171                                     m_TotalCursorTime = mView.Selection.Node.Duration - m_TotalCursorTime;
1172
1173                                 }
1174                             }
1175
1176                             if (selectedIndex == ELAPSED_SECTION || selectedIndex == ELAPSED_TOTAL_INDEX)
1177                             {
1178                                 if (phraseNode.PrecedingNode != null && phraseNode.Parent == phraseNode.PrecedingNode.Parent)
1179                                 {
1180                                     if (phraseNode.PrecedingNode is PhraseNode)
1181                                     {
1182                                         CalculateCursorTime((PhraseNode)phraseNode.PrecedingNode);
1183                                     }
1184                                     else if (phraseNode.PrecedingNode is EmptyNode)
1185                                     {
1186                                         ObiNode tempNode = phraseNode.PrecedingNode;
1187                                         while (tempNode != null && !(tempNode is PhraseNode) && tempNode.Parent == tempNode.PrecedingNode.Parent)
1188                                         {
1189                                             tempNode = tempNode.PrecedingNode;
1190                                         }
1191                                         if (tempNode is PhraseNode)
1192                                         {
1193                                             CalculateCursorTime((PhraseNode)tempNode);
1194                                         }
1195                                     }
1196                                 }
1197                             }
1198                             if (selectedIndex == ELAPSED_TOTAL_INDEX)
1199                             {
1200                                 mDisplayBox.SelectedIndex = ELAPSED_SECTION;
1201                                 m_IsElapsedInProjectSelectedBeforeStop = true;
1202                             }
1203
1204                             mTimeDisplayBox.Text = FormatDuration_hh_mm_ss(m_TotalCursorTime);
1205                         }
1206                         //else if (mView.ObiForm.Settings.Project_ShowSelectionTimeInTransportBar && mView.Selection.Node is PhraseNode)
1207                         //{
1208                         //    PhraseNode phraseNode = (PhraseNode)mView.Selection.Node;
1209                         //    m_TotalCursorTime = 0.0;
1210                         //    if (selectedIndex == ELAPSED_SECTION || selectedIndex == ELAPSED_TOTAL_INDEX)
1211                         //    {
1212                         //        if (phraseNode.PrecedingNode != null && phraseNode.PrecedingNode is PhraseNode && phraseNode.Parent == phraseNode.PrecedingNode.Parent)
1213                         //        {
1214                         //            CalculateCursorTime((PhraseNode)phraseNode.PrecedingNode);
1215                         //        }
1216                         //    }
1217
1218                         //    if (selectedIndex == ELAPSED_TOTAL_INDEX)
1219                         //    {
1220                         //        mDisplayBox.SelectedIndex = ELAPSED_SECTION;
1221                         //        m_IsElapsedInProjectSelectedBeforeStop = true;
1222                         //    }
1223                         //    mTimeDisplayBox.Text = FormatDuration_hh_mm_ss(m_TotalCursorTime);
1224                         //}
1225                         else
1226                         {
1227                             mTimeDisplayBox.Text = FormatDuration_hh_mm_ss(0.0);
1228                         }
1229                     }
1230                     else
1231                     {
1232                         if (mView.ObiForm.Settings.Audio_ShowSelectionTimeInTransportBar && m_IsElapsedInProjectSelectedBeforeStop)
1233                         {
1234                             mDisplayBox.SelectedIndex = selectedIndex = ELAPSED_TOTAL_INDEX;
1235                         }
1236                         mTimeDisplayBox.Text = FormatDuration_hh_mm_ss(
1237                             selectedIndex == ELAPSED_INDEX ?
1238                                 mCurrentPlaylist.CurrentTimeInAsset :
1239                             selectedIndex == ELAPSED_SECTION ?
1240                                 PlaybackTimeElapsedSection :
1241                             selectedIndex == ELAPSED_TOTAL_INDEX ?
1242                             //  mCurrentPlaylist.CurrentTime :
1243                               PlayingTimeElapsedTotal :
1244                             selectedIndex == REMAIN_INDEX ?
1245                             mCurrentPlaylist.RemainingTimeInAsset :
1246                             //  selectedIndex == REMAINING_IN_SECTION?                         
1247                             //  RemainingTimeInSection:
1248                             mCurrentPlaylist.RemainingTime
1249                                 );
1250                     }
1251                 
1252             }
1253         }
1254
1255        private void CalculateCursorTime(PhraseNode phraseNode)
1256        {
1257
1258            m_TotalCursorTime += phraseNode.Duration;
1259
1260            if (phraseNode.PrecedingNode != null && (phraseNode.PrecedingNode.Parent == phraseNode.Parent))
1261            {
1262                if (phraseNode.PrecedingNode is PhraseNode)
1263                {
1264                    CalculateCursorTime((PhraseNode)phraseNode.PrecedingNode);
1265                }
1266                else if (phraseNode.PrecedingNode is EmptyNode)
1267                {
1268                    ObiNode tempNode = phraseNode.PrecedingNode;
1269                    while (tempNode != null && !(tempNode is PhraseNode) && tempNode.PrecedingNode.Parent == tempNode.Parent)
1270                    {
1271                        tempNode = tempNode.PrecedingNode;
1272                    }
1273                    if (tempNode is PhraseNode)
1274                    {
1275                        CalculateCursorTime((PhraseNode)tempNode);
1276                    }
1277                }
1278            }
1279
1280        }
1281         private void CalculateSectionTime(SectionNode secNode)
1282         {
1283
1284             m_TotalCursorTime += secNode.Duration;
1285             if (secNode.PrecedingSection != null && secNode.PrecedingSection is SectionNode)
1286             {
1287                 CalculateSectionTime((SectionNode)secNode.PrecedingSection);
1288             }
1289         }
1290         private double m_ElapsedTime_Book = -1;
1291         public double RecordingTimeElapsedTotal
1292         {
1293             get
1294            {
1295                if (m_ElapsedTime_Book < 0) CalculateTimeElapsed_Book();
1296
1297                return m_ElapsedTime_Book +  (double)mRecordingSession.AudioRecorder.RecordingPCMFormat.ConvertBytesToTime(Convert.ToInt64( mRecorder.CurrentDurationBytePosition)) /
1298                          Time.TIME_UNIT;
1299            }
1300        }
1301
1302        public double PlayingTimeElapsedTotal
1303        {
1304            get
1305            {
1306                if (m_ElapsedTime_Book < 0) CalculateTimeElapsed_Book();
1307                return m_ElapsedTime_Book + mCurrentPlaylist.CurrentTimeInAsset;
1308            }
1309        }
1310
1311
1312             private void CalculateTimeElapsed_Book()
1313        {
1314                 if (CurrentState == State.Recording &&   mRecordingPhrase == null ) return ;
1315                 if (IsPlayerActive && PlaybackPhrase == null) return;
1316                 m_ElapsedTime_Book = 0;
1317
1318                 bool foundPhrase = false;
1319            mView.Presentation.RootNode.AcceptDepthFirst(
1320                    delegate(urakawa.core.TreeNode n)
1321                    {
1322                        if ((CurrentState == State.Recording &&  n == mRecordingPhrase )
1323                            ||    ( IsPlayerActive && n == PlaybackPhrase)
1324                            || foundPhrase)
1325                        {
1326                            foundPhrase = true;
1327                            return false;
1328                        }
1329                        if (n is PhraseNode && n.Children.Count == 0)
1330                        {
1331                            m_ElapsedTime_Book += ((PhraseNode)n).Audio.Duration.AsMilliseconds;
1332                        }
1333                       
1334                        return true;
1335                    },
1336                    delegate(urakawa.core.TreeNode n) { });
1337        }
1338
1339        private double m_ElapsedTime_FromSectionToFirstRecordingPhraseOrPlaybackPhrase = -1;
1340        public double RecordingTimeElapsedSection
1341        {
1342            get
1343            {
1344                if (m_ElapsedTime_FromSectionToFirstRecordingPhraseOrPlaybackPhrase < 0) CalculateTimeElapsedInSection();
1345
1346                return m_ElapsedTime_FromSectionToFirstRecordingPhraseOrPlaybackPhrase + (double)mRecordingSession.AudioRecorder.RecordingPCMFormat.ConvertBytesToTime(Convert.ToInt64( mRecorder.CurrentDurationBytePosition)) /
1347                          Time.TIME_UNIT;
1348            }
1349        }
1350
1351        public double PlaybackTimeElapsedSection
1352        {
1353            get
1354            {
1355                if (m_ElapsedTime_FromSectionToFirstRecordingPhraseOrPlaybackPhrase < 0) CalculateTimeElapsedInSection();
1356
1357                return m_ElapsedTime_FromSectionToFirstRecordingPhraseOrPlaybackPhrase + mCurrentPlaylist.CurrentTimeInAsset;
1358            }
1359        }
1360
1361
1362        private void CalculateTimeElapsedInSection()
1363        {
1364            if (CurrentState == State.Recording && mRecordingPhrase == null) return;
1365            if (IsPlayerActive && PlaybackPhrase == null) return;
1366           
1367            m_ElapsedTime_FromSectionToFirstRecordingPhraseOrPlaybackPhrase = 0;
1368            SectionNode section = CurrentState == State.Recording && mRecordingPhrase != null ? mRecordingPhrase.ParentAs<SectionNode>() :
1369                PlaybackPhrase != null ? PlaybackPhrase.ParentAs<SectionNode>() : null;
1370            if (section != null)
1371            {
1372                for (int i = 0; i < section.PhraseChildCount; ++i)
1373                {
1374                    EmptyNode n = section.PhraseChild(i);
1375                    if ((CurrentState == State.Recording && n == mRecordingPhrase)
1376                        || (IsPlayerActive && n == PlaybackPhrase))
1377                    {
1378                        return;
1379                    }
1380                    if (n is PhraseNode && n.Children.Count == 0)
1381                    {
1382                        m_ElapsedTime_FromSectionToFirstRecordingPhraseOrPlaybackPhrase += ((PhraseNode)n).Audio.Duration.AsMilliseconds;
1383                    }
1384                }
1385            }
1386
1387        }
1388
1389        // Play/Resume playback
1390
1391        private void mPlayButton_Click(object sender, EventArgs e) 
1392        {
1393            if (mView.ObiForm.Settings.Audio_PlaySectionUsingPlayBtn)
1394            {
1395                PlaySection();
1396            }
1397            else
1398            {
1399                PlayOrResume();
1400            }
1401        }
1402
1403        /// <summary>
1404        /// Play all in the project. (Used when nothing is selected, or from the play all menu item.)
1405        /// Start from the current selection, or from the first phrase.
1406        /// </summary>
1407        public void PlayAll()
1408            {
1409            try
1410                {
1411                                                                PlayAll_safe ();
1412                }
1413            catch (System.Exception ex)
1414                {
1415                mView.WriteToLogFile(ex.ToString());
1416                    if (mCurrentPlaylist != null) mCurrentPlaylist.ForcedStopForError();
1417                MessageBox.Show ( string.Format ( Localizer.Message ( "TransportBar_PlayerExceptionMsg" ), "\n\n", ex.ToString () ) );
1418                }
1419            }
1420
1421        private void PlayAll_safe ()
1422        {
1423                        if (CanPlay)
1424            {
1425                //mCurrentPlaylist = mMasterPlaylist;
1426                //PlayCurrentPlaylistFromSelection();
1427            PlayMaster ();
1428            }
1429            else if (CanResumePlayback)
1430            {
1431                if (mCurrentPlaylist != mMasterPlaylist) // if this is local playlist, start playing master playlist from the point where local playlist has paused
1432                {
1433                PlayMasterFromPlaylistTransition ();
1434                }
1435                else
1436                    mCurrentPlaylist.Resume();
1437            }
1438                    }
1439
1440       
1441
1442        private void PlayMaster ()
1443            {
1444            if (mPlayQAPlaylist)
1445                {
1446                CreateQAPlaylist ();
1447                }
1448            else
1449                {
1450                mCurrentPlaylist = mMasterPlaylist;
1451                }
1452            PlayCurrentPlaylistFromSelection ();
1453            }
1454
1455        private void CreateQAPlaylist ()
1456            {
1457                                                mQAMasterPlaylist = new Playlist ( mPlayer, true);
1458                                    mQAMasterPlaylist.Presentation = mView.Presentation;
1459                        mCurrentPlaylist = mQAMasterPlaylist;
1460            SetPlaylistEvents (  mQAMasterPlaylist);
1461            }
1462
1463        /// <summary>
1464        /// if playback is paused and current playlist is not master playlist, starts playing master playlist from paused position
1465                /// </summary>
1466        private void PlayMasterFromPlaylistTransition ()
1467            {
1468            if (mState == State.Paused && mCurrentPlaylist != null)
1469                {
1470                PhraseNode transitionPhrase = mCurrentPlaylist.CurrentPhrase;
1471                double transitionTime = mCurrentPlaylist.CurrentTimeInAsset;
1472                if (mCurrentPlaylist is PreviewPlaylist) transitionTime = ((PreviewPlaylist)mCurrentPlaylist).RevertTime;
1473
1474                Stop ();
1475
1476                if (mPlayQAPlaylist)
1477                    {
1478                    CreateQAPlaylist ();
1479                    }
1480                else
1481                    {
1482                    mCurrentPlaylist = mMasterPlaylist;
1483                    }
1484                PlayCurrentPlaylistFrom ( transitionPhrase, transitionTime );
1485                }
1486            }
1487
1488
1489
1490        /// <summary>
1491        /// All-purpose play function for the play button.
1492        /// Play or resume if possible, otherwise do nothing.
1493        /// If there is a selection, play the selection; if there is no selection, play everything
1494        /// (depending on the relevent preference setting.)
1495        /// </summary>
1496        public void PlayOrResume()
1497            {
1498            try
1499                {
1500                                                PlayOrResume_Safe ();
1501                }
1502            catch ( System.Exception ex )
1503                {
1504                mView.WriteToLogFile(ex.ToString());
1505                    if (mCurrentPlaylist != null) mCurrentPlaylist.ForcedStopForError();
1506                MessageBox.Show ( string.Format ( Localizer.Message ( "TransportBar_PlayerExceptionMsg" ), "\n\n", ex.ToString () ) );
1507                }
1508            }
1509
1510        private void PlayOrResume_Safe ()
1511        {
1512                if (CanPlay || CanPreviewAudioSelection)
1513            {
1514                    // for play selection stop existing playlist if active
1515            if (mState == State.Paused && CanPreviewAudioSelection) Stop ();
1516
1517                PlayOrResume(mView.Selection == null ? null : mView.Selection.Node);
1518            }
1519            else if (CanResumePlayback)
1520            {
1521                if (mCurrentPlaylist == mMasterPlaylist || mCurrentPlaylist is PreviewPlaylist)
1522                {
1523                    // if this is master playlist or preview playlist, start playing local playlist from the point where master or preview playlist is paused
1524                                    PlayLocalPlaylistFromPlaylistTransition ();
1525                }
1526                else
1527                {
1528                    mCurrentPlaylist.Resume();
1529                }
1530            }
1531        }
1532
1533
1534        /// <summary>
1535        /// Play a single node (phrase or section), or everything if the node is null
1536        /// (and the mPlayIfNoSelection flag is set.)
1537        /// </summary>
1538        public void PlayOrResume(ObiNode node)
1539        {
1540            if (node == null && PlayIfNoSelection)
1541            {
1542                PlayAll();
1543            }
1544            else if (node != null)
1545            {
1546                if (!node.IsRooted) return;
1547                bool neglectSelection;
1548                //if (IsPlaySection == false)
1549                //{
1550                     neglectSelection = mView.Selection == null
1551                        || (node is EmptyNode && mView.Selection.Node != node);
1552                //}
1553                //else
1554                //{
1555                    //neglectSelection = true;
1556                    //IsPlaySection = false;
1557                //}
1558               
1559                if (neglectSelection || m_IsPlaySectionInspiteOfPhraseSelection)
1560                {
1561                    if (m_IsPlaySectionInspiteOfPhraseSelection && mView.Selection != null && mView.Selection.Control is ContentView )
1562                    {
1563                        // play shallow, if focus is in the content view
1564                        mLocalPlaylist = new Playlist(mPlayer,  node, mPlayQAPlaylist, false);
1565                    }
1566                    else
1567                    {
1568                    mLocalPlaylist = new Playlist(mPlayer,  node, mPlayQAPlaylist);
1569                    }
1570                }
1571                else
1572                {
1573                    mLocalPlaylist = new Playlist(mPlayer, mView.Selection, mPlayQAPlaylist);
1574                }
1575                SetPlaylistEvents(mLocalPlaylist);
1576                if (mCurrentPlaylist is PreviewPlaylist && !((PreviewPlaylist)mCurrentPlaylist).IsPreviewComplete) ((PreviewPlaylist)mCurrentPlaylist).EnsureDisAssociationEvents(); //added on Oct 29, 2015, precautionary for beta release, will be reviewed after release
1577                mCurrentPlaylist.EnsureDisAssociationEventsinPlaylist();
1578                mCurrentPlaylist = mLocalPlaylist;
1579                if (neglectSelection && !m_IsPlaySectionInspiteOfPhraseSelection)
1580                {
1581                    mCurrentPlaylist.Play () ;
1582                }
1583                else
1584                {
1585                PlayCurrentPlaylistFromSelection();
1586                }
1587                m_IsPlaySectionInspiteOfPhraseSelection = false;
1588            }
1589        }
1590
1591        /// <summary>
1592        /// If playback is paused and current playlist is not local playlist, Plays local playlist from paused position
1593                /// </summary>
1594        private void PlayLocalPlaylistFromPlaylistTransition ()
1595            {
1596            if (mState == State.Paused && mCurrentPlaylist != null)
1597                {
1598                PhraseNode transitionPhrase = mCurrentPlaylist.CurrentPhrase;
1599                double transitionTime = mCurrentPlaylist.CurrentTimeInAsset;
1600                //if (mCurrentPlaylist is PreviewPlaylist && !(mView.Selection is AudioSelection) ) transitionTime = ((PreviewPlaylist)mCurrentPlaylist).RevertTime;
1601                if (mCurrentPlaylist is PreviewPlaylist)
1602                {
1603                    if (mView.Selection is AudioSelection)
1604                    {
1605                        transitionTime = ((AudioSelection)mView.Selection).AudioRange.CursorTime;
1606                    }
1607                    else
1608                    {
1609                        transitionTime = ((PreviewPlaylist)mCurrentPlaylist).RevertTime;
1610                    }
1611                    Console.WriteLine("TransportBar: " + "transition in process " + transitionTime);
1612                }
1613                Stop ();
1614               
1615                mLocalPlaylist = new Playlist ( mPlayer, transitionPhrase , mPlayQAPlaylist );
1616                SetPlaylistEvents ( mLocalPlaylist );
1617                mCurrentPlaylist = mLocalPlaylist;
1618                PlayCurrentPlaylistFrom ( transitionPhrase , transitionTime );
1619                }
1620
1621            }
1622
1623
1624        // Find the node to start playback from.
1625        private PhraseNode FindPlaybackStartNode(ObiNode node)
1626        {
1627            ObiNode n;
1628            // start from this node (or the first leaf for a section)
1629            // and go through every node to find the first one in the playlist.
1630            for (n = node is SectionNode ? node.FirstLeaf : node;
1631                n != null && n.IsRooted && !mCurrentPlaylist.ContainsPhrase(n as PhraseNode);
1632                n = n.FollowingNode) { }
1633            return n as PhraseNode;
1634        }
1635
1636        // Play the current playlist from the current selection.
1637        private void PlayCurrentPlaylistFromSelection()
1638        {
1639            if (mView.Selection is AudioSelection && ((AudioSelection)mView.Selection).AudioRange != null )
1640            {
1641                if (!((AudioSelection)mView.Selection).AudioRange.HasCursor && mCurrentPlaylist != mMasterPlaylist && m_IsPlaySectionInspiteOfPhraseSelection == false)
1642                {
1643                    // Play the audio selection (only for local playlist; play all ignores the end of the selection.)
1644                    mCurrentPlaylist.CurrentPhrase = (PhraseNode)mView.Selection.Node;
1645                    if (mCurrentPlaylist.State != AudioLib.AudioPlayer.State.Playing)  mCurrentPlaylist.Play(((AudioSelection)mView.Selection).AudioRange.SelectionBeginTime,
1646                        ((AudioSelection)mView.Selection).AudioRange.SelectionEndTime);
1647                }
1648                else 
1649                {
1650                    mCurrentPlaylist.CurrentPhrase = FindPlaybackStartNode(mView.Selection.Node);
1651                    if (mCurrentPlaylist.CurrentPhrase == mView.Selection.Node)
1652                    {
1653                    // The selected node is in the playlist so play from the cursor
1654                    if (mCurrentPlaylist.State != AudioLib.AudioPlayer.State.Playing)
1655                        {
1656                        // First disable scrol to avoid jumping scrolling of screen on starting playback @AudioScrol
1657                        mView.DisableScrollingInContentsView ();
1658                        mCurrentPlaylist.Play ( ((AudioSelection)mView.Selection).AudioRange.CursorTime );
1659                        }
1660                    }
1661                    else
1662                    {
1663                    if (mAfterPreviewRestoreTime > 0)
1664                        {
1665                        if (mCurrentPlaylist.State != AudioLib.AudioPlayer.State.Playing) mCurrentPlaylist.Play ( mAfterPreviewRestoreTime );
1666                        mAfterPreviewRestoreTime = 0;
1667                        }
1668                    else
1669                        {
1670                        // The selected node is not in the playlist so play from the beginning
1671                        if (mCurrentPlaylist.State != AudioLib.AudioPlayer.State.Playing) mCurrentPlaylist.Play ();
1672                        }
1673                    }
1674                }
1675            }
1676            else if (mView.Selection is StripIndexSelection)
1677            {
1678                // Play from the first phrase in the playlist following the strip cursor,
1679                // or the beginning of the strip.
1680                StripIndexSelection s = (StripIndexSelection)mView.Selection;
1681                if (s.Index < s.Section.PhraseChildCount) // if the focus is on last index then play has nothing to play
1682                {
1683                    mCurrentPlaylist.CurrentPhrase = FindPlaybackStartNode(s.Index < s.Section.PhraseChildCount ?
1684                        (ObiNode)s.Section.PhraseChild(s.Index) : (ObiNode)s.Section);
1685                    if (mCurrentPlaylist.State != AudioLib.AudioPlayer.State.Playing) mCurrentPlaylist.Play();
1686                }
1687            }
1688            else if (mView.Selection is NodeSelection)
1689            {
1690                mCurrentPlaylist.CurrentPhrase = FindPlaybackStartNode(mView.Selection.Node);
1691                if (mCurrentPlaylist.State != AudioLib.AudioPlayer.State.Playing) mCurrentPlaylist.Play();               
1692            }
1693            else
1694            {
1695                if (mCurrentPlaylist.State != AudioLib.AudioPlayer.State.Playing) mCurrentPlaylist.Play();
1696            }
1697        }
1698
1699        /// <summary>
1700        ///  Plays current playlist from given phrase and given time if this given phrase lie in current playlist
1701                /// </summary>
1702        /// <param name="startNode"></param>
1703        /// <param name="time"></param>
1704        private  void    PlayCurrentPlaylistFrom ( PhraseNode startNode , double time )
1705        {
1706        if (mCurrentPlaylist != null && (mState == State.Stopped || mState == State.Paused))
1707            {
1708            if (startNode != null &&  mCurrentPlaylist.ContainsPhrase ( startNode ))
1709                {
1710                mCurrentPlaylist.CurrentPhrase = startNode;
1711                if (mCurrentPlaylist.State != AudioLib.AudioPlayer.State.Playing) mCurrentPlaylist.Play ( time );
1712                }
1713            else
1714                {
1715                PlayCurrentPlaylistFromSelection ();
1716                }
1717            }
1718        }
1719
1720
1721        // Pause
1722
1723        private void mPauseButton_Click(object sender, EventArgs e) { Pause(); }
1724
1725        /// <summary>
1726        /// Pause playback or recording
1727        /// </summary>
1728        public void Pause()
1729        {
1730            if (m_PreviewBeforeRecordingWorker != null && m_PreviewBeforeRecordingWorker.IsBusy) return ;
1731
1732            if (CanPause)
1733            {
1734                            if (m_IsPreviewing)
1735                {
1736                                    mAfterPreviewRestoreTime = mCurrentPlaylist.CurrentTimeInAsset;
1737                                        //Stop();
1738                                    }
1739
1740                mDisplayTimer.Stop();
1741                if (mRecorder.CurrentState == AudioLib.AudioRecorder.State.Recording
1742                    || mRecorder.CurrentState == AudioLib.AudioRecorder.State.Monitoring)
1743                {
1744                    bool isPlayOnSelectionChange = SelectionChangedPlaybackEnabled;
1745                    SelectionChangedPlaybackEnabled = false;
1746                    PauseRecording();
1747                    SelectionChangedPlaybackEnabled = isPlayOnSelectionChange;
1748                }
1749                else if (mCurrentPlaylist.State == AudioLib.AudioPlayer.State.Playing)
1750                {
1751                                    mCurrentPlaylist.Pause();
1752                                    MoveSelectionToPlaybackPhrase ();
1753                }
1754                UpdateButtons();
1755            }
1756           
1757        }
1758
1759        // Pause recording
1760        private void PauseRecording()
1761        {
1762            if (mRecordingSession != null)
1763            {
1764                bool wasMonitoring = mRecordingSession.AudioRecorder.CurrentState == AudioLib.AudioRecorder.State.Monitoring;
1765                mVUMeterPanel.BeepEnable = false;
1766
1767                EmptyNode firstRecordedPage = null;
1768                List<PhraseNode> listOfRecordedPhrases = new List<PhraseNode>();
1769                try
1770                {
1771                    mRecordingSession.Stop();
1772
1773                    // update recorded phrases with audio assets
1774                    if (mRecordingSection != null) ///@MonitorContinuously , if block inserted to bypass the procedure of assigning assets
1775                    {
1776                        UpdateRecordedPhrasesAlongWithPostRecordingOperations(listOfRecordedPhrases, ref firstRecordedPage);
1777
1778                        //Workaround to force phrases to show if they become invisible on stopping recording
1779                        mView.PostRecording_RecreateInvisibleRecordingPhrases(mRecordingSection, mRecordingInitPhraseIndex, mRecordingSession.RecordedAudio.Count);
1780                    }
1781                }
1782                catch (System.Exception ex)
1783                {
1784                    mView.WriteToLogFile(ex.ToString());
1785                    MessageBox.Show(ex.ToString());
1786                }
1787
1788                if (mRecordingSection != null)//@MonitorContinuously
1789                {
1790                    mResumeRecordingPhrase = (PhraseNode)mRecordingSection.PhraseChild(mRecordingInitPhraseIndex + mRecordingSession.RecordedAudio.Count - 1);
1791                    EmptyNode phraseNextToResumePhrase = null;
1792                    if (mResumeRecordingPhrase.FollowingNode != null && mResumeRecordingPhrase.FollowingNode is EmptyNode) phraseNextToResumePhrase = (EmptyNode)mResumeRecordingPhrase.FollowingNode;
1793
1794                    bool playbackEnabledOnSelectionChange = SelectionChangedPlaybackEnabled;
1795                    SelectionChangedPlaybackEnabled = false;
1796                    try
1797                    {
1798                        int phraseChildCount = mRecordingSection.PhraseChildCount;
1799                        AdditionalPostRecordingOperations(firstRecordedPage, listOfRecordedPhrases);
1800                        if (phraseChildCount != mRecordingSection.PhraseChildCount)
1801                        {
1802                            if (phraseNextToResumePhrase != null && phraseNextToResumePhrase.IsRooted && phraseNextToResumePhrase.PrecedingNode is PhraseNode)
1803                                mResumeRecordingPhrase = (PhraseNode)phraseNextToResumePhrase.PrecedingNode;
1804                            else if (mRecordingSection.PhraseChild(mRecordingSection.PhraseChildCount - 1) is PhraseNode)
1805                                mResumeRecordingPhrase = (PhraseNode)mRecordingSection.PhraseChild(mRecordingSection.PhraseChildCount - 1);
1806
1807                        }
1808                    }
1809                    catch (System.Exception ex)
1810                    {
1811                        mView.WriteToLogFile(ex.ToString());
1812                        MessageBox.Show(ex.ToString());
1813                    }
1814
1815                    if (!wasMonitoring && mResumeRecordingPhrase != null) mView.SelectFromTransportBar(mResumeRecordingPhrase, null);
1816                    SelectionChangedPlaybackEnabled = playbackEnabledOnSelectionChange;
1817                }// recording section check   
1818                mRecordingSession = null;
1819                UpdateTimeDisplay();
1820
1821                // optionally save project
1822                //SaveWhenRecordingEnds ();//@singleSection
1823
1824                // makes phrase blocks invisible if these exceed max. visible blocks count during recording
1825                //mView.MakeOldStripsBlocksInvisible ( true); // @phraseLimit :@singleSection: legagy code commented
1826
1827                // missed recorder notifications messages are written to log, if any
1828                if (m_MissedNotificationMessages != null && m_MissedNotificationMessages.Length > 1)
1829                {
1830                    WriteLogMsgForRecorderMissedNotification();
1831                }
1832
1833                //@MonitorContinuously
1834                if (MonitorContinuously)
1835                {
1836                    /// avoiding use of delay at this time to prevent possible bug. It will be restored after alpha.
1837                    //StartMonitorContinuouslyWithDelay();
1838                    StartMonitorContinuously();
1839                }
1840            }
1841        }
1842
1843
1844        /// <summary>
1845        /// move selection to current phrase in playlist
1846                /// </summary>
1847        public void MoveSelectionToPlaybackPhrase ()
1848            {
1849            if (!CanMoveSelectionToPlaybackPhrase) return;//@singleSection
1850            if ( IsPlayerActive )
1851                {
1852                bool SelectionChangedPlaybackStatus = mSelectionChangedPlayEnable;
1853                mSelectionChangedPlayEnable = false;
1854                if (mView.Selection == null )
1855                    mView.SelectFromTransportBar ( mCurrentPlaylist.CurrentPhrase, null );
1856                else if (mCurrentPlaylist != null &&
1857                    (mCurrentPlaylist.State == AudioLib.AudioPlayer.State.Paused)
1858                    && mView.Selection.Node != mCurrentPlaylist.CurrentPhrase)
1859                    {
1860                    mView.SelectFromTransportBar ( mCurrentPlaylist.CurrentPhrase, mView.Selection.Control );
1861                    }
1862                mSelectionChangedPlayEnable = SelectionChangedPlaybackStatus;
1863                }
1864
1865            }
1866
1867
1868        // Stop
1869
1870        private void mStopButton_Click(object sender, EventArgs e) { Stop(); }
1871
1872        /// <summary>
1873        /// The stop button. Stopping twice deselects all.
1874        /// </summary>
1875        public bool Stop()
1876        {
1877            if (CanStop)
1878            {
1879                if ((IsRecorderActive || CanResumeRecording) && !IsPlayerActive )
1880                {
1881                    bool isPlayOnSelectionChange = SelectionChangedPlaybackEnabled;
1882                    SelectionChangedPlaybackEnabled = false;
1883                    StopRecording();
1884                    SelectionChangedPlaybackEnabled = isPlayOnSelectionChange;
1885                }
1886                else
1887                {
1888                    // Stopping again deselects everything
1889                    if (mState == State.Stopped && !mView.ObiForm.Settings.Audio_DisableDeselectionOnStop)
1890                    {
1891                    mView.SetPlaybackPhraseAndTime ( null, 0.0 );
1892                    if (mView.IsZoomWaveformActive == false)
1893                    {
1894                        mView.Selection = null;
1895                    }
1896                    }
1897                    else
1898                    {
1899                    StopPlaylistPlayback ();
1900                    }
1901                }
1902                return true;
1903            }
1904            return false;
1905        }
1906
1907        private void StopPlaylistPlayback ()
1908            {
1909            if (mCurrentPlaylist != null && mCurrentPlaylist.State != AudioLib.AudioPlayer.State.Stopped)
1910                {
1911                bool PlaybackOnSelectionStatus = SelectionChangedPlaybackEnabled;
1912                SelectionChangedPlaybackEnabled = false;
1913                mCurrentPlaylist.Stop ();
1914                mView.SetPlaybackPhraseAndTime ( null, 0.0 );
1915
1916                if (!(mCurrentPlaylist is PreviewPlaylist))
1917                {
1918                    mCurrentPlaylist = mMasterPlaylist; //@masternewbehaviour
1919                    PhraseNode currentPhrase = FindPlaybackStartNode(mView.Selection == null ? null : mView.Selection.Node);
1920                    if (currentPhrase != null)
1921                    {
1922                        mCurrentPlaylist.CurrentPhrase = currentPhrase;
1923                    }
1924                }
1925                else
1926                {
1927                    // if preview playlist, reset the flickering colors
1928                    if (mView.ObiForm.Settings.Audio_ColorFlickerPreviewBeforeRecording) mView.ResetColorAfterColorFlickering();
1929                    }
1930                UpdateButtons();
1931                SelectionChangedPlaybackEnabled = PlaybackOnSelectionStatus;
1932                }
1933            }
1934
1935
1936
1937        // Record
1938
1939        private void mRecordButton_Click(object sender, EventArgs e) { Record_Button(); }
1940
1941        /// <summary>
1942        /// allows direct recording when record directly preferences is checked else it goes through monitoring first
1943        /// </summary>
1944        public bool Record_Button()
1945        {
1946            if (MonitorContinuously) StopMonitorContinuously(); //@MonitorContinuously
1947            if (mView.ObiForm.Settings.Audio_RecordDirectlyWithRecordButton && CurrentState != State.Monitoring) //if monitoring go through the traditional way
1948            {
1949                if (mView.ObiForm.Settings.Audio_AllowOverwrite && CurrentState == State.Playing) Pause(); //@RecordFromPlayback
1950                if (mView.ObiForm.Settings.Audio_UseRecordBtnToRecordOverSubsequentAudio
1951                    && !mView.ObiForm.Settings.Audio_Recording_PreviewBeforeStarting)
1952                {
1953                   
1954                    RecordOverSubsequentPhrases();
1955                }
1956                else
1957                {
1958                    StartRecordingDirectly(mView.ObiForm.Settings.Audio_Recording_PreviewBeforeStarting);
1959                }
1960               
1961            }
1962            else
1963            {
1964                Record();
1965            }
1966            return true;
1967        }
1968
1969        /// <summary>
1970        /// Start monitoring (if stopped) or recording (if monitoring)
1971        /// </summary>
1972        public void Record()
1973        {
1974            if (mView.Selection is TextSelection || IsMetadataSelected || mView.IsZoomWaveformActive)
1975                return;
1976
1977           
1978            if (mView.Presentation != null
1979                        &&    !IsMetadataSelected && ( mView.Selection == null || !(mView.Selection is TextSelection)))
1980            {
1981                if (CurrentState == State.Playing)//@RecordFromPlayback   
1982                {
1983                    if (mView.ObiForm.Settings.Audio_AllowOverwrite)
1984                    {
1985                        Pause(); 
1986                    }
1987                    else
1988                    {
1989                        return;
1990                    }
1991                }
1992
1993            try
1994                {
1995                if (mState == State.Monitoring)
1996                    {
1997                        if (!MonitorContinuously)
1998                        {
1999                            mRecordingSession.Stop();
2000                            StartRecording();
2001                        }
2002                        else //@MonitorContinuously
2003                        {
2004                            StopMonitorContinuously();//@MonitorContinuously
2005                            SetupRecording(Recording, false);
2006                        }
2007                    }
2008                else if (CanResumeRecording)
2009                    {
2010                        if (MonitorContinuously) StopMonitorContinuously(); //@MonitorContinuously
2011                    SetupRecording ( Recording , false);
2012                    }
2013                else if (!IsRecorderActive)
2014                    {
2015                    SetupRecording ( Monitoring, false );
2016                    }
2017                }
2018            catch (System.Exception ex)
2019                {
2020                mView.WriteToLogFile(ex.ToString());
2021                MessageBox.Show ( Localizer.Message ( "TransportBar_ErrorInStartingRecording" ) + "\n\n" + ex.ToString () , Localizer.Message ( "Caption_Error" ) );
2022                if (mState == State.Monitoring || mState == State.Recording ) Stop ();
2023                }
2024            } // presentation check ends
2025        }
2026
2027
2028        // Parameters for StartRecordingOrMonitoring
2029        private static readonly bool Recording = true;
2030        private static readonly bool Monitoring = false;
2031
2032        private void SetupRecording(bool recording, bool deleteFollowingPhrases) { SetupRecording(recording, null, deleteFollowingPhrases); }
2033
2034        // Setup recording and start recording or monitoring
2035        private void SetupRecording(bool recording, SectionNode afterSection, bool deleteFollowingPhrases)
2036        {
2037
2038            if (mView.ObiForm.CheckDiskSpace() <= 100)
2039            {
2040                DialogResult result = MessageBox.Show(string.Format(Localizer.Message("LimitedDiskSpaceWarning"), 100), Localizer.Message("Memory_Warning"), MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
2041
2042                if (result == DialogResult.No)
2043                {
2044                    return;
2045                }
2046            }
2047
2048        if (mRecorder != null && mRecorder.CurrentState == AudioLib.AudioRecorder.State.Stopped)
2049                        {
2050            urakawa.command.CompositeCommand command = CreateRecordingCommand ();
2051
2052            // assign selection to null if metadata is selected.
2053            // : this may be removed now as recording is skipped if metadata is selected
2054            if (mView.Selection != null && mView.Selection is MetadataSelection)
2055                mView.Selection = null;
2056
2057            // warning message while resuming recording
2058            if ((mResumeRecordingPhrase != null && mResumeRecordingPhrase.IsRooted) &&
2059                mView.Selection != null && mView.Selection.Node != mResumeRecordingPhrase &&
2060                MessageBox.Show ( Localizer.Message ( "recording_resume_check" ),
2061                    Localizer.Message ( "recording_resume_check_caption" ),
2062                    MessageBoxButtons.YesNo,
2063                    MessageBoxIcon.Question ) == DialogResult.No)
2064                {
2065                mResumeRecordingPhrase = null;
2066                mRecordingPhrase = null;
2067                }
2068// if recording phrase is not rooted, make it to null
2069            // doing separately to reduce complexity of above if block
2070            if (mResumeRecordingPhrase != null && !mResumeRecordingPhrase.IsRooted)
2071                {
2072                mResumeRecordingPhrase = null;
2073                mRecordingPhrase = null;
2074                MessageBox.Show ( Localizer.Message ( "RecordingResumePhrasesDeleted" ), Localizer.Message ( "Caption_Information" ), MessageBoxButtons.OK, MessageBoxIcon.Information );
2075                                }
2076
2077            //if selection is in TOC view save it also
2078                                if (mView.Selection != null && mView.Selection.Control is TOCView)
2079                                {
2080                                    command.ChildCommands.Insert(command.ChildCommands.Count , new Commands.UpdateSelection(mView, new NodeSelection(mView.Selection.Node , mView.Selection.Control)));
2081                                }
2082            //@singleSection: if phrases till recording phrases are hidden, remove existing phrases to enable content view start from phrases near to recording phrase
2083            mView.RecreateContentsWhileInitializingRecording ( mResumeRecordingPhrase);
2084            // if record section from first empty phrase is checked, do accordingly.
2085            if (mView.Selection != null && mView.Selection.Node is SectionNode && mResumeRecordingPhrase == null)
2086            {
2087                SectionNode section = mView.GetSelectedPhraseSection;
2088                if ( mView.ObiForm.Settings.Audio_RecordInFirstEmptyPhraseWithRecordSectionCommand
2089                    && section.PhraseChildCount > 0 && !(section.PhraseChild(0) is PhraseNode) && section.PhraseChild(0).Role_ == EmptyNode.Role.Plain)
2090            {
2091                mView.SelectFromTransportBar(mView.GetSelectedPhraseSection.PhraseChild(0), null);
2092            }
2093            }
2094            if (deleteFollowingPhrases && CurrentState == State.Paused && PlaybackPhrase != null
2095                && mView.Selection != null && mView.Selection.Control is TOCView)
2096            {
2097                mView.SelectFromTransportBar(PlaybackPhrase, null);
2098            }
2099
2100            // save the selection before starting recording
2101            ObiNode selectionNode = mResumeRecordingPhrase != null ? mResumeRecordingPhrase :
2102                mView.GetSelectedPhraseSection != null ? (mView.Selection is StripIndexSelection && ( (StripIndexSelection)mView.Selection).EmptyNodeForSelection != null ? ((StripIndexSelection)mView.Selection).EmptyNodeForSelection :mView.Selection.Node ): null;
2103            if (selectionNode != null && mView.GetSelectedPhraseSection != null)
2104                {
2105                if (mResumeRecordingPhrase != null && mResumeRecordingPhrase == selectionNode && !(mView.Selection.Control is ContentView))
2106                    {
2107                    mView.SelectPhraseInContentView ( mResumeRecordingPhrase );
2108                    }
2109                   
2110                    if (deleteFollowingPhrases
2111                        && ( (CurrentState == State.Paused  && mView.Selection.Node is EmptyNode)   
2112                        ||    (mView.Selection is AudioSelection )))
2113                    {
2114                       
2115                        //MessageBox.Show("recording selection update");   
2116                        double replaceStartTime = IsPlayerActive ? CurrentPlaylist.CurrentTimeInAsset:
2117                            mView.Selection is AudioSelection?( ((AudioSelection)mView.Selection).AudioRange.HasCursor? ((AudioSelection)mView.Selection).AudioRange.CursorTime : ((AudioSelection)mView.Selection).AudioRange.SelectionBeginTime ): 
2118                            selectionNode.Duration;
2119
2120                        // adding a command for updating selection after intermediate selection changes, in order to hide the temporary selections being done for achieving the required behaviour.
2121                        if (mView.ObiForm.Settings.Audio_EnsureCursorVisibilityInUndoOfSplitRecording) mView.Selection = new AudioSelection((PhraseNode)selectionNode, mView.Selection.Control, new AudioRange(replaceStartTime));
2122                            command.ChildCommands.Insert(command.ChildCommands.Count, new Commands.UpdateSelection(mView, new NodeSelection(selectionNode, mView.Selection.Control)));
2123
2124                        mView.Selection = new AudioSelection((PhraseNode) selectionNode, mView.Selection.Control, new AudioRange(replaceStartTime, selectionNode.Duration) );
2125                       
2126                    }
2127                    else
2128                    {
2129                        command.ChildCommands.Insert(command.ChildCommands.Count, new Commands.UpdateSelection(mView, new NodeSelection(selectionNode, mView.Selection.Control)));
2130                    }
2131                }
2132                else if (selectionNode == null && mView.GetSelectedPhraseSection == null)//also saving null selection
2133                {
2134                    command.ChildCommands.Insert(command.ChildCommands.Count, new Commands.UpdateSelection(mView, null));
2135                }
2136                if (mResumeRecordingPhrase == null) mRecordingPhrase = null;
2137
2138            ObiNode node = GetRecordingNode ( command, afterSection );
2139            InitRecordingSectionAndPhraseIndex ( node, mView.ObiForm.Settings.Audio_AllowOverwrite, command , deleteFollowingPhrases);
2140            if (mView.Selection == null && node is SectionNode) mView.SelectFromTransportBar(node, null);// if nothing is selected, new section is created, select it in content view
2141           
2142            // Set events
2143            mRecordingSession = new RecordingSession ( mView.Presentation, mRecorder, mView.ObiForm.Settings );
2144            mRecordingSession.StartingPhrase += new Obi.Events.Audio.Recorder.StartingPhraseHandler (
2145                delegate ( object sender, Obi.Events.Audio.Recorder.PhraseEventArgs e )
2146                    {
2147                    RecordingPhraseStarted ( e, command, (EmptyNode)(node.GetType () == typeof ( EmptyNode ) ? node : null) );
2148                    } );
2149            mRecordingSession.FinishingPhrase += new Obi.Events.Audio.Recorder.FinishingPhraseHandler (
2150                delegate ( object sender, Obi.Events.Audio.Recorder.PhraseEventArgs e ) { RecordingPhraseEnded ( e ); } );
2151            mRecordingSession.FinishingPage += new Events.Audio.Recorder.FinishingPageHandler (
2152                delegate ( object sender, Obi.Events.Audio.Recorder.PhraseEventArgs e ) { RecordingPage ( e ); } );
2153
2154            // resume recording should be null to indicate that recoreding is in process and cannot be resumed.
2155            mResumeRecordingPhrase = null;
2156            // Holding the value in recording session because it is dependent on selection before recording
2157            mRecordingSession.Audio_DeleteFollowingPhrasesOfSectionAfterRecording = mView.ObiForm.Settings.Audio_DeleteFollowingPhrasesOfSectionAfterRecording && CanRecordOnFollowingAudio;
2158                //&& (mView.Selection == null || !(mView.Selection is AudioSelection) || ((AudioSelection)mView.Selection).AudioRange.HasCursor) ;
2159
2160            // Actually start monitoring or recording
2161            if (recording)
2162                {
2163                StartRecording ();
2164                }
2165            else
2166                {
2167                                     mRecordingSession.StartMonitoring ();
2168                                   
2169                if (mView.ObiForm.Settings.Audio_AudioClues) mVUMeterPanel.BeepEnable = true;
2170                }
2171            }
2172        }
2173
2174        // Create a new recording command.
2175        private CompositeCommand CreateRecordingCommand()
2176        {
2177            urakawa.command.CompositeCommand command = mView.Presentation.CommandFactory.CreateCompositeCommand();
2178            command.ShortDescription = (Localizer.Message("recording_command"));//sdk2
2179            return command;
2180        }
2181
2182        // member variables to transfer role of recording phrase in case of 2 point split, not a good way but it is safest at this last moment
2183        private bool m_IsAfterRecordingSplitTransferEnabled;
2184                private EmptyNode m_TempNodeForPropertiesTransfer = null;
2185
2186        // Initialize recording section/phrase index depending on the
2187        // context node for recording and the settings.
2188        private void InitRecordingSectionAndPhraseIndex(ObiNode node, bool overwrite, urakawa.command.CompositeCommand  command, bool deleteFollowingPhrases)
2189        {
2190           
2191        m_IsAfterRecordingSplitTransferEnabled = false;
2192        m_TempNodeForPropertiesTransfer = null;
2193        bool isPhraseSplit = false;
2194
2195            if (node is SectionNode)
2196            {
2197                // Record at the end of the section, or after the cursor
2198                // in case of a cursor selection in the section.
2199                mRecordingSection = (SectionNode)node;
2200                mRecordingInitPhraseIndex = mView.Selection is StripIndexSelection ?
2201                    ((StripIndexSelection)mView.Selection).Index : mRecordingSection.PhraseChildCount;
2202                if (mView.Selection is StripIndexSelection && mView.Selection.Node != null)
2203                {
2204                    AddTheDeleteSubsequentPhrasesCommand(mRecordingSection, deleteFollowingPhrases, false,command);
2205                }
2206            }
2207            else if (node is PhraseNode)
2208            {
2209               
2210                // Record in or after the phrase node, depending on overwrite settings.
2211                mRecordingSection = node.AncestorAs<SectionNode>();
2212                mRecordingInitPhraseIndex = 1 + node.Index;
2213                if (overwrite && (mState == State.Paused ||
2214                    mView.Selection is AudioSelection ))
2215                {
2216                    //MessageBox.Show(SplitBeginTime.ToString () + " , selection time"+ ((mView.Selection != null && mView.Selection is AudioSelection)? ((AudioSelection)mView.Selection).AudioRange.CursorTime.ToString () : ""  ));
2217                    // TODO: we cannot record from pause at the moment; maybe that's not so bad actually.
2218
2219                    // behaviour modified as per request of VA
2220                    // Split command should not transfer properties to new phrase if the subsequent phrases are deleted. The following line is replaced by conditional split commands
2221                    //Commands.Node.SplitAudio.GetSplitCommand ( mView );
2222                CompositeCommand SplitCommand = deleteFollowingPhrases?
2223                    Commands.Node.SplitAudio.GetSplitCommand ( mView,false ):
2224                    Commands.Node.SplitAudio.GetSplitCommand ( mView );
2225                if (SplitCommand != null)
2226                {
2227                    command.ChildCommands.Insert(command.ChildCommands.Count, SplitCommand);
2228                    isPhraseSplit = true;
2229                }
2230                else if (SplitCommand == null && mView.ObiForm.Settings.Audio_AllowOverwrite
2231                    && CurrentState == State.Paused && mCurrentPlaylist.CurrentTimeInAsset == 0)
2232                {
2233                    // split does not work if the pause position is at 0.0s.
2234                    // Therefore, if we are in overwrite recording mode,  we need to move index to the selected phrase position, to ensure that the effect is like splitting at 0 position
2235                    mRecordingInitPhraseIndex = node.Index;
2236                    Console.WriteLine("Pause position was at 0");
2237                }
2238
2239                                    if (mView.Selection is AudioSelection && !((AudioSelection)mView.Selection).AudioRange.HasCursor && SplitCommand != null)
2240                                        {
2241                                        command.ChildCommands.Insert (command.ChildCommands.Count,  new Commands.Node.DeleteWithOffset ( mView, node, 1 ) );
2242                                        // copy the properties to the new middle node only if the following phrases are not deleted. (VA request)
2243                                        // i.e. If the following phrases are deleted then the original phrase should retain properties
2244                                        if (!deleteFollowingPhrases)
2245                                        {
2246                                        m_IsAfterRecordingSplitTransferEnabled = true;
2247                                        CopyPropertiesForTransfer((EmptyNode)node);
2248                                    }
2249                                       
2250                                        }
2251                }
2252            }
2253            else if (node is EmptyNode)
2254            {
2255                // Record inside the empty node
2256                mRecordingSection = node.AncestorAs<SectionNode>();
2257                mRecordingInitPhraseIndex = node.Index;
2258            }
2259            // if audio after cursor has to be replaced, delete following phrases command should be used
2260            if ((deleteFollowingPhrases)
2261                && node is EmptyNode && ((EmptyNode)node).Index < ((EmptyNode)node).ParentAs<SectionNode>().PhraseChildCount-1)
2262            {
2263                AddTheDeleteSubsequentPhrasesCommand(node, deleteFollowingPhrases,isPhraseSplit,command);
2264            }
2265        if (IsPlayerActive) StopPlaylistPlayback (); // stop if split recording starts while playback is paused
2266
2267        }
2268
2269        private void AddTheDeleteSubsequentPhrasesCommand(ObiNode node, bool deleteFollowingPhrases, bool isPhraseSplit,CompositeCommand command)
2270        {
2271            if (deleteFollowingPhrases)
2272            {
2273                int phraseIndex =(node != null &&   node is EmptyNode)? ((EmptyNode)node).Index + 1:
2274                    (mView.Selection != null && mView.Selection is StripIndexSelection )? ((StripIndexSelection)mView.Selection).Index: -1 ;
2275                SectionNode section = node != null && node is EmptyNode? ((EmptyNode)node).ParentAs<SectionNode>():
2276                    mView.Selection != null && mView.Selection is StripIndexSelection? (SectionNode)mView.Selection.Node: null ;
2277                //MessageBox.Show(phraseIndex.ToString());
2278                if (section == null || phraseIndex < 0 || phraseIndex >= section.PhraseChildCount) return;
2279
2280                if (mView.ObiForm.Settings.Audio_PreservePagesWhileRecordOverSubsequentAudio
2281                    && isPhraseSplit && node is ObiNode && ((EmptyNode)node).Role_ == EmptyNode.Role.Page)
2282                {
2283                    //command.ChildCommands.Insert(command.ChildCommands.Count,
2284                        //new Commands.Node.Delete(mView, section.PhraseChild(phraseIndex)));
2285                    //phraseIndex++;
2286                    //if (phraseIndex >= section.PhraseChildCount) return;
2287                   
2288                }
2289
2290                command.ChildCommands.Insert(command.ChildCommands.Count, 
2291                    mView.GetDeleteRangeOfPhrasesInSectionCommand(section, section.PhraseChild(phraseIndex), section.PhraseChild(section.PhraseChildCount - 1),
2292                    mView.ObiForm.Settings.Audio_PreservePagesWhileRecordOverSubsequentAudio, PhraseNode.Role.Page));
2293            }
2294        }
2295
2296        private delegate void RecordingPhraseStarted_Delegate(Obi.Events.Audio.Recorder.PhraseEventArgs e,
2297            urakawa.command.CompositeCommand command, EmptyNode emptyNode);
2298
2299        // Start recording a phrase, possibly replacing an empty node (only for the first one.)
2300        private void RecordingPhraseStarted(Obi.Events.Audio.Recorder.PhraseEventArgs e,
2301            urakawa.command.CompositeCommand command, EmptyNode emptyNode)
2302        {
2303            if (InvokeRequired)
2304            {
2305                Invoke(new RecordingPhraseStarted_Delegate(RecordingPhraseStarted), e, command, emptyNode);
2306            }
2307            else
2308            {
2309
2310                // Suspend presentation change handler so that we don't stop when new nodes are added.
2311                mView.Presentation.Changed -= new EventHandler<urakawa.events.DataModelChangedEventArgs>(Presentation_Changed);
2312                mView.Presentation.UsedStatusChanged -= new NodeEventHandler<ObiNode>(Presentation_UsedStatusChanged);
2313                PhraseNode phrase = mView.Presentation.CreatePhraseNode(e.Audio);
2314                mRecordingPhrase = phrase;
2315                Commands.Node.AddNode add = new Commands.Node.AddNode(mView, phrase, mRecordingSection,
2316                    mRecordingInitPhraseIndex + e.PhraseIndex);
2317                add.SetDescriptions(command.ShortDescription);
2318
2319                // transfer properties if 2 point split is being performed
2320                if (m_IsAfterRecordingSplitTransferEnabled && m_TempNodeForPropertiesTransfer != null)
2321                {
2322                    m_IsAfterRecordingSplitTransferEnabled = false;
2323                    CopyPropertiesToRecordingNode((EmptyNode)phrase);
2324                }
2325
2326
2327                //add.UpdateSelection = false;
2328                if (e.PhraseIndex == 0)
2329                {
2330                    if (emptyNode != null && e.PhraseIndex == 0)
2331                    {
2332                        phrase.CopyAttributes(emptyNode);
2333                        phrase.Used = emptyNode.Used;
2334                        Commands.UpdateSelection updateSelection = new Commands.UpdateSelection(mView, new NodeSelection(emptyNode, mView.Selection.Control));
2335                        updateSelection.RefreshSelectionForUnexecute = true;
2336                        command.ChildCommands.Insert(command.ChildCommands.Count, updateSelection);
2337                        command.ChildCommands.Insert(command.ChildCommands.Count, new Commands.Node.Delete(mView, emptyNode));
2338                        command.ChildCommands.Insert(command.ChildCommands.Count, add);
2339                    }
2340                    else
2341                    {
2342                        command.ChildCommands.Insert(command.ChildCommands.Count, add);
2343                    }
2344
2345
2346                    mView.Presentation.UndoRedoManager.Execute(command);
2347                }
2348                else
2349                {
2350                    // Check if the next phrase is empty page. if it is then record into it instead of creating new phrase
2351                    EmptyNode followingEmptyPage = null;
2352                    if (e.PhraseIndex > 0 && mRecordingSection.PhraseChildCount > mRecordingInitPhraseIndex + e.PhraseIndex && e.IsPage)
2353                    {
2354
2355                        ObiNode followingObiNode = mRecordingSection.PhraseChild(mRecordingInitPhraseIndex + e.PhraseIndex);
2356                        if (followingObiNode != null && !(followingObiNode is PhraseNode)
2357                            && ((EmptyNode)followingObiNode).Role_ == EmptyNode.Role.Page)
2358                        {
2359
2360                            followingEmptyPage = (EmptyNode)followingObiNode;
2361                        }
2362                    }
2363
2364                    if (followingEmptyPage != null)
2365                    {
2366                        urakawa.command.CompositeCommand recordInNextPageCommand = mView.Presentation.CreateCompositeCommand(Localizer.Message("Recording_RecordInNextExistingEmptyPage"));
2367                        phrase.CopyAttributes(followingEmptyPage);
2368                        recordInNextPageCommand.ChildCommands.Insert(recordInNextPageCommand.ChildCommands.Count, new Commands.Node.Delete(mView, followingEmptyPage));
2369                        recordInNextPageCommand.ChildCommands.Insert(recordInNextPageCommand.ChildCommands.Count, add);
2370                        mView.Presentation.UndoRedoManager.Execute(recordInNextPageCommand);
2371
2372                    }
2373                    else
2374                    {
2375                        mView.Presentation.UndoRedoManager.Execute(add);
2376                    }
2377                }
2378                mView.Presentation.UsedStatusChanged += new NodeEventHandler<ObiNode>(Presentation_UsedStatusChanged);
2379                mView.Presentation.Changed += new EventHandler<urakawa.events.DataModelChangedEventArgs>(Presentation_Changed);
2380                if (mRecordingPhrase != null && mView.Selection != null && mView.Selection.Control.GetType() == typeof(ContentView) && !this.ContainsFocus)
2381                    mView.Selection = new NodeSelection(mRecordingPhrase, mView.Selection.Control);
2382            }
2383        }
2384
2385
2386        private void CopyPropertiesForTransfer ( EmptyNode node )
2387            {
2388            mView.Presentation.Changed -= new EventHandler<urakawa.events.DataModelChangedEventArgs> ( Presentation_Changed );
2389            mView.Presentation.UsedStatusChanged -= new NodeEventHandler<ObiNode> ( Presentation_UsedStatusChanged );
2390            m_TempNodeForPropertiesTransfer = mView.Presentation.TreeNodeFactory.Create<EmptyNode>();
2391            m_TempNodeForPropertiesTransfer.CopyAttributes ( (EmptyNode)node );
2392            m_TempNodeForPropertiesTransfer.Used = ((EmptyNode)node).Used;
2393            mView.Presentation.UsedStatusChanged += new NodeEventHandler<ObiNode> ( Presentation_UsedStatusChanged );
2394            mView.Presentation.Changed += new EventHandler<urakawa.events.DataModelChangedEventArgs> ( Presentation_Changed );
2395            }
2396
2397
2398        private void CopyPropertiesToRecordingNode ( EmptyNode recordingNode )
2399            {//1
2400            if (m_TempNodeForPropertiesTransfer != null)
2401                {//2
2402                try
2403                    {//3
2404                    if (m_TempNodeForPropertiesTransfer.Role_ == EmptyNode.Role.Page)
2405                        {//4
2406                        recordingNode.TODO = m_TempNodeForPropertiesTransfer.TODO;
2407                        recordingNode.Used = m_TempNodeForPropertiesTransfer.Used;
2408                        recordingNode.Role_ = m_TempNodeForPropertiesTransfer.Role_;
2409                        recordingNode.PageNumber = m_TempNodeForPropertiesTransfer.PageNumber.Clone ();
2410                        }//-4
2411                    else
2412                        {//4
2413                        recordingNode.CopyAttributes ( m_TempNodeForPropertiesTransfer );
2414                        recordingNode.Used = m_TempNodeForPropertiesTransfer.Used;
2415                        }//-4
2416                    m_TempNodeForPropertiesTransfer = null;
2417                    }//-3
2418                catch (System.Exception ex)
2419                    {//3
2420                    mView.WriteToLogFile(ex.ToString());
2421                    m_TempNodeForPropertiesTransfer = null;
2422                    }//-3
2423                }//-2
2424
2425            }
2426
2427
2428        // Stop recording a phrase
2429        private void RecordingPhraseEnded(Obi.Events.Audio.Recorder.PhraseEventArgs e)
2430        {
2431            //if (!mView.ObiForm.Settings.Audio_EnableLivePhraseDetection) //@onTheFly: following code should be executed if live phrase detection is disabled
2432            //{
2433                PhraseNode phrase = (PhraseNode)mRecordingSection.PhraseChild(e.PhraseIndex + mRecordingInitPhraseIndex);
2434                phrase.SignalAudioChanged(this, e.Audio);
2435                mRecordingPhrase = null;
2436            //}
2437        }
2438
2439        // Start recording a new page, set the right page number
2440        private void RecordingPage(Obi.Events.Audio.Recorder.PhraseEventArgs e)
2441        {
2442           
2443                PhraseNode phrase = (PhraseNode)mRecordingSection.PhraseChild(e.PhraseIndex + mRecordingInitPhraseIndex + 1);
2444                Console.WriteLine ("Page mark indexes: " + phrase.Index + " : " + mRecordingSection.PhraseChildCount + ", session phrase count  : " + (mRecordingInitPhraseIndex+mRecordingSession.PhraseMarksCount)) ;
2445                Dictionary<PhraseNode, PageNumber> phraseToPageNumberMap = new Dictionary<PhraseNode, PageNumber>();
2446                phraseToPageNumberMap.Add(phrase, phrase.PageNumber);
2447            // if the phrase is page, make it plain phrase before assigning new page number
2448                if (phrase.Role_ == EmptyNode.Role.Page) phrase.Role_ = EmptyNode.Role.Plain;
2449                // page role is automatically assigned by assigning page number
2450                phrase.PageNumber = mView.Presentation.PageNumberFollowing(phrase);
2451               
2452                for (int i = phrase.Index+1 ; 
2453                    i < mRecordingSection.PhraseChildCount && i<= mRecordingInitPhraseIndex + mRecordingSession.PhraseMarksCount; 
2454                    i++)
2455                {
2456                    EmptyNode empty = mRecordingSection.PhraseChild(i);
2457                    //Console.WriteLine("iterating phrase " + i);
2458                    phrase = (PhraseNode)empty;
2459                   
2460                    phraseToPageNumberMap.Add(phrase, phrase.PageNumber);
2461
2462                    if (phraseToPageNumberMap.ContainsKey((PhraseNode)mRecordingSection.PhraseChild(i - 1)))
2463                    {
2464                        PageNumber number = phraseToPageNumberMap[(PhraseNode)mRecordingSection.PhraseChild(i - 1)];
2465                        if (number != null)
2466                        {
2467                            phrase.PageNumber = number;
2468                        }
2469                        else
2470                        {
2471                            phrase.Role_ = EmptyNode.Role.Plain;
2472                        }
2473                    }//key contains check ends
2474                }
2475           
2476        }
2477
2478        // Get a node to record in. If we are resuming, this is the node to resume from;
2479        // otherwise the selected node (section or phrase) for node selection, audio selection
2480        // or strip cursor selection. If there is no node, add to the recording command a
2481        // command to create a new section to record in.
2482        public ObiNode GetRecordingNode(urakawa.command.CompositeCommand command, SectionNode afterSection)
2483        {
2484            ObiNode node = afterSection != null ? null :
2485                (mResumeRecordingPhrase == null || !mResumeRecordingPhrase.IsRooted) ?
2486                mState == State.Paused && !(mView.Selection is AudioSelection && !((AudioSelection)mView.Selection).AudioRange.HasCursor) ? mCurrentPlaylist.CurrentPhrase :
2487                mView.Selection is NodeSelection || mView.Selection is AudioSelection || mView.Selection is StripIndexSelection ?
2488                    mView.Selection.Node : null :
2489                mResumeRecordingPhrase;
2490            if (node == null)
2491            {
2492           
2493                SectionNode section = mView.Presentation.CreateSectionNode();
2494                urakawa.command.Command add = null;
2495                if (afterSection == null)
2496                {
2497                    add = new Commands.Node.AddNode(mView, section, (ObiNode)mView.Presentation.RootNode,
2498                        ((ObiRootNode)mView.Presentation.RootNode).SectionChildCount);
2499                    ((Commands.Node.AddNode)add).UpdateSelection = false;
2500                }
2501                else
2502                {
2503                    Commands.Node.AddNode addSection =
2504                        new Commands.Node.AddNode(mView, section, afterSection.ParentAs<ObiNode>(), afterSection.Index + 1);
2505                    addSection.UpdateSelection = false;
2506                    add = mView.Presentation.CreateCompositeCommand(addSection.ShortDescription);
2507                    ((CompositeCommand)add).ChildCommands.Insert(((CompositeCommand)add).ChildCommands.Count, addSection);
2508                    for (int i = afterSection.SectionChildCount - 1; i >= 0; --i)
2509                    {
2510                        SectionNode child = afterSection.SectionChild(i);
2511                        Commands.Node.Delete delete = new Commands.Node.Delete(mView, child);
2512                        delete.UpdateSelection = false;
2513                        ((CompositeCommand)add).ChildCommands.Insert(((CompositeCommand)add).ChildCommands.Count, delete);
2514                        Commands.Node.AddNode readd = new Commands.Node.AddNode(mView, child, section, 0);
2515                        readd.UpdateSelection = false;
2516                        ((CompositeCommand)add).ChildCommands.Insert(((CompositeCommand)add).ChildCommands.Count,  readd);
2517                    }
2518                }
2519                command.ChildCommands.Insert(command.ChildCommands.Count, add);
2520                node = section;
2521            }
2522            return node;
2523        }
2524
2525        // Start recording
2526        void StartRecording()
2527        {
2528        mVUMeterPanel.BeepEnable = false;
2529            try
2530            {
2531                mRecordingSession.Record();
2532                mDisplayTimer.Start ();
2533            }
2534            catch (System.Exception ex)
2535            {
2536            mView.WriteToLogFile(ex.ToString());
2537            MessageBox.Show ( Localizer.Message ( "TransportBar_ErrorInStartingRecording" ) + "\n\n" + ex.ToString (), Localizer.Message ( "Caption_Error" ) );
2538            if (mState == State.Monitoring || mState == State.Recording) Stop ();
2539            }
2540                    }
2541
2542
2543        // Navigation
2544
2545        private void mPrevSectionButton_Click(object sender, EventArgs e) { PrevSection(); }
2546        private void mPreviousPageButton_Click(object sender, EventArgs e) { PrevPage(); }
2547        private void mPrevPhraseButton_Click(object sender, EventArgs e) { PrevPhrase(); }
2548        private void mNextPhrase_Click(object sender, EventArgs e) { NextPhrase(); }
2549        private void mNextPageButton_Click(object sender, EventArgs e) { NextPage(); }
2550        private void mNextSectionButton_Click(object sender, EventArgs e) { NextSection(); }
2551
2552        /// <summary>
2553        /// Move to the previous section (i.e. first phrase of the previous section.)
2554        /// </summary>
2555        public bool PrevSection()
2556        {
2557            if (CanNavigatePrevSection)
2558            {
2559                if (mState == State.Stopped)
2560                {
2561                    if (mView.ObiForm.Settings.PlayOnNavigate)
2562                    {
2563                        PlayCurrentPlaylistFromSelection();
2564                        mCurrentPlaylist.NavigateToPreviousSection();
2565                    }
2566                    else
2567                    {
2568                        PhraseNode destinationPhrase = mCurrentPlaylist.PrevSection(
2569                            FindPlaybackStartNode(mView.Selection == null ? null : mView.Selection.Node));
2570                        mView.SelectPhraseInContentView(destinationPhrase);
2571                        mCurrentPlaylist.CurrentPhrase = destinationPhrase; //@masternewbehaviour
2572                    }
2573                }
2574                else
2575                {
2576                    mCurrentPlaylist.NavigateToPreviousSection();
2577                }
2578                return true;
2579            }
2580            return false;
2581        }
2582
2583        /// <summary>
2584        /// Move to or play the previous page.
2585        /// </summary>
2586        public bool PrevPage()
2587        {
2588            if (CanNavigatePrevPage)
2589            {
2590                if (mState == State.Stopped)
2591                {
2592                    if (mView.ObiForm.Settings.PlayOnNavigate)
2593                    {
2594                        PlayCurrentPlaylistFromSelection();
2595                        mCurrentPlaylist.NavigateToPreviousPage();
2596                    }
2597                    else
2598                    {
2599                        PhraseNode destinationPhrase = mCurrentPlaylist.PrevPage(
2600                            FindPlaybackStartNode(mView.Selection == null ? null : mView.Selection.Node));
2601                        mView.SelectPhraseInContentView(destinationPhrase);
2602                        mCurrentPlaylist.CurrentPhrase = destinationPhrase; //@masternewbehaviour
2603                    }
2604                }
2605                else
2606                {
2607                    mCurrentPlaylist.NavigateToPreviousPage();
2608                }
2609                return true;
2610            }
2611            return false;
2612        }
2613
2614        /// <summary>
2615        /// Move to or play the previous phrase.
2616        /// </summary>
2617        public bool PrevPhrase()
2618        {
2619            if (CanNavigatePrevPhrase)
2620            {
2621                if (mState == State.Stopped)
2622                {
2623                    if (mView.ObiForm.Settings.PlayOnNavigate)
2624                    {
2625                        PlayCurrentPlaylistFromSelection();
2626                        mCurrentPlaylist.NavigateToPreviousPhrase();
2627                    }
2628                    else
2629                    {
2630                        // if strip index is selected then select the equivalent phrase block.
2631                        if (mView.Selection != null
2632                            && mView.Selection.Node is SectionNode
2633                            && mView.Selection is StripIndexSelection)
2634                        {
2635                            if (((StripIndexSelection)mView.Selection).Index >= ((SectionNode)mView.Selection.Node).PhraseChildCount)
2636                            {
2637                                SectionNode section = (SectionNode)mView.Selection.Node;
2638                                mView.SelectPhraseBlockOrStrip(section.PhraseChild(section.PhraseChildCount - 1));
2639                            }
2640                            else
2641                            {
2642                                mView.SelectPhraseBlockOrStrip (mView.Selection.EmptyNodeForSelection);
2643                            }
2644                        }
2645                           
2646                        // older code continues below
2647                        PhraseNode destinationPhrase = mCurrentPlaylist.PrevPhrase(
2648                                                    FindPlaybackStartNode(mView.Selection == null ? null : mView.Selection.Node));
2649                        mView.SelectPhraseInContentView(destinationPhrase);
2650                        mCurrentPlaylist.CurrentPhrase = destinationPhrase; //@masternewbehaviour
2651                    }
2652                }
2653                else
2654                {
2655                    mCurrentPlaylist.NavigateToPreviousPhrase();
2656                }
2657                return true;
2658            }
2659            return false;
2660        }
2661
2662        /// <summary>
2663        /// Go to the next phrase.
2664        /// If recording, create a new phrase to record in.
2665        /// If playing or paused,
2666        /// </summary>
2667        public bool NextPhrase()
2668        {
2669            if (CanNavigateNextPhrase)
2670            {
2671                if (mState == State.Recording)
2672                {
2673                    //mRecordingSession.AudioRecorder.TimeOfAsset
2674                    double timeOfAssetMilliseconds =
2675                   (double)mRecordingSession.AudioRecorder.RecordingPCMFormat.ConvertBytesToTime(Convert.ToInt64 (mRecordingSession.AudioRecorder.CurrentDurationBytePosition)) /
2676                   Time.TIME_UNIT;
2677
2678                    if (mRecordingPhrase != null && mRecordingSession != null
2679                        && timeOfAssetMilliseconds < 250) return false;
2680                    // record into to next phrase.
2681                    // check if phrase count of section is less than max limit
2682                    if ( mRecordingSection != null && mRecordingSection.PhraseChildCount < mView.MaxVisibleBlocksCount ) // @phraseLimit
2683                    mRecordingSession.NextPhrase();
2684                }
2685                else if (mState == State.Monitoring)
2686                {
2687                    // start recording
2688                    try
2689                    {
2690                        //@MonitorContinuously
2691                        if (MonitorContinuously)
2692                        {
2693                            StopMonitorContinuously();
2694                            Record_Button();
2695                        }
2696                        else
2697                        {
2698                            mRecordingSession.Stop();
2699
2700                            mVUMeterPanel.BeepEnable = false;
2701                            mRecordingSession.Record();
2702                            mDisplayTimer.Start();
2703                        }
2704                    }
2705                    catch (System.Exception ex)
2706                    {
2707                        mView.WriteToLogFile(ex.ToString());
2708                        MessageBox.Show(Localizer.Message("TransportBar_ErrorInStartingRecording") + "\n\n" + ex.ToString());  //@Messagecorrected
2709                    }
2710                }
2711                else if (mState == State.Stopped)
2712                {
2713                    if (mView.ObiForm.Settings.PlayOnNavigate)
2714                    {
2715                        PlayCurrentPlaylistFromSelection();
2716                        mCurrentPlaylist.NavigateToNextPhrase();
2717                    }
2718                    else
2719                    {
2720                        // if strip index is selected then select the equivalent phrase block.
2721                        if (mView.Selection != null
2722                            && mView.Selection.Node is SectionNode
2723                            && mView.Selection is StripIndexSelection)
2724                        {
2725                            if (((StripIndexSelection)mView.Selection).Index >= ((SectionNode)mView.Selection.Node).PhraseChildCount)
2726                            {
2727                                SectionNode section = (SectionNode)mView.Selection.Node;
2728                                mView.SelectPhraseBlockOrStrip(section.PhraseChild(section.PhraseChildCount - 1));
2729                            }
2730                            else
2731                            {
2732                                mView.SelectPhraseBlockOrStrip(mView.Selection.EmptyNodeForSelection);
2733                            }
2734                        }
2735
2736                        // older code continues below
2737                        PhraseNode startPhrase = FindPlaybackStartNode(mView.Selection == null ? null : mView.Selection.Node);
2738                        PhraseNode destinationPhrase = null;
2739                        if (mView.Selection != null && mView.Selection.Node is EmptyNode && !(mView.Selection.Node is PhraseNode))
2740                        {
2741                            destinationPhrase = startPhrase;
2742                        }
2743                        else
2744                        {
2745                            destinationPhrase = mCurrentPlaylist.NextPhrase(startPhrase);
2746                        }
2747                        mView.SelectPhraseInContentView(destinationPhrase);
2748                        mCurrentPlaylist.CurrentPhrase = destinationPhrase; //@masternewbehaviour
2749                    }
2750                                        }
2751                else
2752                {
2753                    mCurrentPlaylist.NavigateToNextPhrase();
2754                 
2755                }
2756                return true;
2757            }
2758            return false;
2759        }
2760
2761        /// <summary>
2762        /// Go to the next page.
2763        /// </summary>
2764        public bool NextPage()
2765        {
2766            if (CanNavigateNextPage)
2767            {
2768                if (mState == State.Recording)
2769                {
2770                    //mRecordingSession.AudioRecorder.TimeOfAsset
2771                    double timeOfAssetMilliseconds =
2772                   (double)mRecordingSession.AudioRecorder.RecordingPCMFormat.ConvertBytesToTime(Convert.ToInt64( mRecordingSession.AudioRecorder.CurrentDurationBytePosition)) /
2773                   Time.TIME_UNIT;
2774
2775                    if (mRecordingPhrase != null && mRecordingSession != null
2776                        && timeOfAssetMilliseconds < 250) return false;
2777                    // check if phrase limit for section is not over
2778                    if (mRecordingSection != null && mRecordingSection.PhraseChildCount < mView.MaxVisibleBlocksCount) // @phraseLimit
2779                    {
2780                        // check if creation of pages is disabled. If yes, then should proceed only if the next phrase is empty page.
2781                        if (mView.ObiForm.Settings.Audio_DisableCreationOfNewHeadingsAndPagesWhileRecording )
2782                        {
2783                            if (mRecordingPhrase.FollowingNode == null) return false;
2784                            if (!(mRecordingPhrase.FollowingNode is EmptyNode)) return false;
2785                            // if next node is empty node then move to following
2786                                EmptyNode nextEmptyNode = (EmptyNode)mRecordingPhrase.FollowingNode;
2787                                if (nextEmptyNode.Parent != mRecordingPhrase.Parent) return false;
2788                                if (nextEmptyNode.Duration > 0) return false;
2789                                if (nextEmptyNode.Role_ != EmptyNode.Role.Page) return false;
2790                           
2791                        }   
2792
2793                        mRecordingSession.MarkPage();
2794                    }
2795                }
2796                else if (mState == State.Monitoring)
2797                {
2798                    return false;
2799                }
2800                else if (mState == State.Stopped)
2801                {
2802                    if (mView.ObiForm.Settings.PlayOnNavigate)
2803                    {
2804                        PlayCurrentPlaylistFromSelection();
2805                        mCurrentPlaylist.NavigateToNextPage();
2806                    }
2807                    else
2808                    {
2809                        PhraseNode destinationPhrase = mCurrentPlaylist.NextPage(
2810                            FindPlaybackStartNode(mView.Selection == null ? null : mView.Selection.Node));
2811                        mView.SelectPhraseInContentView(destinationPhrase);
2812                        mCurrentPlaylist.CurrentPhrase = destinationPhrase; //@masternewbehaviour
2813                        // assignment to current playlist should happen before selection for calling update button function through selection change event. For now update button is explicitly called, but it will be corrected in next release
2814                        UpdateButtons();
2815                    }
2816                }
2817
2818                else if (mState != State.Monitoring)
2819                {
2820                    mCurrentPlaylist.NavigateToNextPage();
2821                }
2822                return true;
2823            }
2824            return false;
2825        }
2826        private bool m_EnablePostRecordingPageRenumbering = true;
2827        /// <summary>
2828        /// Move to the next section (i.e. the first phrase of the next section)
2829        /// </summary>
2830        public bool NextSection()
2831        {
2832            if (CanNavigateNextSection)
2833            {
2834                if (mState == State.Recording)
2835                {
2836                    // first check if creation of next heading is allowed. If not, then should proceed only if the next heading is empty
2837                    if (mView.ObiForm.Settings.Audio_DisableCreationOfNewHeadingsAndPagesWhileRecording
2838                        && mRecordingSection.FollowingSection != null && mRecordingSection.FollowingSection.Duration > 0)
2839                    {
2840                        return false;
2841                    }
2842                    //mRecordingSession.AudioRecorder.TimeOfAsset
2843                    double timeOfAssetMilliseconds =
2844                   (double)mRecordingSession.AudioRecorder.RecordingPCMFormat.ConvertBytesToTime(Convert.ToInt64( mRecordingSession.AudioRecorder.CurrentDurationBytePosition)) /
2845                   Time.TIME_UNIT;
2846
2847                    if (mRecordingPhrase != null && mRecordingSession != null
2848                        && timeOfAssetMilliseconds < 250) return false;
2849                    m_EnablePostRecordingPageRenumbering = false;
2850                    bool isPlayOnSelectionChange = SelectionChangedPlaybackEnabled;
2851                    SelectionChangedPlaybackEnabled = false;
2852                    PauseRecording();
2853                    SelectionChangedPlaybackEnabled = isPlayOnSelectionChange;
2854                    m_EnablePostRecordingPageRenumbering = true;
2855                    mResumeRecordingPhrase = null;
2856
2857                    if (mRecordingSection.FollowingSection != null && mRecordingSection.FollowingSection.Duration == 0)
2858                    {
2859                        //focus to next section and start recording again
2860                        if ( mView.Selection != null )
2861                        mView.Selection = new NodeSelection(mRecordingSection.FollowingSection, mView.Selection.Control);
2862                        else if ( mRecordingSection != null )
2863                        mView.SelectFromTransportBar ( mRecordingSection , null ) ;
2864
2865                    try
2866                        {
2867                            if (MonitorContinuously) StopMonitorContinuously(); //@MonitorContinuously
2868                        SetupRecording ( Recording , false);
2869                        }
2870                    catch (System.Exception ex)
2871                        {
2872                        mView.WriteToLogFile(ex.ToString());
2873                        MessageBox.Show ( Localizer.Message ( "TransportBar_ErrorInStartingRecording" ) + "\n\n" + ex.ToString (), Localizer.Message ( "Caption_Error" ) );
2874                        if (mState == State.Monitoring || mState == State.Recording ) Stop ();
2875                        }
2876                    }
2877                    else
2878                    {
2879                        // mView.AddSection(ProjectView.WithoutRename);
2880
2881                    try
2882                        {
2883                            if (MonitorContinuously) StopMonitorContinuously(); //@MonitorContinuously
2884                        SetupRecording ( Recording, mRecordingSection, false );
2885                        }
2886                    catch (System.Exception ex)
2887                        {
2888                        mView.WriteToLogFile(ex.ToString());
2889                        MessageBox.Show ( Localizer.Message ( "TransportBar_ErrorInStartingRecording" ) + "\n\n" + ex.ToString (), Localizer.Message ( "Caption_Error" ) );
2890                        if (mState == State.Monitoring || mState == State.Recording) Stop ();
2891                        }
2892                    }
2893                }
2894                else if (mState == State.Monitoring)
2895                {
2896                    return false;
2897                }
2898                else if (mState == State.Stopped)
2899                {
2900                    if (mView.ObiForm.Settings.PlayOnNavigate)
2901                    {
2902                        PlayCurrentPlaylistFromSelection();
2903                        mCurrentPlaylist.NavigateToNextSection();
2904                    }
2905                    else
2906                    {
2907                        PhraseNode destinationPhrase = mCurrentPlaylist.NextSection(
2908                            FindPlaybackStartNode(mView.Selection == null ? null : mView.Selection.Node));
2909                        mView.SelectPhraseInContentView(destinationPhrase);
2910                        mCurrentPlaylist.CurrentPhrase = destinationPhrase; //@masternewbehaviour
2911                        // assignment to current playlist should happen before selection for calling update button function through selection change event. For now update button is explicitly called, but it will be corrected in next release
2912                        UpdateButtons();
2913                    }
2914                }
2915                else
2916                {
2917                    mCurrentPlaylist.NavigateToNextSection();
2918                }
2919                return true;
2920            }
2921            return false;
2922        }
2923
2924
2925        // Rewind/Fast forward
2926
2927        private void mRewindButton_Click(object sender, EventArgs e) { Rewind(); }
2928        private void mFastForwardButton_Click(object sender, EventArgs e) { FastForward(); }
2929
2930        /// <summary>
2931        /// Play faster.
2932        /// </summary>
2933        public void FastForward()
2934        {
2935            if (CanFastForward)
2936            {
2937                if (mState == State.Stopped || mState == State.Paused) PlayOrResume();
2938                if (mCurrentPlaylist.CurrentPhrase != null) mCurrentPlaylist.FastForward(); // explicit care required for zero phrase playlist to prevent setting of fwd/rwd rate without playback
2939
2940                if (mCurrentPlaylist.State == AudioLib.AudioPlayer.State.Playing)
2941                    mDisplayTimer.Start ();
2942            }
2943        }
2944
2945        /// <summary>
2946        /// Rewind (i.e. play faster backward)
2947        /// </summary>
2948        public void Rewind()
2949        {
2950            if (CanRewind)
2951            {
2952                if (mState == State.Stopped || mState == State.Paused) PlayOrResume();
2953                if (mCurrentPlaylist.CurrentPhrase != null) mCurrentPlaylist.Rewind(); // explicit care required for zero phrase playlist because it will set the fwd/rwd rate
2954
2955                if (mCurrentPlaylist.State == AudioLib.AudioPlayer.State.Playing)
2956                    mDisplayTimer.Start ();
2957            }
2958        }
2959
2960
2961        public bool FastPlayRateStepUp()
2962        {
2963            if (mFastPlayRateCombobox.SelectedIndex < mFastPlayRateCombobox.Items.Count - 1)
2964            {
2965                mFastPlayRateCombobox.SelectedIndex = mFastPlayRateCombobox.SelectedIndex + 1;
2966                float fastPlayFactor = GetFastPlayFactorOfCombobox () ;
2967                DetermineUseOfSoundTouch(fastPlayFactor);
2968                mCurrentPlaylist.Audioplayer.FastPlayFactor = fastPlayFactor;
2969                //mCurrentPlaylist.Audioplayer.FastPlayFactor = (float)Convert.ToDouble(mFastPlayRateCombobox.SelectedItem.ToString());
2970                return true;
2971            }
2972            return false;
2973        }
2974
2975        public bool  FastPlayRateStepDown()
2976        {
2977            if (mFastPlayRateCombobox.SelectedIndex > 0)
2978            {
2979                mFastPlayRateCombobox.SelectedIndex = mFastPlayRateCombobox.SelectedIndex - 1;
2980
2981                float fastPlayFactor = GetFastPlayFactorOfCombobox ();
2982                DetermineUseOfSoundTouch(fastPlayFactor);
2983                mCurrentPlaylist.Audioplayer.FastPlayFactor = fastPlayFactor;
2984                //mCurrentPlaylist.Audioplayer.FastPlayFactor = (float)Convert.ToDouble(mFastPlayRateCombobox.SelectedItem.ToString());
2985                return true;
2986            }
2987            return false;
2988        }
2989
2990        public bool FastPlayRateNormalise()
2991        {
2992            mFastPlayRateCombobox.SelectedIndex = 0;
2993            DetermineUseOfSoundTouch(1.0f);
2994            mCurrentPlaylist.Audioplayer.FastPlayFactor = (float)Convert.ToDouble(mFastPlayRateCombobox.SelectedItem.ToString());
2995            return true;
2996        }
2997
2998        private void mFastPlayRateComboBox_SelectionChangeCommitted(object sender, EventArgs e)
2999        {
3000            float fastPlayFactor = GetFastPlayFactorOfCombobox ();
3001            DetermineUseOfSoundTouch(fastPlayFactor);
3002            mCurrentPlaylist.Audioplayer.FastPlayFactor = fastPlayFactor;
3003            //mCurrentPlaylist.Audioplayer.FastPlayFactor = (float)Convert.ToDouble(mFastPlayRateCombobox.SelectedItem.ToString());
3004        }
3005
3006        private float GetFastPlayFactorOfCombobox()
3007        {
3008            float fastPlayFactor = 0;
3009            float.TryParse(mFastPlayRateCombobox.SelectedItem.ToString(), out fastPlayFactor);
3010            if (fastPlayFactor == 0)
3011            {
3012                fastPlayFactor = float.Parse(mFastPlayRateCombobox.SelectedItem.ToString(), System.Globalization.CultureInfo.CreateSpecificCulture("en-EN"));
3013            }
3014            return fastPlayFactor;
3015        }
3016
3017        public bool FastPlayNormaliseWithLapseBack()
3018        {
3019            m_ElapseBackInterval = mView.ObiForm.Settings.Audio_ElapseBackTimeInMilliseconds;
3020            // work around to handle special nudge condition of preview: this should be implemented universally after 2.0 release
3021            if (mCurrentPlaylist != null && mView.Selection is AudioSelection && mCurrentPlaylist is PreviewPlaylist && CurrentState == State.Paused) Stop();
3022            if (IsPlayerActive)
3023            {
3024                // if current playback phrase is not selected, hthen select it.
3025                if (mView.Selection == null
3026                    || (CurrentPlaylist.CurrentPhrase != null &&  CurrentPlaylist.CurrentPhrase != mView.Selection.Node))
3027                {
3028                    mView.SelectFromTransportBar(mCurrentPlaylist.CurrentPhrase, null);
3029                }
3030
3031
3032                if (((IsPaused && mCurrentPlaylist.CurrentTimeInAsset <= 10) || (mView.ObiForm.Settings.PlayOnNavigate && CurrentState == State.Playing && mCurrentPlaylist.CurrentTimeInAsset <= 800))
3033                    && (mView.Selection.Node.PrecedingNode is PhraseNode || mView.Selection.Node.PrecedingNode is EmptyNode) && !mView.IsZoomWaveformActive)
3034                {
3035                    if (mView.ObiForm.Settings.PlayOnNavigate && CurrentState == State.Playing && mCurrentPlaylist.CurrentTimeInAsset <= 800) Pause();
3036                    LapseBackCursor();
3037                    return true;
3038                }
3039                else
3040                {
3041                    DetermineUseOfSoundTouch(1.0f);
3042                    mCurrentPlaylist.FastPlayNormaliseWithLapseBack(m_ElapseBackInterval);
3043                    mFastPlayRateCombobox.SelectedIndex = 0;
3044                    UpdateTimeDisplay();
3045                    if (mCurrentPlaylist.CurrentTimeInAsset <= 10)
3046                    {
3047                        this.Pause();
3048                        PhraseNode prevPhraseNode = mCurrentPlaylist.PrevPhrase(mCurrentPlaylist.CurrentPhrase);
3049                        if (mView.Selection != null && mView.Selection.Node is PhraseNode)
3050                        {
3051                            if (prevPhraseNode != null)
3052                            {
3053                                LapseBackCursor(); 
3054                                this.PlayOrResume();
3055                                return true;
3056                            }
3057                            else
3058                            {
3059                                LapseBackCursor();
3060                                return true;
3061                            }
3062                        }
3063                    }
3064 
3065                    if (CurrentPlaylist != null) mView.UpdateCursorPosition(mCurrentPlaylist.CurrentTimeInAsset);
3066                    if (mView.Selection is AudioSelection)
3067                    {
3068                        if (((AudioSelection)mView.Selection).AudioRange.HasCursor)
3069                        {
3070                            if (((AudioSelection)mView.Selection).AudioRange.CursorTime != mCurrentPlaylist.CurrentTimeInAsset)
3071                            {
3072                                ((AudioSelection)mView.Selection).AudioRange.CursorTime = mCurrentPlaylist.CurrentTimeInAsset;
3073                            }
3074
3075                        }
3076                    }
3077                    return true;
3078                }
3079            }
3080            else if (CurrentState == State.Stopped && mView.Selection != null && mView.Selection.Node is PhraseNode)
3081            {
3082                LapseBackCursor();
3083
3084                return true;
3085            }
3086            return false;
3087        }
3088
3089        public bool StepForward()
3090        {
3091            m_ElapseBackInterval = mView.ObiForm.Settings.Audio_ElapseBackTimeInMilliseconds;
3092            // work around to handle special nudge condition of preview: this should be implemented universally after 2.0 release
3093            if (mCurrentPlaylist != null && mView.Selection is AudioSelection && mCurrentPlaylist is PreviewPlaylist && CurrentState == State.Paused) Stop();
3094            if (IsPlayerActive)
3095            {
3096
3097                if ((IsPaused || (mView.ObiForm.Settings.PlayOnNavigate && CurrentState == State.Playing ))
3098                    && (mView.Selection.Node.FollowingNode is PhraseNode || mView.Selection.Node.FollowingNode is EmptyNode) && (mView.Selection.Node.Parent == mView.Selection.Node.FollowingNode.Parent) && (mCurrentPlaylist.CurrentTimeInAsset >= (mView.Selection.Node.Duration - m_ElapseBackInterval)) && !mView.IsZoomWaveformActive)
3099                {
3100                    if (mView.ObiForm.Settings.PlayOnNavigate && CurrentState == State.Playing) Pause();
3101                    StepForwardCursor();
3102                    return true;
3103                }
3104                else
3105                {
3106                    //DetermineUseOfSoundTouch(1.0f);
3107                    mCurrentPlaylist.StepForward(m_ElapseBackInterval, mCurrentPlaylist.CurrentPhrase != null ? mCurrentPlaylist.CurrentPhrase.Duration : mView.Selection.Node.Duration);
3108                   
3109                    UpdateTimeDisplay();
3110                    if (CurrentPlaylist != null)
3111                    {
3112                        mView.UpdateCursorPosition(mCurrentPlaylist.CurrentTimeInAsset);                       
3113                    }
3114                    if (mView.Selection is AudioSelection)
3115                    {
3116                        if (((AudioSelection)mView.Selection).AudioRange.HasCursor)
3117                        {
3118                            if (((AudioSelection)mView.Selection).AudioRange.CursorTime != mCurrentPlaylist.CurrentTimeInAsset)
3119                            {
3120                                ((AudioSelection)mView.Selection).AudioRange.CursorTime = mCurrentPlaylist.CurrentTimeInAsset;
3121                            }
3122
3123                        }
3124                    }
3125                    return true;
3126                }
3127            }
3128            else if (CurrentState == State.Stopped && mView.Selection != null && mView.Selection.Node is PhraseNode)
3129            {
3130                StepForwardCursor();
3131
3132                return true;
3133            }
3134            return false;
3135        }
3136
3137        private void LapseBackCursor()
3138        {
3139            if (IsPaused)
3140            {
3141                double time = mCurrentPlaylist.CurrentTimeInAsset;
3142               
3143                if (mView.Selection.Node.PrecedingNode != null && mView.Selection.Node.PrecedingNode is PhraseNode)
3144                {
3145                    Stop();
3146                   // mView.ClearCursor();
3147                    mView.Selection = new NodeSelection(mView.Selection.Node.PrecedingNode, mView.Selection.Control);
3148                   
3149                    AudioRange range = new AudioRange(mView.Selection.Node.Duration);
3150                    mView.Selection = new AudioSelection((PhraseNode)mView.Selection.Node, mView.Selection.Control, range);
3151                    if (mView.ObiForm.Settings.Audio_AudioClues)
3152                    {
3153                        System.Media.SystemSounds.Asterisk.Play();
3154                    }
3155                }
3156            }
3157            if (mView.Selection is AudioSelection)
3158            {
3159                double time = ((AudioSelection)mView.Selection).AudioRange.CursorTime;
3160
3161                if (time < 1 && !mView.IsZoomWaveformActive && ((mView.Selection.Node.PrecedingNode is PhraseNode) || (mView.Selection.Node.PrecedingNode is EmptyNode)))
3162                {
3163                    ObiNode preceedingNode = mView.Selection.Node.PrecedingNode;
3164                    mView.Selection = new NodeSelection(preceedingNode, mView.Selection.Control);
3165                    AudioRange range = new AudioRange(mView.Selection.Node.Duration);
3166                    while (mView.Selection.Node is EmptyNode && !(mView.Selection.Node is PhraseNode))
3167                    {
3168                        preceedingNode = mView.Selection.Node.PrecedingNode;
3169                        mView.Selection = new NodeSelection(preceedingNode, mView.Selection.Control);
3170                        range = new AudioRange(mView.Selection.Node.Duration);
3171                    }
3172                    Console.WriteLine("Current time in Asset {0}", mCurrentPlaylist.CurrentTimeInAsset);
3173                    mView.Selection = new AudioSelection((PhraseNode)mView.Selection.Node, mView.Selection.Control, range);
3174                    time = ((AudioSelection)mView.Selection).AudioRange.CursorTime;
3175                    if (mView.ObiForm.Settings.Audio_AudioClues)
3176                    {
3177                        System.Media.SystemSounds.Asterisk.Play();
3178                    }
3179                }
3180
3181                time = time - m_ElapseBackInterval >= 0 ? time - m_ElapseBackInterval : 0;
3182
3183                mView.Selection = new AudioSelection((PhraseNode)mView.Selection.Node, mView.Selection.Control,
3184                    new AudioRange(time));
3185            }
3186            else if(!IsPaused)
3187            {
3188                mView.Selection = new AudioSelection((PhraseNode)mView.Selection.Node, mView.Selection.Control,
3189                    new AudioRange(((PhraseNode)mView.Selection.EmptyNodeForSelection).Duration - m_ElapseBackInterval));
3190            }
3191        }
3192        private void StepForwardCursor()
3193        {
3194            bool flag = false;
3195            if (IsPaused)
3196            {
3197                double time = mCurrentPlaylist.CurrentTimeInAsset;
3198
3199                if (mView.Selection.Node.FollowingNode != null && mView.Selection.Node.FollowingNode is PhraseNode)
3200                {
3201                    Stop();
3202                    // mView.ClearCursor();
3203                    double diff = mView.Selection.Node.Duration - time;
3204                    diff = m_ElapseBackInterval - diff;
3205                    mView.Selection = new NodeSelection(mView.Selection.Node.FollowingNode, mView.Selection.Control);
3206
3207                    AudioRange range = new AudioRange(diff);
3208                    mView.Selection = new AudioSelection((PhraseNode)mView.Selection.Node, mView.Selection.Control, range);
3209                    flag = true;
3210                    if (mView.ObiForm.Settings.Audio_AudioClues)
3211                    {
3212                        System.Media.SystemSounds.Asterisk.Play();
3213                    }
3214                }
3215            }
3216            if (mView.Selection is AudioSelection)
3217            {
3218                double time = ((AudioSelection)mView.Selection).AudioRange.CursorTime;
3219
3220                if ((time + m_ElapseBackInterval) >= mView.Selection.Node.Duration && !mView.IsZoomWaveformActive && ((mView.Selection.Node.FollowingNode is PhraseNode) || (mView.Selection.Node.FollowingNode is EmptyNode)) && (mView.Selection.Node.Parent==mView.Selection.Node.FollowingNode.Parent))
3221                {
3222                    ObiNode followingNode = mView.Selection.Node.FollowingNode;
3223                    double diff = mView.Selection.Node.Duration - time;
3224                    diff = m_ElapseBackInterval - diff;
3225                    mView.Selection = new NodeSelection(followingNode, mView.Selection.Control);
3226                    AudioRange range = new AudioRange(diff);
3227                    while (mView.Selection.Node is EmptyNode && !(mView.Selection.Node is PhraseNode))
3228                    {
3229                        followingNode = mView.Selection.Node.FollowingNode;
3230                        mView.Selection = new NodeSelection(followingNode, mView.Selection.Control);
3231                        range = new AudioRange(diff);
3232                    }
3233                    mView.Selection = new AudioSelection((PhraseNode)mView.Selection.Node, mView.Selection.Control, range);
3234                    time = ((AudioSelection)mView.Selection).AudioRange.CursorTime;
3235                    if (time > mView.Selection.Node.Duration)
3236                    {
3237                        time = mView.Selection.Node.Duration;
3238                    }
3239                    //mView.UpdateCursorPosition(time);
3240                    if (mView.ObiForm.Settings.Audio_AudioClues)
3241                    {
3242                        System.Media.SystemSounds.Asterisk.Play();
3243                    }
3244                }
3245                else if (((time + m_ElapseBackInterval) <= mView.Selection.Node.Duration) && !flag)
3246                {
3247                    time = time + m_ElapseBackInterval;
3248                }
3249                else if(!flag)
3250                {
3251                    time = mView.Selection.Node.Duration;
3252                }
3253
3254                mView.Selection = new AudioSelection((PhraseNode)mView.Selection.Node, mView.Selection.Control,
3255                    new AudioRange(time));
3256            }
3257            else if (!IsPaused)
3258            {             
3259                mView.Selection = new AudioSelection((PhraseNode)mView.Selection.Node, mView.Selection.Control,
3260                    new AudioRange(((PhraseNode)mView.Selection.EmptyNodeForSelection).Duration));
3261            }
3262        }
3263        /// <summary>
3264        /// sound touch is enabled if fast play is to be activated else it is restored to original DX
3265        /// </summary>
3266        /// <param name="fastPlayFactor"></param>
3267        private void DetermineUseOfSoundTouch(float fastPlayFactor)
3268        {
3269            if (mPlayer == null) return;
3270            //if (mView.Presentation != null &&  mView.Presentation.MediaDataManager.DefaultPCMFormat.Data.NumberOfChannels == 1
3271            if (mView.ObiForm != null
3272                && mView.ObiForm.Settings.Audio_FastPlayWithoutPitchChange
3273                && fastPlayFactor > 1.0f
3274                && !mPlayer.UseSoundTouch)
3275            {
3276                mPlayer.UseSoundTouch = true;
3277            }
3278            else if (mPlayer.UseSoundTouch
3279                && (!mView.ObiForm.Settings.Audio_FastPlayWithoutPitchChange ||  fastPlayFactor <= 1.0f))
3280            {
3281                mPlayer.UseSoundTouch = false;
3282                Console.WriteLine("use sound touch " + mPlayer.UseSoundTouch);
3283            }
3284        }
3285
3286        public void ResetFastPlayForPreferencesChange()
3287        {
3288            FastPlayRateNormalise();
3289            if (mFastPlayRateCombobox.Items.Count < 8)
3290            {
3291                System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(TransportBar));
3292                resources.ApplyResources(this.mFastPlayRateCombobox, "mFastPlayRateCombobox");
3293                mFastPlayRateCombobox.Items.Clear();
3294                this.mFastPlayRateCombobox.Items.AddRange(new object[] {
3295            resources.GetString("mFastPlayRateCombobox.Items"),
3296            resources.GetString("mFastPlayRateCombobox.Items1"),
3297            resources.GetString("mFastPlayRateCombobox.Items2"),
3298            resources.GetString("mFastPlayRateCombobox.Items3"),
3299            resources.GetString("mFastPlayRateCombobox.Items4"),
3300                resources.GetString("mFastPlayRateCombobox.Items5"),
3301                resources.GetString("mFastPlayRateCombobox.Items6"),
3302            resources.GetString("mFastPlayRateCombobox.Items7")});
3303            }
3304           
3305                if (mFastPlayRateCombobox.Items.Count == 8 &&  mView.ObiForm.Settings.Audio_FastPlayWithoutPitchChange)
3306                {
3307                    mFastPlayRateCombobox.Items.RemoveAt(1);
3308                    mFastPlayRateCombobox.Items.RemoveAt(1);
3309                }
3310           
3311        }
3312        // nudge selection
3313        public static readonly bool Forward = true;         // nudge forward
3314        public static readonly bool Backward = false;       // nudge backward
3315
3316        // Nudge selection forward or backward.
3317        public bool Nudge(bool forward)
3318        {
3319        bool PlaybackOnSelectionEnabledStatus = SelectionChangedPlaybackEnabled;
3320        SelectionChangedPlaybackEnabled = false;
3321            double nudge = mView.ObiForm.Settings.Audio_NudgeTimeMs * (forward ? 1 : -1);
3322           
3323            if (!IsRecorderActive && (mState == State.Paused || m_IsPreviewing))
3324            {
3325                                double time = mCurrentPlaylist.CurrentTimeInAsset + nudge;
3326                if (m_IsPreviewing )
3327                    time = ((PreviewPlaylist)mCurrentPlaylist).RevertTime + nudge;
3328
3329                if (time >= 0.0 && time < mCurrentPlaylist.CurrentPhrase.Duration)
3330                {
3331                    // Move selection to audio cursor, stop, and nudge the selection.
3332                    PhraseNode currentlyPlayingNode = mCurrentPlaylist.CurrentPhrase;
3333                    Stop();
3334
3335                    if (mCurrentPlaylist is PreviewPlaylist)
3336                        ((PreviewPlaylist)mCurrentPlaylist).TriggerEndOfPreviewPlaylist ( time);
3337
3338                    mView.SelectedBlockNode = currentlyPlayingNode;
3339                    mView.Selection = new AudioSelection((PhraseNode)mView.Selection.Node, mView.Selection.Control,
3340                        new AudioRange(time));
3341
3342                    if (mView.ObiForm.Settings.PlayOnNavigate) Preview(true, false);
3343                   
3344                    SelectionChangedPlaybackEnabled = PlaybackOnSelectionEnabledStatus;
3345                    return true;
3346                }
3347            }
3348            else if (mState == State.Stopped)
3349            {
3350                AudioSelection s = mView.Selection as AudioSelection;
3351                if (s != null)
3352                {
3353                    double time = (s.AudioRange.HasCursor ? s.AudioRange.CursorTime : s.AudioRange.SelectionBeginTime) + nudge;
3354                    if (time >= 0.0 && time < ((PhraseNode)s.Node).Duration)
3355                    {
3356                        mView.Selection = new AudioSelection((PhraseNode)s.Node, mView.Selection.Control, new AudioRange(time));
3357                        if (mView.ObiForm.Settings.PlayOnNavigate) Preview(true, false);
3358                        SelectionChangedPlaybackEnabled = PlaybackOnSelectionEnabledStatus;
3359                        return true;
3360                    }
3361                }
3362            }
3363        SelectionChangedPlaybackEnabled = PlaybackOnSelectionEnabledStatus ;
3364            return false;
3365        }
3366
3367        public enum NudgeSelection { ExpandAtLeft, ContractAtLeft, ExpandAtRight, ContractAtRight } ;
3368
3369        public bool NudgeSelectedAudio(NudgeSelection nudgeDirection)
3370        {
3371            if (mView.Selection == null || !(mView.Selection is AudioSelection)) return false;
3372
3373            double beginTime = ((AudioSelection)mView.Selection).AudioRange.SelectionBeginTime;
3374            double endTime = ((AudioSelection)mView.Selection).AudioRange.SelectionEndTime;
3375            PhraseNode phrase = (PhraseNode)mView.Selection.Node ;
3376            if (beginTime == 0 || endTime == phrase.Duration) return false;
3377
3378            double nudgeDuration = mView.ObiForm.Settings.Audio_NudgeTimeMs ;
3379
3380            if (nudgeDirection == NudgeSelection.ExpandAtLeft)
3381            {
3382                beginTime = beginTime - nudgeDuration;
3383                if (beginTime < 0) beginTime = 0;
3384            }
3385            else if (nudgeDirection == NudgeSelection.ContractAtLeft)
3386            {
3387                beginTime = beginTime + nudgeDuration;
3388            }
3389            else if (nudgeDirection == NudgeSelection.ExpandAtRight)
3390            {
3391                endTime = endTime + nudgeDuration;
3392                if (endTime > phrase.Duration) endTime = phrase.Duration;
3393            }
3394            else if (nudgeDirection == NudgeSelection.ContractAtRight)
3395            {
3396                endTime = endTime - nudgeDuration;
3397            }
3398            if (endTime < beginTime) return false;
3399
3400            this.SelectionChangedPlaybackEnabled = false;
3401            mView.Selection = new AudioSelection (phrase,mView.Selection.Control, new AudioRange(beginTime,endTime)) ;
3402            SelectionChangedPlaybackEnabled = true;
3403            if (mView.ObiForm.Settings.PlayOnNavigate ) PreviewAudioSelection(); 
3404            return true ;
3405        }
3406
3407        // preview playback functions
3408        public static readonly bool From = true;
3409        public static readonly bool Upto = false;
3410        public static readonly bool UseSelection = true;
3411        public static readonly bool UseAudioCursor = false;
3412
3413        /// <summary>
3414        /// Preview from or upt the current position; use the audio cursor, the selection cursor,
3415        /// or the beginning position of a selection. If the useSelection flag is set, use the
3416        /// selection position; otherwise, use the audio cursor position (if set.)
3417        /// </summary>
3418        public bool Preview(bool from, bool useSelection)
3419        {
3420            if (!IsRecorderActive && PreviewDuration > 0)
3421            {
3422                if ((mState == State.Paused || mState == State.Playing) && !useSelection )
3423                {
3424                   
3425
3426                    PhraseNode node = mCurrentPlaylist is PreviewPlaylist ? ((PreviewPlaylist)mCurrentPlaylist).RevertPhrase: 
3427                        mCurrentPlaylist.CurrentPhrase;
3428                    double time = mCurrentPlaylist is PreviewPlaylist ?
3429                        ((PreviewPlaylist)mCurrentPlaylist).RevertTime : mCurrentPlaylist.CurrentTimeInAsset;
3430                    if (mState == State.Playing ||  mState == State.Paused) Stop ();
3431                    CreateLocalPlaylistForPreview( node , time, useSelection);
3432                    mCurrentPlaylist.CurrentTimeInAsset = time;
3433                    PlayPreview(mCurrentPlaylist.CurrentPhrase, time - (from ? 0.0 : PreviewDuration), PreviewDuration, from);
3434                    return true;
3435                }
3436                else if (mView.Selection is AudioSelection)
3437                {
3438                if (mState == State.Playing) Pause ();
3439                if (!(mView.Selection is AudioSelection)) return false;
3440
3441                                    AudioSelection s = (AudioSelection)mView.Selection;
3442                                    if (mState == State.Stopped && s.AudioRange != null && !s.AudioRange.HasCursor && !useSelection) 
3443                                        return false ;
3444
3445                                    double time = (s.AudioRange.HasCursor || !useSelection ? s.AudioRange.CursorTime : s.AudioRange.SelectionBeginTime);
3446                                   
3447
3448
3449                    if (mState == State.Playing || mState == State.Paused ) Stop ();
3450                    CreateLocalPlaylistForPreview ( (PhraseNode)s.Node, time, true );
3451
3452                    time = from ? (s.AudioRange.HasCursor || !useSelection ? s.AudioRange.CursorTime : s.AudioRange.SelectionBeginTime) :
3453                        (s.AudioRange.HasCursor ? s.AudioRange.CursorTime : s.AudioRange.SelectionEndTime) - PreviewDuration;
3454                   
3455                    PlayPreview((PhraseNode)s.Node, time, PreviewDuration, from);
3456                   
3457                    return true;
3458                }
3459            }
3460            return false;
3461        }
3462
3463        /// <summary>
3464        /// Preview the audio selection.
3465        /// </summary>
3466        public bool PreviewAudioSelection()
3467        {
3468            if (CanPreviewAudioSelection)
3469            {
3470                AudioSelection s = (AudioSelection)mView.Selection;
3471               
3472                if (mState == State.Playing  || mState == State.Paused) Stop ();
3473                CreateLocalPlaylistForPreview( (PhraseNode)s.Node , s.AudioRange.SelectionBeginTime, true);
3474                PlayPreview((PhraseNode)s.Node, s.AudioRange.SelectionBeginTime,
3475                    s.AudioRange.SelectionEndTime - s.AudioRange.SelectionBeginTime, true);
3476                return true;
3477            }
3478            return false;
3479        }
3480
3481        private PhraseNode m_PreviewPhraseNode;
3482        private double mAfterPreviewRestoreTime;
3483        private double m_AfterPreviewRestoreEndTime;
3484        private bool m_IsPreviewing;
3485
3486
3487        // Preview from a given time for a given duration inside a phrase.
3488        private void PlayPreview(PhraseNode phrase, double from, double duration, bool forward)
3489        {
3490            urakawa.media.data.audio.AudioMediaData audioData = phrase.Audio.AudioMediaData;
3491            //if (from < 0.0)
3492            //{
3493                //duration += from;
3494                //from = 0.0;
3495            //}
3496            double end = from + duration;
3497            if (end > audioData.AudioDuration.AsMilliseconds)
3498                end = audioData.AudioDuration.AsMilliseconds;
3499
3500            if (from >= end) return;
3501            //mPlayer.PlayPreview(audioData, from, end, forward ? from : end);
3502            m_PreviewPhraseNode = mCurrentPlaylist.CurrentPhrase;
3503            m_AfterPreviewRestoreEndTime =  mAfterPreviewRestoreTime = forward ? from : end;
3504           
3505            if (mView.Selection != null && mView.Selection is AudioSelection &&   !((AudioSelection)mView.Selection).AudioRange.HasCursor)
3506                m_AfterPreviewRestoreEndTime = ((AudioSelection)mView.Selection).AudioRange.SelectionEndTime;
3507            if (mCurrentPlaylist.State != AudioLib.AudioPlayer.State.Playing) 
3508                        mCurrentPlaylist.Play(from, end);
3509           
3510            m_IsPreviewing = true;
3511        }
3512       
3513
3514        private void PostPreviewRestore()
3515        {
3516        bool playOnSelectionStatus = SelectionChangedPlaybackEnabled;
3517        SelectionChangedPlaybackEnabled = false;
3518                                        if (mView.Selection != null &&
3519                    mView.Selection.Node == m_PreviewPhraseNode)
3520                {
3521                if (mAfterPreviewRestoreTime == m_AfterPreviewRestoreEndTime)
3522                    {
3523                    mView.UpdateCursorPosition ( mAfterPreviewRestoreTime );
3524                    //mView.Selection = new AudioSelection(m_PreviewPhraseNode, mView.Selection.Control, new AudioRange(m_AfterPreviewRestoreTime));
3525                    }
3526                else
3527                    {
3528                                        //mView.Selection = new AudioSelection ( m_PreviewPhraseNode, mView.Selection.Control, new AudioRange ( mAfterPreviewRestoreTime, m_AfterPreviewRestoreEndTime ) );
3529                    }
3530                                                                                                                                                            }
3531                m_IsPreviewing = false;
3532            // Aug 12, 2015 check added for kind of playlist. The pause here is to ensure that playback does not starts due to some event, when play on navigate is checked.
3533                if (mState == State.Playing && !(mCurrentPlaylist is PreviewPlaylist )) Pause();
3534
3535                SelectionChangedPlaybackEnabled = playOnSelectionStatus ;
3536                        }
3537
3538
3539        #region undoable recording
3540
3541
3542
3543        System.ComponentModel.BackgroundWorker m_PreviewBeforeRecordingWorker = null;
3544        /// <summary>
3545        /// Start recording directly without going through listening
3546        /// </summary>
3547        public void StartRecordingDirectly(bool isPreviewBeforeRecording)
3548        {
3549            if (isPreviewBeforeRecording && mView.ObiForm.Settings.Audio_AllowOverwrite
3550                && m_PreviewBeforeRecordingWorker != null && m_PreviewBeforeRecordingWorker.IsBusy)
3551            {
3552                return;
3553            }
3554            if (mView.IsZoomWaveformActive)
3555            {
3556                return;
3557            }
3558
3559            if (isPreviewBeforeRecording && mCurrentPlaylist.Audioplayer.PlaybackFwdRwdRate != 0)
3560            {
3561                return;
3562            }
3563            if (mView.ObiForm.Settings.Audio_AllowOverwrite && CurrentState == State.Playing) //@recordFromPlay
3564            {
3565                Pause();
3566                if (isPreviewBeforeRecording)
3567                {
3568                if (mView.Selection == null || !(mView.Selection.Node is EmptyNode) || mView.Selection.Node != mCurrentPlaylist.CurrentPhrase) return;
3569            }
3570            }
3571
3572            // special handling if the time is at 0 s. This code should be removed by doing adequate improvements in preview playlist.
3573            if (isPreviewBeforeRecording && mView.Selection != null
3574                && mView.ObiForm.Settings.Audio_AllowOverwrite)
3575            {
3576                double time = -1;
3577
3578                time = IsPlayerActive ? mCurrentPlaylist.CurrentTimeInAsset :
3579                    mView.Selection is AudioSelection ?
3580                    (((AudioSelection)mView.Selection).AudioRange.HasCursor ? ((AudioSelection)mView.Selection).AudioRange.CursorTime : ((AudioSelection)mView.Selection).AudioRange.SelectionBeginTime) :
3581                    -1;
3582                // If the preceeding phrase is in the same section then place the cursor at end of preceeding phrase
3583                // if preceeding phrase is not appropriate then select the strip index, start recording and  and return
3584                if (time == 0)
3585                {
3586                    ObiNode proceedingNode = mView.Selection.Node.PrecedingNode;
3587                    if (proceedingNode != null 
3588                        && proceedingNode.Parent == mView.Selection.Node.Parent
3589                        && proceedingNode is EmptyNode && ((EmptyNode)proceedingNode).Duration > 0)
3590                    {
3591                        mView.Selection = new AudioSelection((PhraseNode)proceedingNode, mView.Selection.Control,
3592                           new AudioRange(proceedingNode.Duration));
3593                       
3594                    }
3595                    else
3596                    {
3597                        mView.Selection = new StripIndexSelection(mView.Selection.Node.ParentAs<SectionNode>(), mView.Selection.Control, mView.Selection.Node.Index);
3598                        StartRecordingDirectly_Internal(true);
3599                        return;
3600                    }
3601                }
3602            }
3603
3604            bool Status_SelectionChangedPlaybackEnabled = SelectionChangedPlaybackEnabled;
3605            if (isPreviewBeforeRecording && mView.ObiForm.Settings.Audio_AllowOverwrite
3606               && ((CurrentState == State.Paused && !(mView.Selection is AudioSelection)) || (mView.Selection != null && mView.Selection is AudioSelection && ((AudioSelection)mView.Selection).AudioRange.HasCursor)))
3607            {
3608                // first delete the subsequent phrases in the section
3609                try
3610                {
3611                    if (SelectionChangedPlaybackEnabled) SelectionChangedPlaybackEnabled = false;
3612                    EmptyNode selectedNode = mView.Selection != null && mView.Selection.Node is EmptyNode ? (EmptyNode)mView.Selection.Node : null;
3613                    NodeSelection currentSelection = mView.Selection;
3614                    double time = -1;
3615                    if (selectedNode != null)
3616                    {
3617                        time = IsPlayerActive ? mCurrentPlaylist.CurrentTimeInAsset :
3618                            mView.Selection is AudioSelection ?
3619                            (((AudioSelection)mView.Selection).AudioRange.HasCursor ? ((AudioSelection)mView.Selection).AudioRange.CursorTime : ((AudioSelection)mView.Selection).AudioRange.SelectionBeginTime) :
3620                            -1;
3621                       
3622                        // Specific request of SBS: restore blue audio selection even if in pause state, so that blue cursor is visible after undo.
3623                        if (time >= 0 && mView.ObiForm.Settings.Audio_EnsureCursorVisibilityInUndoOfSplitRecording&& !(mView is AudioSelection))
3624                        {
3625                            mView.Selection = new AudioSelection((PhraseNode)selectedNode, currentSelection.Control,
3626                               new AudioRange(time));
3627                        }
3628                    }
3629
3630                    if (selectedNode != null && selectedNode is PhraseNode && selectedNode.Index < selectedNode.ParentAs<SectionNode>().PhraseChildCount - 1)
3631                    {
3632                        SectionNode section = selectedNode.ParentAs<SectionNode>();
3633                        Command deleteFollowingCmd = mView.GetDeleteRangeOfPhrasesInSectionCommand(
3634                            section, section.PhraseChild(selectedNode.Index + 1), section.PhraseChild(section.PhraseChildCount - 1),
3635                            mView.ObiForm.Settings.Audio_PreservePagesWhileRecordOverSubsequentAudio, PhraseNode.Role.Page);
3636                        mView.Presentation.Do(deleteFollowingCmd);
3637                    }
3638                    else
3639                    {
3640                        // selection is automatically saved if delete command is executed. But it should also be saved if delete command is bypassed.
3641                        Commands.UpdateSelection selectionUpdateCmd = new Obi.Commands.UpdateSelection(mView, mView.Selection);
3642                        mView.Presentation.Do(selectionUpdateCmd);
3643                    }
3644                    if (time >= 0)
3645                    {
3646                        mView.Selection = new AudioSelection((PhraseNode)selectedNode, currentSelection.Control,
3647                           new AudioRange(time));
3648                    }
3649                }
3650                catch (System.Exception ex)
3651                {
3652                    mView.WriteToLogFile(ex.ToString());
3653                    MessageBox.Show(ex.ToString());
3654                }
3655                NodeSelection prevSelection = mView.Selection;
3656                m_PreviewBeforeRecordingWorker = new System.ComponentModel.BackgroundWorker();
3657                m_PreviewBeforeRecordingWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(delegate(object sender, System.ComponentModel.DoWorkEventArgs e)
3658                {
3659                    m_PreviewBeforeRecordingActive = true;
3660                   
3661                    double time = IsPlayerActive ? mCurrentPlaylist.CurrentTimeInAsset :
3662                            mView.Selection is AudioSelection ?
3663                            (((AudioSelection)mView.Selection).AudioRange.HasCursor ? ((AudioSelection)mView.Selection).AudioRange.CursorTime : ((AudioSelection)mView.Selection).AudioRange.SelectionBeginTime) :
3664                            -1;
3665                    if (time > 0)
3666                    {
3667                        Preview(Upto, IsPlayerActive ? UseAudioCursor : UseSelection);
3668                        int interval = 50;
3669                        for (int i = 0; i < (PreviewDuration * 2) / interval; i++)
3670                        {
3671                            if (mCurrentPlaylist is PreviewPlaylist && ((PreviewPlaylist)mCurrentPlaylist).IsPreviewComplete)
3672                            {
3673                                //System.Media.SystemSounds.Asterisk.Play();
3674                                Console.WriteLine(i);
3675                                break;
3676                            }
3677                            Thread.Sleep(interval);
3678                        }
3679                    }
3680                    //if (CurrentState == State.Paused && mCurrentPlaylist is PreviewPlaylist && ((PreviewPlaylist)mCurrentPlaylist).RevertTime == 0
3681                        //&& ((PreviewPlaylist)mCurrentPlaylist).RevertPhrase != mCurrentPlaylist.CurrentPhrase)
3682                    //{
3683                        //mCurrentPlaylist.CurrentPhrase = ((PreviewPlaylist)mCurrentPlaylist).RevertPhrase;
3684                    //}
3685                });
3686                m_PreviewBeforeRecordingWorker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(delegate(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
3687                {
3688                    m_PreviewBeforeRecordingActive = false;
3689                    if (CurrentState == State.Paused)
3690                    {
3691                        if (prevSelection.Node == mView.Selection.Node)
3692                        {
3693                            if (mResumeRecordingPhrase != null) mResumeRecordingPhrase = null;
3694                            if (mView.ObiForm.Settings.Audio_ColorFlickerPreviewBeforeRecording) mView.ResetColorAfterColorFlickering();
3695
3696                            StartRecordingDirectly_Internal(true);
3697                        }
3698                        else
3699                        {
3700                            if (mView.ObiForm.Settings.Audio_ColorFlickerPreviewBeforeRecording) mView.ResetColorAfterColorFlickering();
3701                            if (CurrentState == State.Paused) Stop();
3702                            MessageBox.Show(Localizer.Message("PreviewBeforeRecording_SelectionChanged"), Localizer.Message("Caption_Information"), MessageBoxButtons.OK, MessageBoxIcon.Stop);
3703                        }
3704                    }
3705                    if (SelectionChangedPlaybackEnabled != Status_SelectionChangedPlaybackEnabled)
3706                        SelectionChangedPlaybackEnabled = Status_SelectionChangedPlaybackEnabled;
3707                   
3708                });
3709                m_PreviewBeforeRecordingWorker.RunWorkerAsync();
3710               
3711            }
3712            else
3713            {
3714                StartRecordingDirectly_Internal(false);
3715            }
3716           
3717        }
3718
3719        private void StartRecordingDirectly_Internal(bool deleteFollowingPhrases)
3720    {
3721            if (mRecordingSession == null
3722                && mCurrentPlaylist.Audioplayer.CurrentState != AudioLib.AudioPlayer.State.Playing
3723                &&    !IsMetadataSelected &&  ( mView.Selection == null || !(mView.Selection is TextSelection)))
3724                {
3725                try
3726                    {
3727                        if (MonitorContinuously) StopMonitorContinuously(); //@MonitorContinuously
3728                    SetupRecording ( Recording, deleteFollowingPhrases );
3729                    }
3730                catch (System.Exception ex)
3731                    {
3732                    MessageBox.Show ( Localizer.Message ( "TransportBar_ErrorInStartingRecording" ) + "\n\n" + ex.ToString (), Localizer.Message ( "Caption_Error" ) );
3733                    if (mState == State.Monitoring || mState == State.Recording) Stop ();
3734                    }
3735               
3736                }
3737        }
3738
3739
3740
3741
3742        // Stop recording
3743        private void StopRecording()
3744        {
3745            if (mRecordingSession != null && 
3746                (mRecordingSession.AudioRecorder.CurrentState == AudioLib.AudioRecorder.State.Monitoring ||
3747                mRecordingSession.AudioRecorder.CurrentState == AudioLib.AudioRecorder.State.Recording))
3748            {
3749                bool IsDataMissingException = false;
3750                bool wasMonitoring = mRecordingSession.AudioRecorder.CurrentState == AudioLib.AudioRecorder.State.Monitoring;
3751                mVUMeterPanel.BeepEnable = false;
3752                List<PhraseNode> listOfRecordedPhrases = new List<PhraseNode>();
3753                EmptyNode firstRecordedPage = null;
3754                try
3755                {
3756                    mRecordingSession.Stop();
3757
3758
3759                    if (mRecordingSection != null) ///@MonitorContinuously , if block inserted to bypass the procedure of assigning assets
3760                    {
3761                        // update phrases with audio assets
3762                        UpdateRecordedPhrasesAlongWithPostRecordingOperations(listOfRecordedPhrases, ref firstRecordedPage);
3763
3764                        //Workaround to force phrases to show if they become invisible on stopping recording
3765                        mView.PostRecording_RecreateInvisibleRecordingPhrases(mRecordingSection, mRecordingInitPhraseIndex, mRecordingSession.RecordedAudio.Count);
3766                        EmptyNode lastRecordedPhrase = mRecordingSection.PhraseChildCount > 0 ? mRecordingSection.PhraseChild(mRecordingInitPhraseIndex + mRecordingSession.RecordedAudio.Count - 1) : null;
3767                        if (!wasMonitoring && lastRecordedPhrase != null && lastRecordedPhrase.IsRooted) mView.SelectFromTransportBar(lastRecordedPhrase, null);
3768                    }
3769
3770
3771                }
3772                catch (System.Exception ex)
3773                {                   
3774                    if (ex is urakawa.exception.DataMissingException || ex is System.IO.DirectoryNotFoundException)
3775                    {
3776                        IsDataMissingException = true;
3777                    }
3778                    MessageBox.Show(Localizer.Message("TransportBar_ErrorInStopRecording") + "\n\n" + ex.ToString(), Localizer.Message("Caption_Error"));
3779                }
3780
3781                    if (IsDataMissingException)
3782                    {
3783                        mView.ReplacePhrasesWithImproperAudioWithEmptyPhrases((ObiNode)mView.Presentation.RootNode, true);
3784                    }
3785UpdateButtons();
3786bool playbackEnabledOnSelectionChange = SelectionChangedPlaybackEnabled;
3787SelectionChangedPlaybackEnabled = false;
3788                try
3789                {
3790                    AdditionalPostRecordingOperations(firstRecordedPage, listOfRecordedPhrases);
3791                }
3792                catch (System.Exception ex)
3793                {
3794                    mView.WriteToLogFile(ex.ToString());
3795                    MessageBox.Show(ex.ToString());
3796                }
3797                SelectionChangedPlaybackEnabled = playbackEnabledOnSelectionChange;
3798                mRecordingSession = null;
3799                mResumeRecordingPhrase = null;
3800                // if a new unrooted section is created and is held in selection, clear the selection
3801                if (mRecordingSection != null && mView.Selection != null && !mRecordingSection.IsRooted && mView.Selection.Node == mRecordingSection) mView.Selection = null;
3802            }
3803        else if (mResumeRecordingPhrase != null)
3804            {
3805            mRecordingSession = null;
3806            mResumeRecordingPhrase = null;
3807
3808            }
3809            // missed recorder notification messages are written to log, if any
3810            if (m_MissedNotificationMessages != null && m_MissedNotificationMessages.Length > 1)
3811            {
3812                WriteLogMsgForRecorderMissedNotification();
3813            }
3814
3815            if (MonitorContinuously)
3816            {
3817                /// avoiding use of delay at this time to prevent possible bug. It will be restored after alpha.
3818                //StartMonitorContinuouslyWithDelay();
3819                StartMonitorContinuously();
3820            }
3821            else if (mView.ObiForm.Settings.Audio_AutoPlayAfterRecordingStops)
3822            {
3823                // if monitoring is not enabled and auto play after recording is checked.
3824                PlayOrResume_Safe();
3825            }
3826        }
3827
3828        private void UpdateRecordedPhrasesAlongWithPostRecordingOperations(List<PhraseNode> listOfRecordedPhrases,ref EmptyNode firstRecordedPage)
3829        {
3830            if (mRecordingSession!=null && mRecordingSession.RecordedAudio != null && mRecordingSession.RecordedAudio.Count > 0)
3831            {
3832                for (int i = 0; i < mRecordingSession.RecordedAudio.Count; ++i)
3833                {
3834                    mView.Presentation.UpdateAudioForPhrase(mRecordingSection.PhraseChild(mRecordingInitPhraseIndex + i),
3835                        mRecordingSession.RecordedAudio[i]);
3836                    if (!mRecordingSection.Used) mRecordingSection.PhraseChild(mRecordingInitPhraseIndex + i).Used = false;
3837                    if (mRecordingSession.PhraseIndexesToDelete.Contains(i))
3838                    {
3839                        mRecordingSection.PhraseChild(mRecordingInitPhraseIndex + i).Used = false;
3840                    }
3841                    //check if a page was marked
3842                    if (firstRecordedPage == null && mRecordingSection.PhraseChild(mRecordingInitPhraseIndex + i).Role_ == EmptyNode.Role.Page) firstRecordedPage = mRecordingSection.PhraseChild(mRecordingInitPhraseIndex + i);
3843
3844                    listOfRecordedPhrases.Add((PhraseNode)mRecordingSection.PhraseChild(mRecordingInitPhraseIndex + i));
3845                }
3846               
3847            }
3848        }
3849
3850        private void AdditionalPostRecordingOperations(EmptyNode firstRecordedPage, List<PhraseNode> listOfRecordedPhrases)
3851        {
3852            // make sure that recordingsession is not null before calling this function
3853            bool isRecordingAtEnd = false;
3854            if (listOfRecordedPhrases.Count > 0 && listOfRecordedPhrases[listOfRecordedPhrases.Count - 1]== mView.Presentation.LastSection.LastLeaf) 
3855                isRecordingAtEnd = true;
3856            //Console.WriteLine("recording index :" + listOfRecordedPhrases[listOfRecordedPhrases.Count - 1].Index + " : " + (mRecordingSection.PhraseChildCount-1));
3857
3858            // delete the following phrases before going into more complex commands
3859            if (mRecordingSession.Audio_DeleteFollowingPhrasesOfSectionAfterRecording && listOfRecordedPhrases != null && listOfRecordedPhrases.Count > 0)
3860            {
3861                EmptyNode lastRecordedPhrase = listOfRecordedPhrases[listOfRecordedPhrases.Count - 1] ;
3862                SectionNode section = lastRecordedPhrase.ParentAs<SectionNode> () ;
3863                if ( lastRecordedPhrase.IsRooted && lastRecordedPhrase.Index < section.PhraseChildCount -1)
3864                {
3865                Command deleteFollowingCmd =  mView.GetDeleteRangeOfPhrasesInSectionCommand(
3866                    section, section.PhraseChild(lastRecordedPhrase.Index+1), section.PhraseChild(section.PhraseChildCount - 1),
3867                    mView.ObiForm.Settings.Audio_PreservePagesWhileRecordOverSubsequentAudio, PhraseNode.Role.Page);
3868               
3869                mView.Presentation.Do(deleteFollowingCmd);
3870                }
3871            }
3872
3873            // on the fly phrase detection
3874            if (mRecordingSession != null && mRecordingSession.PhraseMarksOnTheFly != null && mRecordingSession.PhraseMarksOnTheFly.Count > 0)
3875            {
3876                if (IsPlaying) Pause();
3877
3878                EmptyNode lastPhrase = listOfRecordedPhrases.Count > 0 ? listOfRecordedPhrases[listOfRecordedPhrases.Count - 1] : null;//@AdvanceRecording
3879                EmptyNode nextToLastPhrase = null;
3880                if (lastPhrase != null)
3881                {
3882                    nextToLastPhrase = lastPhrase.Index < lastPhrase.ParentAs<SectionNode>().PhraseChildCount - 1 ? (EmptyNode)lastPhrase.FollowingNode :
3883                        null;//@AdvanceRecording
3884                }
3885                if (mView.ObiForm.Settings.Audio_MergeFirstTwoPhrasesAfterPhraseDetectionWhileRecording
3886                    && mRecordingSession.PhraseMarksOnTheFly.Count > 1)
3887                {
3888                    mRecordingSession.PhraseMarksOnTheFly.RemoveAt(0);
3889                    Console.WriteLine("Merging first 2 phrases aftre recording");
3890                }
3891
3892                mView.Presentation.Do(GetSplitCommandForOnTheFlyDetectedPhrases(listOfRecordedPhrases, mRecordingSession.PhraseMarksOnTheFly, mView.ObiForm.Settings.Audio_PreventSplittingPages));
3893
3894                if (!mView.ObiForm.Settings.Audio_PreventSplittingPages)
3895                {
3896                    CompositeCommand multipleMergePhraseCommand = GetMultiplePhrasesMergeCommand(listOfRecordedPhrases);
3897                    if (multipleMergePhraseCommand.ChildCommands.Count > 0)
3898                    {
3899                        mView.Presentation.Do(multipleMergePhraseCommand);
3900                    }
3901                }
3902
3903                if (nextToLastPhrase != null && nextToLastPhrase.IsRooted && nextToLastPhrase.Index > 0)//@advanceRecording
3904                {
3905                    SectionNode section = nextToLastPhrase.ParentAs<SectionNode>();
3906                    mView.SelectFromTransportBar( section.PhraseChild(nextToLastPhrase.Index - 1), null);
3907                   
3908                }
3909                else if (lastPhrase != null)
3910                {
3911                    SectionNode section = lastPhrase.ParentAs<SectionNode>();
3912                    mView.SelectFromTransportBar(section.PhraseChild(section.PhraseChildCount-1), null);
3913                }
3914
3915                if (mView.Selection != null)
3916                {
3917                    Commands.UpdateSelection updateSelectionCmd = updateSelectionCmd = new Obi.Commands.UpdateSelection(mView,
3918                        new NodeSelection(mView.Selection.Node, mView.Selection.Control));
3919                    mView.Presentation.Do(updateSelectionCmd);
3920                }
3921            }
3922            if (mView.ObiForm.Settings.Audio_EnablePostRecordingPageRenumbering &&  m_EnablePostRecordingPageRenumbering &&  firstRecordedPage != null)
3923            {//1
3924                int pageNum = firstRecordedPage.PageNumber.Number ;
3925                PageKind pageKind = firstRecordedPage.PageNumber.Kind ;
3926                bool renumber = false ;
3927                foreach (PhraseNode p in listOfRecordedPhrases)
3928                {//2
3929                    if ( p == firstRecordedPage ) continue ;
3930                    if (p.Role_ == EmptyNode.Role.Page && p.PageNumber != null && p.PageNumber.Kind == pageKind)
3931                    {//3
3932                        if (p.PageNumber.Number != pageNum + 1)
3933                        {//4
3934                            renumber = true;
3935                            break;
3936                        }//-4
3937                        pageNum = p.PageNumber.Number;
3938                    }//-3
3939                }//-2
3940                // check if the last recording phrase is also last phrase in section
3941                if (!isRecordingAtEnd) renumber = true;
3942                if(renumber )
3943                    //&& MessageBox.Show(Localizer.Message("TransportBar_RenumberPagesAfterRecording"), Localizer.Message("RenumberPagesCaption"), MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
3944            {
3945                if (IsPlaying) Pause();
3946                mView.Presentation.Do(mView.GetPageRenumberCommand(firstRecordedPage, firstRecordedPage.PageNumber, Localizer.Message("RenumberPagesCaption").Replace("?", ""),true));
3947            }
3948            }
3949
3950           
3951            if (mView != null && mView.ObiForm.Settings.Project_SaveProjectWhenRecordingEnds) mView.ObiForm.Save();
3952        }
3953
3954        private CompositeCommand GetSplitCommandForOnTheFlyDetectedPhrases(List<PhraseNode> phrasesList, List<double> timingList, bool preventSplittingPages)
3955        {
3956            CompositeCommand multipleSplitCommand = mView.Presentation.CreateCompositeCommand("Multiple split command");
3957            timingList.Sort();
3958            List<double> newTimingList = new List<double>();
3959            newTimingList.InsertRange(0, timingList);
3960            Console.WriteLine("On the fly: " + phrasesList.Count);
3961            for (int i = phrasesList.Count - 1; i >= 0; i--)
3962            {
3963                PhraseNode phrase = phrasesList[i];
3964                double referenceTimeForPhrase = 0;
3965
3966                if ((preventSplittingPages && phrase.Role_ == EmptyNode.Role.Page) || phrase.TODO || !phrase.Used) continue;
3967
3968                //first calculate the reference time
3969                foreach (PhraseNode p in phrasesList)
3970                {
3971                    if (p == phrase) break;
3972                    referenceTimeForPhrase += p.Duration;
3973                }
3974               
3975                for (int j = newTimingList.Count-1; j >= 0; j--)
3976                {
3977                    if (newTimingList[j] < referenceTimeForPhrase) break;
3978                    //Commands.Node.SplitAudio split = new Commands.Node.SplitAudio(mView, phrase, newTimingList[j]);
3979                    double splitTimeInPhrase = newTimingList[j] - referenceTimeForPhrase;
3980                    //avoid invalid time and also too small phrases, less than 200ms
3981                    if ( splitTimeInPhrase <= 200 || splitTimeInPhrase>= (phrase.Duration - 200) ) continue ;
3982                    CompositeCommand split = Commands.Node.SplitAudio.GetSplitCommand(mView, phrase,splitTimeInPhrase );
3983                    multipleSplitCommand.ChildCommands.Insert(multipleSplitCommand.ChildCommands.Count, split);
3984                    newTimingList.RemoveAt(j);
3985                }
3986
3987            }
3988            // mark to do to first phrase if retain initial silence is false
3989            if (!mView.ObiForm.Settings.Audio_RetainInitialSilenceInPhraseDetection
3990                && phrasesList.Count > 0
3991                && multipleSplitCommand.ChildCommands.Count > 0)
3992            {
3993                Commands.Node.ToggleNodeTODO todoMarkCmd = new Obi.Commands.Node.ToggleNodeTODO(mView, phrasesList[0]);
3994                todoMarkCmd.UpdateSelection = false;
3995                multipleSplitCommand.ChildCommands.Insert(multipleSplitCommand.ChildCommands.Count, todoMarkCmd);
3996            }
3997            return multipleSplitCommand;
3998        }
3999
4000        private CompositeCommand GetMultiplePhrasesMergeCommand(List<PhraseNode> listOfRecordedPhrases)
4001        {
4002            CompositeCommand multipleMergePhraseCommand = mView.Presentation.CreateCompositeCommand("Merge multiple phrases");
4003            foreach (PhraseNode n in listOfRecordedPhrases)
4004            {
4005                ObiNode nextObiNode = n.FollowingNode;
4006                if (nextObiNode != null && nextObiNode is PhraseNode && !listOfRecordedPhrases.Contains((PhraseNode)nextObiNode) && nextObiNode.Parent == n.Parent)
4007                {
4008                    PhraseNode nextPhraseNode = (PhraseNode)nextObiNode;
4009                    Commands.Node.MergeAudio mergeCmd = new Obi.Commands.Node.MergeAudio(mView, n, nextPhraseNode);
4010                    mergeCmd.UpdateSelection = false;
4011                    multipleMergePhraseCommand.ChildCommands.Insert(multipleMergePhraseCommand.ChildCommands.Count,
4012                        mergeCmd);
4013                    Console.WriteLine(n.ToString());
4014                }
4015            }
4016            return multipleMergePhraseCommand;
4017        }
4018
4019        public bool IsRecording
4020        {
4021            get
4022            {
4023                return mRecordingSession != null &&
4024                    mRecordingSession.AudioRecorder.CurrentState == AudioLib.AudioRecorder.State.Recording;
4025            }
4026        }
4027
4028        public bool IsListening
4029        {
4030            get
4031            {
4032                return mRecordingSession != null &&
4033                    mRecordingSession.AudioRecorder.CurrentState == AudioLib.AudioRecorder.State.Monitoring;
4034            }
4035        }
4036
4037        public bool IsActive { get { return Enabled && ( IsPlayerActive || IsRecorderActive ); } }
4038        private bool IsPlaying { get { return mPlayer.CurrentState == AudioLib.AudioPlayer.State.Playing; } }
4039        public bool IsPlayerActive { get { return IsPaused || IsPlaying; } }
4040        private bool IsPaused { get { return mPlayer.CurrentState == AudioLib.AudioPlayer.State.Paused; } }
4041        public bool IsRecorderActive { get { return IsListening || IsRecording; } }
4042        private bool IsMetadataSelected { get { return mView.Selection != null && mView.Selection.Control is MetadataView  ; } }
4043
4044        private void mToDoMarkButton_Click ( object sender, EventArgs e ) 
4045        {
4046                    MarkTodo();
4047        }
4048
4049        /// <summary>
4050        /// Toggle TODO on the currently playing/recording phrase.
4051        /// </summary>
4052        public void MarkTodo(bool IsCommentAdded = false)
4053        {
4054            EmptyNode node = null;
4055            if (IsRecording)
4056            {
4057                node = (EmptyNode)mRecordingPhrase;
4058
4059                mView.Presentation.Changed -= new EventHandler<urakawa.events.DataModelChangedEventArgs>(Presentation_Changed);
4060                mView.Presentation.UndoRedoManager.Execute(new Commands.Node.ToggleNodeTODO(mView, node));
4061                mView.Presentation.Changed += new EventHandler<urakawa.events.DataModelChangedEventArgs>(Presentation_Changed);
4062                if (!IsCommentAdded)
4063                NextPhrase();
4064            }
4065            else if (IsPlayerActive)
4066            {
4067                node = (EmptyNode)mCurrentPlaylist.CurrentPhrase;
4068                if (node != null)
4069                {
4070                    mView.Presentation.Changed -= new EventHandler<urakawa.events.DataModelChangedEventArgs>(Presentation_Changed);
4071                    if (node is PhraseNode && node.Duration > 0 && mCurrentPlaylist != null)
4072                    {
4073                        mView.Presentation.UndoRedoManager.Execute(new Commands.Node.ToggleNodeTODO(mView, node, mCurrentPlaylist.CurrentTimeInAsset));
4074                }
4075                else
4076                    {
4077                    mView.Presentation.UndoRedoManager.Execute(new Commands.Node.ToggleNodeTODO(mView, node));
4078                }
4079                    mView.Presentation.Changed += new EventHandler<urakawa.events.DataModelChangedEventArgs>(Presentation_Changed);
4080                }
4081
4082            }
4083        else if (mView.Selection != null && mView.Selection.Node is EmptyNode)
4084            {
4085            node  = (EmptyNode)mView.Selection.Node;
4086            mView.Presentation.Changed -= new EventHandler<urakawa.events.DataModelChangedEventArgs> ( Presentation_Changed );
4087            if (node != null && node is PhraseNode && node.Duration > 0 && mView.Selection is AudioSelection)
4088            {
4089                AudioSelection selection = mView.Selection as AudioSelection;
4090                double todoTime = selection.AudioRange.HasCursor ? selection.AudioRange.CursorTime :
4091                    selection.AudioRange.SelectionBeginTime;
4092                if (todoTime > 0 && todoTime < node.Duration) mView.Presentation.UndoRedoManager.Execute(new Commands.Node.ToggleNodeTODO(mView, node, todoTime));
4093            }
4094            else
4095            {
4096                mView.Presentation.UndoRedoManager.Execute(new Commands.Node.ToggleNodeTODO(mView, node));
4097            }
4098            mView.Presentation.Changed += new EventHandler<urakawa.events.DataModelChangedEventArgs> ( Presentation_Changed );
4099               
4100            }
4101           
4102        }
4103
4104
4105        private void PlaybackOnSelectionChange_Safe ()
4106            {
4107            if (mView.Selection != null && !(mView.Selection is TextSelection)
4108                &&mView.Selection.Node is ObiNode)
4109                {
4110                try
4111                    {
4112                    m_PlayOnSelectionChangedMutex.WaitOne ();
4113                    PlaybackOnSelectionChange ();
4114                    m_PlayOnSelectionChangedMutex.ReleaseMutex ();
4115                    }
4116                catch (System.Exception)
4117                    {
4118                    m_PlayOnSelectionChangedMutex.ReleaseMutex ();
4119                    return;
4120                    }
4121                }
4122            }
4123
4124        public bool SkipPlayOnNavigateForSection { set { m_SkipPlayOnNavigateForSection = value; } } 
4125        private bool m_SkipPlayOnNavigateForSection = false;
4126        private void PlaybackOnSelectionChange ()
4127        {
4128            if (IsRecorderActive) return;
4129            if (m_SkipPlayOnNavigateForSection && (mView.Selection == null || mView.Selection.Node is SectionNode))
4130            {
4131                m_SkipPlayOnNavigateForSection = false;
4132                return;
4133            }
4134            if (mView.Selection != null && !(mView.Selection is StripIndexSelection))
4135            {
4136                if (mState == State.Playing || mState == State.Paused)
4137                {
4138                    ObiNode node = mView.Selection.Node;
4139                    PhraseNode PNode = null;
4140
4141                    if (node is PhraseNode)
4142                        PNode = (PhraseNode)node;
4143                    else if (node is SectionNode)
4144                    {
4145                        if (((SectionNode)node).PhraseChildCount > 0 )
4146                            {
4147                            if ( mCurrentPlaylist != mMasterPlaylist &&  ((SectionNode)node).PhraseChild(0) is PhraseNode)
4148                            PNode = (PhraseNode)((SectionNode)node).PhraseChild(0);
4149                            else // start finding required phrase node in this section
4150                                {
4151                                for (int PIndex = 0; PIndex < node.PhraseChildCount; PIndex++)
4152                                    {
4153                                    if (node.PhraseChild ( PIndex ) is PhraseNode && node.PhraseChild ( PIndex ).Used)
4154                                        {
4155                                        PNode = (PhraseNode)((SectionNode)node).PhraseChild ( PIndex );
4156                                        break;
4157                                        }
4158                                    } // for loop ends
4159
4160                                }
4161                            }
4162                    }
4163
4164                if (PNode != null && mCurrentPlaylist.ContainsPhrase ( PNode ))
4165                    {// 1
4166                    if (PNode != mCurrentPlaylist.CurrentPhrase) // if selected node is not currently playing phrase
4167                        { //2
4168                        if (mView.Selection.Control.GetType () != typeof ( TOCView )
4169                            || mCurrentPlaylist.CurrentPhrase.ParentAs<SectionNode> () != PNode.ParentAs<SectionNode> ()) // bypass if selection is in TOC and playing section is same as selected section
4170                            { //3
4171                            if (mPlayer.CurrentState == AudioLib.AudioPlayer.State.Paused) mCurrentPlaylist.Stop ();
4172
4173                            mCurrentPlaylist.CurrentPhrase = PNode;
4174                            if (mView.Selection is AudioSelection) mCurrentPlaylist.CurrentTimeInAsset = ((AudioSelection)mView.Selection).AudioRange.CursorTime;
4175                            } //-3
4176                        } //-2
4177                    else if (mView.Selection is AudioSelection && ((AudioSelection)mView.Selection).AudioRange.HasCursor) // clicked on the same phrase
4178                        mCurrentPlaylist.CurrentTimeInAsset = ((AudioSelection)mView.Selection).AudioRange.CursorTime;
4179                    } //-1
4180                else if (mCurrentPlaylist == mMasterPlaylist) // newly selected phrase is not in master paylist
4181                    Stop ();
4182
4183                    if (mCurrentPlaylist != mMasterPlaylist
4184                        && !mCurrentPlaylist.ContainsPhrase(PNode))
4185                    {
4186                        if (mState == State.Playing)
4187                        {
4188                            mView.SetPlaybackPhraseAndTime(null, 0.0);
4189                            mCurrentPlaylist.Stop();
4190                            //if (mView.Selection.Node is PhraseNode)
4191                                //PlayOrResume();
4192                            if (mView.Selection.Node is SectionNode && mView.ObiForm.Settings.PlayOnNavigate)
4193                                PlayHeadingPhrase(mView.SelectedNodeAs<SectionNode>());
4194                        }
4195                        else
4196                        {
4197                            mView.SetPlaybackPhraseAndTime(null, 0.0);
4198                            mCurrentPlaylist.Stop();
4199                        }
4200                    }
4201                }
4202                if (mView.ObiForm.Settings.PlayOnNavigate
4203                    &&
4204                    (mState == State.Paused || mState == State.Stopped))
4205                {
4206                    if (mView.Selection.Node is SectionNode)
4207                        PlayHeadingPhrase(mView.SelectedNodeAs<SectionNode>());
4208                    else if (mView.Selection.Node is PhraseNode)
4209                        PlayOrResume();
4210                }
4211                if (mView.ObiForm.Settings.Audio_ShowSelectionTimeInTransportBar && mState == State.Stopped)
4212                {
4213                    UpdateTimeDisplay();
4214                }
4215                                        }// end of selection null check
4216
4217        }
4218
4219        public void PlayHeadingPhrase( SectionNode node     )
4220        {
4221            if ( node != null  && node.PhraseChildCount > 0  )
4222            {
4223                EmptyNode ENode = node.PhraseChild(0);
4224                   
4225                for (int i = 0; i < node.PhraseChildCount ; i++)
4226                {
4227                    if (((EmptyNode)node.PhraseChild(i)).Role_ == EmptyNode.Role.Heading)
4228                    {
4229                        ENode = node.PhraseChild(i);
4230                                                break;
4231                    }
4232                                    }
4233
4234                                    if (ENode is PhraseNode)
4235                                    {
4236                                        mLocalPlaylist = new Playlist(mPlayer, ENode ,mPlayQAPlaylist);
4237                                        SetPlaylistEvents(mLocalPlaylist);
4238                                        mCurrentPlaylist = mLocalPlaylist;
4239                                        mCurrentPlaylist.CurrentPhrase = (PhraseNode) ENode ;
4240                                        if (mCurrentPlaylist.State != AudioLib.AudioPlayer.State.Playing) mCurrentPlaylist.Play();
4241                                                                                //PlayOrResume(node.PhraseChild(0));
4242                                    }
4243            }
4244        }
4245
4246
4247        public enum AudioCluesSelection { SelectionBegin, SelectionEnd } ;
4248
4249        public void PlayAudioClue(AudioCluesSelection Clue)
4250        {
4251            if ( mView.ObiForm.Settings.Audio_AudioClues )
4252            {
4253            if (Clue == AudioCluesSelection.SelectionBegin)
4254            {
4255                string FilePath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "SelectionBegin.wav");
4256                if ( System.IO.File.Exists (FilePath))
4257                                    new System.Media.SoundPlayer(FilePath).Play ()  ;
4258                                                }
4259            else if (Clue == AudioCluesSelection.SelectionEnd)
4260            {
4261                string FilePath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "SelectionEnd.wav");
4262                if (System.IO.File.Exists(FilePath))
4263                                    new System.Media.SoundPlayer(FilePath).Play();
4264            }
4265            }
4266                    }
4267
4268
4269        #endregion
4270
4271        public bool FocusOnTimeDisplay()
4272        {
4273            return mTimeDisplayBox.Focus();
4274        }
4275
4276        /// <summary>
4277        ///  Process dialog key overridden to prevent tab  from  moving focus out of transportbar
4278        /// </summary>
4279        /// <param name="KeyData"></param>
4280        /// <returns></returns>
4281        protected override bool ProcessDialogKey(Keys KeyData)
4282        {
4283            if (KeyData == Keys.Tab
4284                && this.ActiveControl != null)
4285            {
4286                Control c = this.ActiveControl;
4287                this.SelectNextControl(c, true, true, true, true);
4288                if (this.ActiveControl != null && c.TabIndex > this.ActiveControl.TabIndex)
4289                    System.Media.SystemSounds.Beep.Play();
4290                return true;
4291            }
4292            else if (KeyData == (Keys)(Keys.Shift | Keys.Tab)
4293                && this.ActiveControl != null)
4294            {
4295                Control c = this.ActiveControl;
4296                this.SelectNextControl(c, false, true, true, true);
4297                if (this.ActiveControl != null && c.TabIndex < this.ActiveControl.TabIndex)
4298                    System.Media.SystemSounds.Beep.Play();
4299
4300                return true;
4301            }
4302            else
4303            {
4304                return base.ProcessDialogKey(KeyData);
4305            }
4306        }
4307
4308        // Create the preview playlist
4309        private void CreateLocalPlaylistForPreview(PhraseNode node,  double revertTime, bool useSelection)
4310        {
4311            PreviewPlaylist playlist = useSelection ? new PreviewPlaylist(mPlayer, mView.Selection, revertTime) :
4312                new PreviewPlaylist(mPlayer, node , revertTime);
4313            SetPlaylistEvents(playlist);
4314            mCurrentPlaylist = playlist;
4315        }
4316
4317       
4318
4319        public bool CanUsePlaybackSelection { get { return Enabled && IsPlayerActive && mView.ObiForm.Settings.PlayOnNavigate; }}
4320
4321        public void mView_BlocksVisibilityChanged ( object sender, EventArgs e )
4322            {
4323            UpdateButtons ();
4324            }
4325
4326        private void mDisplayBox_DropDown(object sender, EventArgs e)
4327        {
4328            mDisplayBox.Tag = mDisplayBox.SelectedIndex;
4329        }
4330
4331        private bool m_FineNavigationModeForPhrase = false ;
4332        private EmptyNode m_FineNavigationPhrase = null;
4333        public bool FineNavigationModeForPhrase
4334        {
4335            get
4336            {
4337                return m_FineNavigationModeForPhrase;
4338            }
4339            set
4340            {
4341                if (value != m_FineNavigationModeForPhrase)
4342                {
4343                    m_FineNavigationModeForPhrase = value;
4344                    if (m_FineNavigationModeForPhrase)
4345                    {
4346                        m_FineNavigationPhrase = mView.Selection.EmptyNodeForSelection;
4347                        mView.UpdateBlockForFindNavigation(m_FineNavigationPhrase, m_FineNavigationModeForPhrase);   
4348                        string navigationOnClue = System.IO.Path.Combine ( System.AppDomain.CurrentDomain.BaseDirectory, "FineNavigationOn.wav") ;
4349                        if (mView.ObiForm.Settings.Audio_AudioClues &&  System.IO.File.Exists(navigationOnClue))
4350                        {
4351                            System.Media.SoundPlayer player = new System.Media.SoundPlayer(navigationOnClue);
4352                            player.Play();
4353                        }
4354                        // add sound here
4355                    }
4356                    else
4357                    {
4358                        if (m_FineNavigationPhrase != null) mView.UpdateBlockForFindNavigation(m_FineNavigationPhrase, m_FineNavigationModeForPhrase);
4359                        m_FineNavigationPhrase = null;
4360                        if(mView.ObiForm.Settings.Audio_AudioClues)  System.Media.SystemSounds.Exclamation.Play();
4361                        // add sound here
4362                    }
4363                   
4364
4365                    if (StateChanged != null) StateChanged(this, new AudioLib.AudioPlayer.StateChangedEventArgs(mPlayer.CurrentState) );
4366                }
4367            }
4368        }
4369
4370        public string FineNavigationStatusMsg
4371        {
4372            get { return FineNavigationModeForPhrase ? Localizer.Message ("StatusMsg_FineNavigation") : ""; }
4373        }
4374
4375        public string GetHelpTopicPath()
4376        {
4377            if (mTimeDisplayBox.ContainsFocus || mDisplayBox.ContainsFocus)
4378            {
4379                return "HTML Files\\Exploring the GUI\\Obi Views and Transport Bar\\Time Display.htm";
4380            }
4381            else if (mVUMeterPanel.ContainsFocus)
4382            {
4383                return "HTML Files\\Exploring the GUI\\Obi Views and Transport Bar\\Textual peak meter.htm";
4384            }
4385            else if (mFastPlayRateCombobox.ContainsFocus)
4386            {
4387                return "HTML Files\\Creating a DTB\\Working with Audio\\Fast Play.htm";
4388            }
4389            else if (mToDo_CustomClassMarkButton.ContainsFocus)
4390            {
4391                return "HTML Files\\Creating a DTB\\Working with Phrases\\Changing the Todo or Used Status.htm";
4392            }
4393            else
4394            { return "HTML Files\\Exploring the GUI\\Obi Views and Transport Bar\\Audio and Navigation controls.htm"; }
4395        }
4396
4397
4398        private void m_btnRecordingOptions_Click(object sender, EventArgs e)
4399        {
4400            Button btn = (Button)sender;
4401            Point ptLowerLeft = new Point(0, btn.Height);
4402            ptLowerLeft = btn.PointToScreen(ptLowerLeft);
4403            m_RecordingOptionsContextMenuStrip.Show(ptLowerLeft); 
4404
4405        }
4406
4407        private void RecordingOptions_Monitoring_Click(object sender, EventArgs e)
4408        {
4409            if (CanResumePlayback || mState == State.Stopped)
4410            {
4411                if (MonitorContinuously) StopMonitorContinuously(); //@MonitorContinuously
4412                SetupRecording(Monitoring, false); 
4413            }
4414        }
4415
4416        private void RecordingOptions_RecordWithDeleteFollowing_Click(object sender, EventArgs e)
4417        {
4418            RecordOverSubsequentPhrases();
4419        }
4420
4421        public void RecordOverSubsequentPhrases()
4422        {
4423            if (CanRecord )
4424            {
4425                if (mView.ObiForm.Settings.Audio_AllowOverwrite && CurrentState == State.Playing) Pause(); //@recordFromPlay
4426                //StartRecordingDirectly_Internal(true); //@deleterecording
4427                StartRecordingDirectly_Internal(CanRecordOnFollowingAudio);
4428            }
4429        }
4430
4431        private void m_RecordingtoolStripMenuItem_Click(object sender, EventArgs e)
4432        {
4433            this.Record();
4434        }
4435
4436        private void m_RecordingOptionsContextMenuStrip_Opening(object sender, System.ComponentModel.CancelEventArgs e)
4437        {
4438            if (IsPreviewBeforeRecordingEnabled)           
4439            {
4440                mPreviewBeforeRecToolStripMenuItem.Enabled = true;
4441            }
4442            else
4443            {
4444                mPreviewBeforeRecToolStripMenuItem.Enabled = false;
4445            }
4446
4447            if (mView.ObiForm.Settings.Audio_AllowOverwrite)
4448            {
4449                m_DeletePhrasestoolStripMenuItem.Enabled = !IsListening;
4450            }
4451            else
4452            {
4453                m_DeletePhrasestoolStripMenuItem.Enabled = false;
4454            }
4455
4456            mMonitorContinuouslyToolStripMenuItem.Checked = MonitorContinuously;//@MonitorContinuously
4457
4458        }
4459
4460        public string GetPredefinedProfilesDirectory()
4461        {
4462            string appDirectory = System.AppDomain.CurrentDomain.BaseDirectory;
4463            string defaultProfilesDirectory = System.IO.Path.Combine(appDirectory, "profiles");
4464            return defaultProfilesDirectory;
4465        }
4466
4467        public string GetCustomProfilesDirectory()
4468        {
4469            string ProfileDirectory = System.IO.Directory.GetParent(Settings_Permanent.GetSettingFilePath()).ToString();
4470            string customProfilesDirectory = System.IO.Path.Combine(ProfileDirectory, "profiles");
4471            return customProfilesDirectory;
4472        }
4473        public string[] ProfilesPaths
4474        {
4475            get
4476            {
4477                return m_filePaths;
4478            }
4479        }
4480        public void RemoveProfileFromSwitchProfile(string profileToRemove)
4481        {           
4482            if (m_ListOfSwitchProfiles.ContainsKey(profileToRemove))
4483            {
4484                m_SwitchProfileContextMenuStrip.Items.Remove(m_ListOfSwitchProfiles[profileToRemove]);
4485                m_ListOfSwitchProfiles.Remove(profileToRemove);
4486            } 
4487        }
4488        public void AddProfileToSwitchProfile(string profileToAdd)
4489        {
4490            ToolStripMenuItem SwitchProfile = new ToolStripMenuItem(profileToAdd, null, SwitchProfile_Click);
4491            m_SwitchProfileContextMenuStrip.Items.Add(SwitchProfile);
4492            m_ListOfSwitchProfiles.Add(profileToAdd, SwitchProfile);           
4493        }
4494        // To Initialize Switch Profile ToolStrip menu Items
4495        public void InitializeSwitchProfiles()
4496        {
4497            //string ProfileDirectory = System.AppDomain.CurrentDomain.BaseDirectory;
4498            //string defaultProfilesDirectory = System.IO.Path.Combine(ProfileDirectory, "profiles");
4499            m_ListOfSwitchProfiles.Clear();
4500            m_SwitchProfileContextMenuStrip.Items.Clear();
4501            m_CurrentCheckedProfile = null;
4502            string ProfileDirectory = GetPredefinedProfilesDirectory();
4503            m_filePaths = System.IO.Directory.GetFiles(ProfileDirectory, "*.xml");
4504            List<string> filePathsList = new List<string>();
4505            if (m_filePaths != null && m_filePaths.Length > 0)
4506            {
4507                //string[] profileFileNames = new string[m_filePaths.Length];
4508                for (int i = 0; i < m_filePaths.Length; i++)
4509                {
4510                    filePathsList.Add(System.IO.Path.GetFileNameWithoutExtension(m_filePaths[i]));
4511                    //   m_cb_SelectProfile.Items.Add(System.IO.Path.GetFileNameWithoutExtension(m_filePaths[i]));
4512                }
4513               
4514                if (filePathsList.Contains("Basic"))
4515                {
4516                    int index = filePathsList.IndexOf("Basic");
4517                    ToolStripMenuItem SwitchProfile = new ToolStripMenuItem(filePathsList[index], null, SwitchProfile_Click);
4518                    m_SwitchProfileContextMenuStrip.Items.Add(SwitchProfile);
4519                    m_ListOfSwitchProfiles.Add(filePathsList[index], SwitchProfile);
4520                    filePathsList.RemoveAt(index);
4521                }
4522                if (filePathsList.Contains("Intermediate"))
4523                {
4524                    int index = filePathsList.IndexOf("Intermediate");
4525                    ToolStripMenuItem SwitchProfile = new ToolStripMenuItem(filePathsList[index], null, SwitchProfile_Click);
4526                    m_SwitchProfileContextMenuStrip.Items.Add(SwitchProfile);
4527                    m_ListOfSwitchProfiles.Add(filePathsList[index], SwitchProfile);
4528                    filePathsList.RemoveAt(index);
4529                }
4530                foreach (string file in filePathsList)
4531                {
4532                    ToolStripMenuItem SwitchProfile = new ToolStripMenuItem(file, null, SwitchProfile_Click);
4533                    m_SwitchProfileContextMenuStrip.Items.Add(SwitchProfile);
4534                    m_ListOfSwitchProfiles.Add(file, SwitchProfile);                 
4535                }
4536
4537            }
4538
4539            //ProfileDirectory = System.IO.Directory.GetParent(Settings_Permanent.GetSettingFilePath()).ToString();
4540            //ProfileDirectory = System.IO.Path.Combine(ProfileDirectory, "profiles");
4541            ProfileDirectory = GetCustomProfilesDirectory();
4542            if (System.IO.Directory.Exists(ProfileDirectory))
4543            {
4544                string[] temp =  System.IO.Directory.GetFiles(ProfileDirectory, "*.xml");
4545                string[] tempFilePaths = new string[m_filePaths.Length + temp.Length];
4546                m_filePaths.CopyTo(tempFilePaths, 0);
4547                temp.CopyTo(tempFilePaths, m_filePaths.Length);
4548                m_filePaths = tempFilePaths;
4549
4550
4551                if (temp != null && temp.Length > 0)
4552                {
4553                    for (int i = 0; i < temp.Length; i++)
4554                    {
4555                        string filename = System.IO.Path.GetFileNameWithoutExtension(temp[i]);
4556                        if (!m_ListOfSwitchProfiles.ContainsKey(filename))
4557                        {
4558                            ToolStripMenuItem SwitchProfile = new ToolStripMenuItem(filename, null, SwitchProfile_Click);
4559                            m_SwitchProfileContextMenuStrip.Items.Add(SwitchProfile);
4560                            m_ListOfSwitchProfiles.Add(filename, SwitchProfile);
4561                        }
4562
4563                    }
4564                }
4565            }// directory exists check
4566
4567            if (mView != null && mView.ObiForm != null && mView.ObiForm.Settings != null)
4568            {
4569                mView.ObiForm.UpdateTitle();
4570            }
4571        }
4572        // LoadProfile is used to Load Profile from RT toggle and Transport bar Switch profile button.
4573        public void LoadProfile(string profilePath, string ProfileName)
4574        {
4575            if (this.MonitorContinuously) this.MonitorContinuously = false;
4576            if (this.IsRecorderActive || this.IsPlayerActive) this.Stop();
4577            Settings saveProfile = Settings.GetSettingsFromSavedProfile(profilePath);
4578            saveProfile.CopyPropertiesToExistingSettings(mView.ObiForm.Settings, PreferenceProfiles.Audio,ProfileName);
4579            saveProfile.CopyPropertiesToExistingSettings(mView.ObiForm.Settings, PreferenceProfiles.Colors,ProfileName);
4580            saveProfile.SettingsName = ProfileName;
4581            string strLoadedProfiles = " ";
4582            if (saveProfile.Compare(mView.ObiForm.Settings, PreferenceProfiles.All))
4583            {
4584                strLoadedProfiles += "all";
4585            }
4586            else
4587            {
4588                if (saveProfile.Compare(mView.ObiForm.Settings, PreferenceProfiles.Project))
4589                {
4590                    strLoadedProfiles += "project, ";
4591                }
4592                if (saveProfile.Compare(mView.ObiForm.Settings, PreferenceProfiles.Audio))
4593                {
4594                    strLoadedProfiles += "audio, ";
4595                }
4596                if (saveProfile.Compare(mView.ObiForm.Settings, PreferenceProfiles.UserProfile))
4597                {
4598                    strLoadedProfiles += "users profile, ";
4599                }
4600                if (saveProfile.Compare(mView.ObiForm.Settings, PreferenceProfiles.Colors))
4601                {
4602                    strLoadedProfiles += "colors";
4603                }
4604            }
4605            if (string.IsNullOrEmpty(strLoadedProfiles))
4606            {
4607                mView.ObiForm.Settings.SettingsName = "customized";
4608            }
4609            else
4610            {
4611                if (strLoadedProfiles.EndsWith(",")) strLoadedProfiles = strLoadedProfiles.Remove(strLoadedProfiles.Length - 2);
4612            }
4613            string text = string.Format(Localizer.Message("Preferences_ProfilesStatus"), saveProfile.SettingsName, strLoadedProfiles);
4614            mView.ObiForm.Settings.SettingsNameForManipulation = saveProfile.SettingsName + "   " + Localizer.Message("Profile_Audio");
4615            mView.ObiForm.Settings.SettingsName = text;
4616            UpdateButtons();
4617            mTransportBarTooltip.SetToolTip(m_btnSwitchProfile, Localizer.Message("Transport_SwitchProfile") + "\n" + ProfileName + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ContentView_TransportBarExpandSwitchProfile.Value.ToString()) + ")");
4618            m_btnSwitchProfile.AccessibleName = Localizer.Message("Transport_SwitchProfile") + ProfileName + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ContentView_TransportBarExpandSwitchProfile.Value.ToString());
4619
4620            if (m_CurrentCheckedProfile != null)
4621            {
4622                m_CurrentCheckedProfile.Checked = false;
4623            }
4624            if (m_ListOfSwitchProfiles.ContainsKey(ProfileName))
4625            {
4626                ToolStripMenuItem ProfileSelected = m_ListOfSwitchProfiles[ProfileName];
4627                ProfileSelected.Checked = true;
4628                m_CurrentCheckedProfile = ProfileSelected;
4629            }
4630               
4631            mView.ObiForm.UpdateRecordingToolBarButtons();
4632            mView.ObiForm.UpdateTitle();
4633            mView.ObiForm.UpdateColors();
4634        }
4635
4636    // Event is subscribed to ToolStripMenu items.
4637        void SwitchProfile_Click(object sender, EventArgs e)
4638        {
4639
4640            string ProfileName =   sender.ToString();
4641           
4642            List<string> filePathsList = new List<string>();
4643            if (m_filePaths != null && m_filePaths.Length > 0)
4644            {
4645                for (int i = 0; i < m_filePaths.Length; i++)
4646                {
4647                    filePathsList.Add(System.IO.Path.GetFileNameWithoutExtension(m_filePaths[i]));
4648                }
4649            }
4650            if (filePathsList.Contains(ProfileName))
4651            {
4652                int index = filePathsList.IndexOf(ProfileName);
4653
4654                LoadProfile(m_filePaths[index],ProfileName);
4655                List<string> installedTTSVoices = Obi.Audio.AudioFormatConverter.InstalledTTSVoices;
4656                if (installedTTSVoices != null && installedTTSVoices.Count > 0)
4657                {
4658                    if (!installedTTSVoices.Contains(mView.ObiForm.Settings.Audio_TTSVoice))
4659                    {
4660                        mView.ObiForm.Settings.Audio_TTSVoice = installedTTSVoices[0];
4661                    }
4662                }
4663            }
4664        }
4665        public void InitializeTooltipsForTransportpar()
4666        {
4667            keyboardShortcuts = mView.ObiForm.KeyboardShortcuts;
4668            if (keyboardShortcuts.MenuNameDictionary.ContainsKey("mPreviousPhraseToolStripMenuItem"))
4669            {
4670                mTransportBarTooltip.SetToolTip(mPrevPhraseButton, Localizer.Message("Transport_PreviousPhrase") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mPreviousPhraseToolStripMenuItem"].Value.ToString()) + ")");
4671                mPrevPhraseButton.AccessibleName = Localizer.Message("Transport_PreviousPhraseAcc") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mPreviousPhraseToolStripMenuItem"].Value.ToString());
4672            }
4673            if (keyboardShortcuts.MenuNameDictionary.ContainsKey("mPreviousSectionToolStripMenuItem"))
4674            {
4675                mTransportBarTooltip.SetToolTip(mPrevSectionButton, Localizer.Message("Transport_PreviousSection") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mPreviousSectionToolStripMenuItem"].Value.ToString()) + ")");
4676                mPrevSectionButton.AccessibleName = Localizer.Message("Transport_PreviousSectionAcc") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mPreviousSectionToolStripMenuItem"].Value.ToString());
4677            }
4678
4679            if (keyboardShortcuts.MenuNameDictionary.ContainsKey("mPreviousPageToolStripMenuItem"))
4680            {
4681                mTransportBarTooltip.SetToolTip(mPreviousPageButton, Localizer.Message("Transport_PreviousPage") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mPreviousPageToolStripMenuItem"].Value.ToString()) + ")");
4682                mPreviousPageButton.AccessibleName = Localizer.Message("Transport_PreviousPageAcc") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mPreviousPageToolStripMenuItem"].Value.ToString());
4683            }
4684            if (keyboardShortcuts.MenuNameDictionary.ContainsKey("mRewindToolStripMenuItem"))
4685            {
4686                mTransportBarTooltip.SetToolTip(mRewindButton, Localizer.Message("Transport_FastPlayBackward") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mRewindToolStripMenuItem"].Value.ToString()) + ")");
4687                mRewindButton.AccessibleName = Localizer.Message("Transport_FastPlayBackwardAcc") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mRewindToolStripMenuItem"].Value.ToString());           
4688            }
4689
4690           
4691            mTransportBarTooltip.SetToolTip(mPlayButton, Localizer.Message("Transport_StartPlayback") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ProjectView_PlayPauseUsingAudioCursor_Default.Value.ToString()) + ")");
4692            mTransportBarTooltip.SetToolTip(mPauseButton, Localizer.Message("Transport_StartPlayback") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ProjectView_PlayPauseUsingAudioCursor_Default.Value.ToString()) + ")");
4693
4694            mPlayButton.AccessibleName = Localizer.Message("Transport_StartPlaybackAcc") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ProjectView_PlayPauseUsingAudioCursor_Default.Value.ToString());
4695            mPauseButton.AccessibleName = Localizer.Message("Transport_StartPausebackAcc") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ProjectView_PlayPauseUsingAudioCursor_Default.Value.ToString());
4696
4697            if (keyboardShortcuts.MenuNameDictionary.ContainsKey("mStopToolStripMenuItem"))
4698            {
4699                mTransportBarTooltip.SetToolTip(mStopButton, Localizer.Message("Transport_StopPlayback") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mStopToolStripMenuItem"].Value.ToString()) + ")");
4700                mStopButton.AccessibleName = Localizer.Message("Transport_StopPlaybackAcc") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mStopToolStripMenuItem"].Value.ToString());
4701            }
4702            if (keyboardShortcuts.MenuNameDictionary.ContainsKey("mStartMonitoringToolStripMenuItem"))
4703            {
4704                mTransportBarTooltip.SetToolTip(mRecordButton, Localizer.Message("Transport_StartRecording") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mStartMonitoringToolStripMenuItem"].Value.ToString()) + ")");
4705            }
4706            if (keyboardShortcuts.MenuNameDictionary.ContainsKey("mNextPhraseToolStripMenuItem"))
4707            {
4708                mTransportBarTooltip.SetToolTip(mNextPhrase, Localizer.Message("Transport_NextPhrase") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mNextPhraseToolStripMenuItem"].Value.ToString()) + ")");
4709                mNextPhrase.AccessibleName = Localizer.Message("Transport_NextPhrase") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mNextPhraseToolStripMenuItem"].Value.ToString());
4710            }
4711
4712            if (keyboardShortcuts.MenuNameDictionary.ContainsKey("mNextPageToolStripMenuItem"))
4713            {
4714                mTransportBarTooltip.SetToolTip(mNextPageButton, Localizer.Message("Transport_NextPage") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mNextPageToolStripMenuItem"].Value.ToString()) + ")");
4715                mNextPageButton.AccessibleName = Localizer.Message("Transport_NextPage") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mNextPageToolStripMenuItem"].Value.ToString());
4716            }
4717            if (keyboardShortcuts.MenuNameDictionary.ContainsKey("mNextSectionToolStripMenuItem"))
4718            {
4719                mTransportBarTooltip.SetToolTip(mNextSectionButton, Localizer.Message("Transport_NextSection") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mNextSectionToolStripMenuItem"].Value.ToString()) + ")");
4720                mNextSectionButton.AccessibleName = Localizer.Message("Transport_NextSection") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mNextSectionToolStripMenuItem"].Value.ToString());
4721            }
4722            if (keyboardShortcuts.MenuNameDictionary.ContainsKey("mPhrases_PhraseIsTODOMenuItem"))
4723            {
4724                mTransportBarTooltip.SetToolTip(mToDo_CustomClassMarkButton, Localizer.Message("Transport_AddTodo") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mPhrases_PhraseIsTODOMenuItem"].Value.ToString()) + ")");
4725                mToDo_CustomClassMarkButton.AccessibleName = Localizer.Message("Transport_AddTodoAcc") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mPhrases_PhraseIsTODOMenuItem"].Value.ToString());
4726            }
4727            if (keyboardShortcuts.MenuNameDictionary.ContainsKey("mFastForwardToolStripMenuItem"))
4728            {
4729                mTransportBarTooltip.SetToolTip(mFastForwardButton, Localizer.Message("Transport_FastPlayForward") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mFastForwardToolStripMenuItem"].Value.ToString()) + ")");
4730                mFastForwardButton.AccessibleName = Localizer.Message("Transport_FastPlayForwardAcc") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mFastForwardToolStripMenuItem"].Value.ToString()); 
4731            }
4732
4733            mTransportBarTooltip.SetToolTip(m_btnPlayingOptions, Localizer.Message("Transport_PlayingOptions") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ContentView_TransportBarExpandPlayOptions.Value.ToString()) + ")");
4734            m_btnPlayingOptions.AccessibleName = Localizer.Message("Transport_PlayingOptions") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ContentView_TransportBarExpandPlayOptions.Value.ToString());
4735
4736            mTransportBarTooltip.SetToolTip(m_btnRecordingOptions, Localizer.Message("Transport_RecordingOptions") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ContentView_TransportBarExpandRecordOptions.Value.ToString()) + ")");
4737            m_btnRecordingOptions.AccessibleName = Localizer.Message("Transport_RecordingOptions") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ContentView_TransportBarExpandRecordOptions.Value.ToString());
4738
4739            string tempSettingsName = mView.ObiForm.Settings.SettingsNameForManipulation;
4740            string[] str = tempSettingsName.Split(new string[] { "   " }, StringSplitOptions.None);
4741            mTransportBarTooltip.SetToolTip(m_btnSwitchProfile, Localizer.Message("Transport_SwitchProfile") + "\n" + str[0] + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ContentView_TransportBarExpandSwitchProfile.Value.ToString()) + ")");
4742            m_btnSwitchProfile.AccessibleName = Localizer.Message("Transport_SwitchProfile") + str[0] + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ContentView_TransportBarExpandSwitchProfile.Value.ToString());
4743
4744            mTransportBarTooltip.SetToolTip(mDisplayBox, mDisplayBox.SelectedItem.ToString());
4745           
4746        }
4747
4748        private void m_btnPlayingOptions_Click(object sender, EventArgs e)
4749        {
4750            Button btn = (Button)sender;
4751            Point ptLowerLeft = new Point(0, btn.Height);
4752            ptLowerLeft = btn.PointToScreen(ptLowerLeft);
4753            m_PlayingOptionsContextMenuStrip.Show(ptLowerLeft); 
4754        }
4755
4756        private void m_PlaySectiontoolStripMenuItem_Click(object sender, EventArgs e)
4757        {
4758            PlaySection();           
4759           
4760        }
4761        public void PlaySection()
4762        {
4763            EmptyNode phrase = null;
4764            ObiNode nodeSelect = null;
4765            if (mView != null && mView.Selection != null)
4766            {
4767
4768
4769                if (mView.Selection.Node is EmptyNode)
4770                {
4771                    phrase = (EmptyNode)mView.Selection.Node;
4772                    nodeSelect = phrase.ParentAs<SectionNode>();
4773                }
4774                else if (mView.Selection.Node is SectionNode)
4775                {
4776                    nodeSelect = mView.Selection.Node;
4777                }
4778                if (nodeSelect != null)
4779                {
4780
4781                    m_IsPlaySectionInspiteOfPhraseSelection = true;
4782                    double time = -1;
4783                    if (IsPlayerActive)
4784                    {
4785                        if (mCurrentPlaylist.CurrentPhrase == mView.Selection.Node) time = mCurrentPlaylist.CurrentTimeInAsset;
4786                    }
4787                    else if (mView.Selection is AudioSelection && ((AudioSelection)mView.Selection).AudioRange != null)
4788                    {
4789                        AudioSelection audioSel = (AudioSelection)mView.Selection;
4790                        if (audioSel.AudioRange.HasCursor) time = audioSel.AudioRange.CursorTime;
4791                        else time = audioSel.AudioRange.SelectionBeginTime;
4792                    }
4793
4794                    if (IsPlayerActive) Stop();
4795
4796                    if (time > 0  && mView.Selection.Node is PhraseNode) 
4797                    {
4798                        bool playOnNavigateStatus = SelectionChangedPlaybackEnabled;
4799                        SelectionChangedPlaybackEnabled = false;
4800                        mView.Selection = new AudioSelection((PhraseNode) mView.Selection.Node, mView.Selection.Control, new AudioRange(time));
4801                        SelectionChangedPlaybackEnabled = playOnNavigateStatus;
4802                        }
4803
4804                    try
4805                    {
4806                        PlayOrResume(nodeSelect);
4807                    }
4808                    catch (System.Exception ex)
4809                    {
4810                        mView.WriteToLogFile(ex.ToString());
4811                        if (mCurrentPlaylist != null) mCurrentPlaylist.ForcedStopForError();
4812                        MessageBox.Show(string.Format(Localizer.Message("TransportBar_PlayerExceptionMsg"), "\n\n", ex.ToString()));
4813                    }
4814                }
4815            }
4816        }
4817
4818        private void m_PlayAlltoolStripMenuItem_Click(object sender, EventArgs e)
4819        {
4820            if (!mView.ObiForm.Settings.Audio_PlaySectionUsingPlayBtn)
4821            {
4822                PlayAllSections();
4823            }
4824            else
4825            {
4826                PlayOrResume();
4827            }
4828
4829        }
4830        public void PlayAllSections()
4831        {
4832            if (!mView.IsZoomWaveformActive)//@zoomwaveform: if zoom waveform is not active, start play all else start play selection
4833            {
4834                PlayAll();
4835            }
4836            else
4837            {
4838                PlayOrResume();
4839            }
4840        }
4841
4842        private void m_PreviewFromtoolStripMenuItem_Click(object sender, EventArgs e)
4843        {
4844            Preview(From, UseAudioCursor);
4845        }
4846
4847        private void m_PreviewUptotoolStripMenuItem_Click(object sender, EventArgs e)
4848        {
4849            Preview(Upto, UseAudioCursor);
4850        }
4851
4852        private void m_PlayingOptionsContextMenuStrip_Opening(object sender, System.ComponentModel.CancelEventArgs e)
4853        {
4854            if (!mView.ObiForm.Settings.Audio_PlaySectionUsingPlayBtn)
4855            {
4856                m_PlayAlltoolStripMenuItem.Enabled = mView.CanPlay || mView.CanResume;
4857            }
4858            else
4859            {
4860                m_PlayAlltoolStripMenuItem.Enabled = mView.CanPlaySelection || mView.CanResume;
4861            }
4862            m_PlaySectiontoolStripMenuItem.Enabled = mView.CanPlaySelection || mView.CanResume;
4863            m_playHeadingToolStripMenuItem.Enabled = mView.CanPlaySelection || mView.CanResume;
4864
4865            m_PreviewFromtoolStripMenuItem.Enabled = mView.CanPreview || mView.CanPreviewAudioSelection;
4866            m_PreviewUptotoolStripMenuItem.Enabled = mView.CanPreview || mView.CanPreviewAudioSelection;
4867           
4868        }
4869
4870        private void mPreviewBeforeRecToolStripMenuItem_Click(object sender, EventArgs e)
4871        {
4872            PreviewBeforeRecording();
4873        }
4874        public void PreviewBeforeRecording()
4875        {
4876            StartRecordingDirectly(true);
4877        }
4878
4879        public bool PreviewBeforeRecordingActive
4880        {
4881            get { return m_PreviewBeforeRecordingActive; }
4882        }
4883
4884        private void m_playHeadingToolStripMenuItem_Click(object sender, EventArgs e)
4885        {
4886            PlayHeading();       
4887           
4888        }
4889        public void PlayHeading()
4890        {
4891            PhraseNode pharse = null;
4892            SectionNode nodeSelect = null;
4893            EmptyNode emptyNode = null;
4894            if (mView != null )
4895            {
4896                if (mView.Selection == null)
4897                {
4898                    nodeSelect = mView.Presentation.FirstSection;
4899                }
4900                if (mView.Selection.Node is EmptyNode)
4901                {
4902                    nodeSelect = mView.Selection.Node.ParentAs<SectionNode>();
4903                }
4904                else if (mView.Selection.Node is SectionNode)
4905                {
4906                    nodeSelect = (SectionNode)mView.Selection.Node;
4907                }
4908               
4909                if (nodeSelect != null)
4910                {
4911                    if (IsPlayerActive) Stop();
4912                    PlayHeadingPhrase(nodeSelect);
4913                }
4914            }
4915        }
4916        public bool ExpandPlayOptions()
4917        {
4918            if (m_btnPlayingOptions.Enabled)
4919            {
4920                Point pt = new Point(0, m_btnPlayingOptions.Height);
4921                pt = m_btnPlayingOptions.PointToScreen(pt);
4922                m_PlayingOptionsContextMenuStrip.Show(pt);
4923                return true;
4924            }
4925            else
4926            {
4927                return false;
4928            }
4929           
4930        }
4931        public bool ExpandRecordOptions()
4932        {
4933            if (m_btnRecordingOptions.Enabled)
4934            {
4935                Point pt = new Point(0, m_btnRecordingOptions.Height);
4936                pt = m_btnRecordingOptions.PointToScreen(pt);
4937                m_RecordingOptionsContextMenuStrip.Show(pt);
4938                return true;
4939            }
4940            else
4941            {
4942                return false;
4943            }
4944
4945        }
4946        public bool ExpandSwitchProfile()
4947        {
4948            if (m_btnSwitchProfile.Enabled)
4949            {
4950                Point pt = new Point(0, m_btnSwitchProfile.Height);
4951                pt = m_btnSwitchProfile.PointToScreen(pt);
4952                m_SwitchProfileContextMenuStrip.Show(pt);
4953                ShowSwitchProfileContextMenu();
4954                return true;
4955            }
4956            else
4957            {
4958                return false;
4959            }
4960
4961        }
4962
4963        public bool IsPreviewBeforeRecordingEnabled
4964        {
4965            get
4966            {
4967                if (mView != null && mView.ObiForm != null && mView.ObiForm.Settings != null && mView.Selection != null && CurrentState != State.Monitoring
4968&& mView.ObiForm.Settings.Audio_AllowOverwrite && ((CurrentState == State.Paused && !(mView.Selection is AudioSelection)) || (mView.Selection != null && mView.Selection is AudioSelection && ((AudioSelection)mView.Selection).AudioRange != null && ((AudioSelection)mView.Selection).AudioRange.HasCursor)))
4969                {
4970                    return true;
4971                }
4972                else
4973                {
4974                    return false;
4975                }
4976
4977            }
4978        }
4979
4980        //@MonitorContinuously
4981        public bool MonitorContinuously
4982        {
4983            get { return m_MonitorContinuously; }
4984            set
4985            {
4986                Console.WriteLine("value of monitor continuously" + value);
4987                if (value && mView.ObiForm != null )
4988                {
4989                   
4990                    m_MonitorContinuously = value;
4991                    StartMonitorContinuously();
4992                }
4993                else
4994                {
4995                    StopMonitorContinuously();
4996                    m_MonitorContinuously = value;
4997                    // trigger state changed event again because the MonitorContinuesly goes false after the state changed event
4998                    if (StateChanged != null) StateChanged(this, new AudioLib.AudioPlayer.StateChangedEventArgs(mPlayer.CurrentState));
4999                }
5000               
5001            }
5002        }
5003
5004        //@MonitorContinuously
5005        private void StartMonitorContinuously()
5006        {
5007            if (m_MonitorContinuously && mPlayer.CurrentState == AudioLib.AudioPlayer.State.Stopped && mRecorder.CurrentState == AudioLib.AudioRecorder.State.Stopped)
5008            {
5009                mRecordingSession = new RecordingSession(mView.Presentation, mRecorder, mView.ObiForm.Settings);
5010                mRecordingSession.StartMonitoring();
5011                mVUMeterPanel.BeepEnable = true;
5012            }
5013        }
5014
5015        //@MonitorContinuously
5016        private void StopMonitorContinuously()
5017        {
5018            if (m_MonitorContinuously && mRecordingSession != null && mRecorder.CurrentState == AudioLib.AudioRecorder.State.Monitoring)
5019            {
5020                mRecordingSession.Stop();
5021                mRecordingSession = null;
5022                mVUMeterPanel.BeepEnable = false;                 
5023            }
5024        }
5025
5026        //@MonitorContinuously
5027        System.ComponentModel.BackgroundWorker m_MonitorContinuouslyWorker= null;
5028        private void StartMonitorContinuouslyWithDelay()
5029        {
5030            m_MonitorContinuouslyWorker = new System.ComponentModel.BackgroundWorker();
5031                m_MonitorContinuouslyWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(delegate(object sender, System.ComponentModel.DoWorkEventArgs e)
5032                {
5033                    Thread.Sleep(1500);
5034                 });
5035
5036m_MonitorContinuouslyWorker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(delegate(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
5037                {
5038                    if (m_MonitorContinuously && CurrentState == State.Stopped)
5039                    {
5040                        StartMonitorContinuously();
5041                    }
5042                });
5043m_MonitorContinuouslyWorker.RunWorkerAsync();
5044               
5045        }
5046
5047        private void mMonitorContinuouslyToolStripMenuItem_Click(object sender, EventArgs e)
5048        {
5049            if (mMonitorContinuouslyToolStripMenuItem.Checked)
5050            {
5051                MonitorContinuously = true;
5052            }
5053            else
5054            {
5055                MonitorContinuously = false;
5056            }
5057        }
5058
5059        private void m_SwitchProfile_Click(object sender, EventArgs e)
5060        {
5061            Point pt = new Point(0, m_btnSwitchProfile.Height);
5062            pt = m_btnSwitchProfile.PointToScreen(pt);
5063            m_SwitchProfileContextMenuStrip.Show(pt);
5064            ShowSwitchProfileContextMenu();
5065        }
5066        public void ShowSwitchProfileContextMenu()
5067        {
5068
5069            string[] str = mView.ObiForm.Settings.SettingsNameForManipulation.Split(new string[] { "   " }, StringSplitOptions.None);
5070            //     if (m_CurrentCheckedProfile == null || m_CurrentCheckedProfile.ToString() != str[0])
5071
5072            if (m_ListOfSwitchProfiles.ContainsKey(str[0]))
5073            {
5074                if (m_CurrentCheckedProfile != null)
5075                {
5076                    m_CurrentCheckedProfile.Checked = false;
5077                }
5078                ToolStripMenuItem ProfileSelected = m_ListOfSwitchProfiles[str[0]];
5079                ProfileSelected.Checked = true;
5080                m_CurrentCheckedProfile = ProfileSelected;
5081                mTransportBarTooltip.SetToolTip(m_btnSwitchProfile, Localizer.Message("Transport_SwitchProfile") + "\n" + str[0] + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ContentView_TransportBarExpandSwitchProfile.Value.ToString()) + ")");
5082                m_btnSwitchProfile.AccessibleName = Localizer.Message("Transport_SwitchProfile") + str[0] + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ContentView_TransportBarExpandSwitchProfile.Value.ToString());
5083                mView.ObiForm.UpdateTitle();
5084
5085            }
5086
5087        }
5088
5089        public void SetFont()//@fontconfig
5090        {
5091            mTransportBarTooltip.OwnerDraw = true;
5092            mTransportBarTooltip.IsBalloon = false;
5093            this.Font = new Font(mView.ObiForm.Settings.ObiFont, this.Font.Size, FontStyle.Regular);
5094            m_PlayingOptionsContextMenuStrip.Font = m_RecordingOptionsContextMenuStrip.Font = new Font(mView.ObiForm.Settings.ObiFont, this.Font.Size, FontStyle.Regular);
5095        }
5096        private void mTransportBarTooltip_Draw(object sender, DrawToolTipEventArgs e)//@fontconfig
5097        {
5098            Font tooltipFont = new Font(mView.ObiForm.Settings.ObiFont, this.Font.Size);
5099            Font tooltipTitleFont = new Font(mView.ObiForm.Settings.ObiFont, this.Font.Size, FontStyle.Bold);
5100            e.Graphics.Clear(Color.White);
5101
5102            e.Graphics.DrawString(mTransportBarTooltip.ToolTipTitle, tooltipTitleFont, Brushes.Blue, new PointF(0, 0));
5103            e.Graphics.DrawString(" \n" + e.ToolTipText, tooltipFont, Brushes.Black, new PointF(0, 0));
5104
5105        }
5106
5107        private void mTransportBarTooltip_Popup(object sender, PopupEventArgs e)//@fontconfig
5108        {
5109            e.ToolTipSize = TextRenderer.MeasureText(mTransportBarTooltip.ToolTipTitle + "\n" + mTransportBarTooltip.GetToolTip(e.AssociatedControl), new Font(mView.ObiForm.Settings.ObiFont, this.Font.Size));
5110        }
5111
5112        private System.Text.StringBuilder m_MissedNotificationMessages = new System.Text.StringBuilder();
5113        private void LogRecorderMissedNotificationMsg(object sender, AudioLib.AudioRecorder.CircularBufferNotificationTimerMessageEventArgs e)
5114        {
5115            if (e != null && !string.IsNullOrEmpty(e.Msg))
5116            {
5117                m_MissedNotificationMessages.AppendLine(e.Msg);
5118                if (m_MissedNotificationMessages != null &&  m_MissedNotificationMessages.Length > 4000)
5119                {
5120                    WriteLogMsgForRecorderMissedNotification();
5121                }
5122            }
5123        }
5124
5125        private void WriteLogMsgForRecorderMissedNotification ()
5126        {
5127            if (m_MissedNotificationMessages != null &&  m_MissedNotificationMessages.Length > 0)
5128            {
5129                m_MissedNotificationMessages.AppendLine("adding next set of missed notification messages");
5130                mView.WriteToLogFile(m_MissedNotificationMessages.ToString());
5131                m_MissedNotificationMessages = null;
5132                m_MissedNotificationMessages = new System.Text.StringBuilder();
5133            }
5134        }
5135
5136
5137    }
5138}
Note: See TracBrowser for help on using the repository browser.