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

Revision 7623, 253.8 KB checked in by avneesh-singh, 4 months ago (diff)

Added todo time in command

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()
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                NextPhrase();
4063            }
4064            else if (IsPlayerActive)
4065            {
4066                node = (EmptyNode)mCurrentPlaylist.CurrentPhrase;
4067                if (node != null)
4068                {
4069                    mView.Presentation.Changed -= new EventHandler<urakawa.events.DataModelChangedEventArgs>(Presentation_Changed);
4070                    if (node is PhraseNode && node.Duration > 0 && mCurrentPlaylist != null)
4071                    {
4072                        mView.Presentation.UndoRedoManager.Execute(new Commands.Node.ToggleNodeTODO(mView, node, mCurrentPlaylist.CurrentTimeInAsset));
4073                }
4074                else
4075                    {
4076                    mView.Presentation.UndoRedoManager.Execute(new Commands.Node.ToggleNodeTODO(mView, node));
4077                }
4078                    mView.Presentation.Changed += new EventHandler<urakawa.events.DataModelChangedEventArgs>(Presentation_Changed);
4079                }
4080
4081            }
4082        else if (mView.Selection != null && mView.Selection.Node is EmptyNode)
4083            {
4084            node  = (EmptyNode)mView.Selection.Node;
4085            mView.Presentation.Changed -= new EventHandler<urakawa.events.DataModelChangedEventArgs> ( Presentation_Changed );
4086            if (node != null && node is PhraseNode && node.Duration > 0 && mView.Selection is AudioSelection)
4087            {
4088                AudioSelection selection = mView.Selection as AudioSelection;
4089                double todoTime = selection.AudioRange.HasCursor ? selection.AudioRange.CursorTime :
4090                    selection.AudioRange.SelectionBeginTime;
4091                if (todoTime > 0 && todoTime < node.Duration) mView.Presentation.UndoRedoManager.Execute(new Commands.Node.ToggleNodeTODO(mView, node, todoTime));
4092            }
4093            else
4094            {
4095                mView.Presentation.UndoRedoManager.Execute(new Commands.Node.ToggleNodeTODO(mView, node));
4096            }
4097            mView.Presentation.Changed += new EventHandler<urakawa.events.DataModelChangedEventArgs> ( Presentation_Changed );
4098               
4099            }
4100           
4101        }
4102
4103
4104        private void PlaybackOnSelectionChange_Safe ()
4105            {
4106            if (mView.Selection != null && !(mView.Selection is TextSelection)
4107                &&mView.Selection.Node is ObiNode)
4108                {
4109                try
4110                    {
4111                    m_PlayOnSelectionChangedMutex.WaitOne ();
4112                    PlaybackOnSelectionChange ();
4113                    m_PlayOnSelectionChangedMutex.ReleaseMutex ();
4114                    }
4115                catch (System.Exception)
4116                    {
4117                    m_PlayOnSelectionChangedMutex.ReleaseMutex ();
4118                    return;
4119                    }
4120                }
4121            }
4122
4123        public bool SkipPlayOnNavigateForSection { set { m_SkipPlayOnNavigateForSection = value; } } 
4124        private bool m_SkipPlayOnNavigateForSection = false;
4125        private void PlaybackOnSelectionChange ()
4126        {
4127            if (IsRecorderActive) return;
4128            if (m_SkipPlayOnNavigateForSection && (mView.Selection == null || mView.Selection.Node is SectionNode))
4129            {
4130                m_SkipPlayOnNavigateForSection = false;
4131                return;
4132            }
4133            if (mView.Selection != null && !(mView.Selection is StripIndexSelection))
4134            {
4135                if (mState == State.Playing || mState == State.Paused)
4136                {
4137                    ObiNode node = mView.Selection.Node;
4138                    PhraseNode PNode = null;
4139
4140                    if (node is PhraseNode)
4141                        PNode = (PhraseNode)node;
4142                    else if (node is SectionNode)
4143                    {
4144                        if (((SectionNode)node).PhraseChildCount > 0 )
4145                            {
4146                            if ( mCurrentPlaylist != mMasterPlaylist &&  ((SectionNode)node).PhraseChild(0) is PhraseNode)
4147                            PNode = (PhraseNode)((SectionNode)node).PhraseChild(0);
4148                            else // start finding required phrase node in this section
4149                                {
4150                                for (int PIndex = 0; PIndex < node.PhraseChildCount; PIndex++)
4151                                    {
4152                                    if (node.PhraseChild ( PIndex ) is PhraseNode && node.PhraseChild ( PIndex ).Used)
4153                                        {
4154                                        PNode = (PhraseNode)((SectionNode)node).PhraseChild ( PIndex );
4155                                        break;
4156                                        }
4157                                    } // for loop ends
4158
4159                                }
4160                            }
4161                    }
4162
4163                if (PNode != null && mCurrentPlaylist.ContainsPhrase ( PNode ))
4164                    {// 1
4165                    if (PNode != mCurrentPlaylist.CurrentPhrase) // if selected node is not currently playing phrase
4166                        { //2
4167                        if (mView.Selection.Control.GetType () != typeof ( TOCView )
4168                            || mCurrentPlaylist.CurrentPhrase.ParentAs<SectionNode> () != PNode.ParentAs<SectionNode> ()) // bypass if selection is in TOC and playing section is same as selected section
4169                            { //3
4170                            if (mPlayer.CurrentState == AudioLib.AudioPlayer.State.Paused) mCurrentPlaylist.Stop ();
4171
4172                            mCurrentPlaylist.CurrentPhrase = PNode;
4173                            if (mView.Selection is AudioSelection) mCurrentPlaylist.CurrentTimeInAsset = ((AudioSelection)mView.Selection).AudioRange.CursorTime;
4174                            } //-3
4175                        } //-2
4176                    else if (mView.Selection is AudioSelection && ((AudioSelection)mView.Selection).AudioRange.HasCursor) // clicked on the same phrase
4177                        mCurrentPlaylist.CurrentTimeInAsset = ((AudioSelection)mView.Selection).AudioRange.CursorTime;
4178                    } //-1
4179                else if (mCurrentPlaylist == mMasterPlaylist) // newly selected phrase is not in master paylist
4180                    Stop ();
4181
4182                    if (mCurrentPlaylist != mMasterPlaylist
4183                        && !mCurrentPlaylist.ContainsPhrase(PNode))
4184                    {
4185                        if (mState == State.Playing)
4186                        {
4187                            mView.SetPlaybackPhraseAndTime(null, 0.0);
4188                            mCurrentPlaylist.Stop();
4189                            //if (mView.Selection.Node is PhraseNode)
4190                                //PlayOrResume();
4191                            if (mView.Selection.Node is SectionNode && mView.ObiForm.Settings.PlayOnNavigate)
4192                                PlayHeadingPhrase(mView.SelectedNodeAs<SectionNode>());
4193                        }
4194                        else
4195                        {
4196                            mView.SetPlaybackPhraseAndTime(null, 0.0);
4197                            mCurrentPlaylist.Stop();
4198                        }
4199                    }
4200                }
4201                if (mView.ObiForm.Settings.PlayOnNavigate
4202                    &&
4203                    (mState == State.Paused || mState == State.Stopped))
4204                {
4205                    if (mView.Selection.Node is SectionNode)
4206                        PlayHeadingPhrase(mView.SelectedNodeAs<SectionNode>());
4207                    else if (mView.Selection.Node is PhraseNode)
4208                        PlayOrResume();
4209                }
4210                if (mView.ObiForm.Settings.Audio_ShowSelectionTimeInTransportBar && mState == State.Stopped)
4211                {
4212                    UpdateTimeDisplay();
4213                }
4214                                        }// end of selection null check
4215
4216        }
4217
4218        public void PlayHeadingPhrase( SectionNode node     )
4219        {
4220            if ( node != null  && node.PhraseChildCount > 0  )
4221            {
4222                EmptyNode ENode = node.PhraseChild(0);
4223                   
4224                for (int i = 0; i < node.PhraseChildCount ; i++)
4225                {
4226                    if (((EmptyNode)node.PhraseChild(i)).Role_ == EmptyNode.Role.Heading)
4227                    {
4228                        ENode = node.PhraseChild(i);
4229                                                break;
4230                    }
4231                                    }
4232
4233                                    if (ENode is PhraseNode)
4234                                    {
4235                                        mLocalPlaylist = new Playlist(mPlayer, ENode ,mPlayQAPlaylist);
4236                                        SetPlaylistEvents(mLocalPlaylist);
4237                                        mCurrentPlaylist = mLocalPlaylist;
4238                                        mCurrentPlaylist.CurrentPhrase = (PhraseNode) ENode ;
4239                                        if (mCurrentPlaylist.State != AudioLib.AudioPlayer.State.Playing) mCurrentPlaylist.Play();
4240                                                                                //PlayOrResume(node.PhraseChild(0));
4241                                    }
4242            }
4243        }
4244
4245
4246        public enum AudioCluesSelection { SelectionBegin, SelectionEnd } ;
4247
4248        public void PlayAudioClue(AudioCluesSelection Clue)
4249        {
4250            if ( mView.ObiForm.Settings.Audio_AudioClues )
4251            {
4252            if (Clue == AudioCluesSelection.SelectionBegin)
4253            {
4254                string FilePath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "SelectionBegin.wav");
4255                if ( System.IO.File.Exists (FilePath))
4256                                    new System.Media.SoundPlayer(FilePath).Play ()  ;
4257                                                }
4258            else if (Clue == AudioCluesSelection.SelectionEnd)
4259            {
4260                string FilePath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "SelectionEnd.wav");
4261                if (System.IO.File.Exists(FilePath))
4262                                    new System.Media.SoundPlayer(FilePath).Play();
4263            }
4264            }
4265                    }
4266
4267
4268        #endregion
4269
4270        public bool FocusOnTimeDisplay()
4271        {
4272            return mTimeDisplayBox.Focus();
4273        }
4274
4275        /// <summary>
4276        ///  Process dialog key overridden to prevent tab  from  moving focus out of transportbar
4277        /// </summary>
4278        /// <param name="KeyData"></param>
4279        /// <returns></returns>
4280        protected override bool ProcessDialogKey(Keys KeyData)
4281        {
4282            if (KeyData == Keys.Tab
4283                && this.ActiveControl != null)
4284            {
4285                Control c = this.ActiveControl;
4286                this.SelectNextControl(c, true, true, true, true);
4287                if (this.ActiveControl != null && c.TabIndex > this.ActiveControl.TabIndex)
4288                    System.Media.SystemSounds.Beep.Play();
4289                return true;
4290            }
4291            else if (KeyData == (Keys)(Keys.Shift | Keys.Tab)
4292                && this.ActiveControl != null)
4293            {
4294                Control c = this.ActiveControl;
4295                this.SelectNextControl(c, false, true, true, true);
4296                if (this.ActiveControl != null && c.TabIndex < this.ActiveControl.TabIndex)
4297                    System.Media.SystemSounds.Beep.Play();
4298
4299                return true;
4300            }
4301            else
4302            {
4303                return base.ProcessDialogKey(KeyData);
4304            }
4305        }
4306
4307        // Create the preview playlist
4308        private void CreateLocalPlaylistForPreview(PhraseNode node,  double revertTime, bool useSelection)
4309        {
4310            PreviewPlaylist playlist = useSelection ? new PreviewPlaylist(mPlayer, mView.Selection, revertTime) :
4311                new PreviewPlaylist(mPlayer, node , revertTime);
4312            SetPlaylistEvents(playlist);
4313            mCurrentPlaylist = playlist;
4314        }
4315
4316       
4317
4318        public bool CanUsePlaybackSelection { get { return Enabled && IsPlayerActive && mView.ObiForm.Settings.PlayOnNavigate; }}
4319
4320        public void mView_BlocksVisibilityChanged ( object sender, EventArgs e )
4321            {
4322            UpdateButtons ();
4323            }
4324
4325        private void mDisplayBox_DropDown(object sender, EventArgs e)
4326        {
4327            mDisplayBox.Tag = mDisplayBox.SelectedIndex;
4328        }
4329
4330        private bool m_FineNavigationModeForPhrase = false ;
4331        private EmptyNode m_FineNavigationPhrase = null;
4332        public bool FineNavigationModeForPhrase
4333        {
4334            get
4335            {
4336                return m_FineNavigationModeForPhrase;
4337            }
4338            set
4339            {
4340                if (value != m_FineNavigationModeForPhrase)
4341                {
4342                    m_FineNavigationModeForPhrase = value;
4343                    if (m_FineNavigationModeForPhrase)
4344                    {
4345                        m_FineNavigationPhrase = mView.Selection.EmptyNodeForSelection;
4346                        mView.UpdateBlockForFindNavigation(m_FineNavigationPhrase, m_FineNavigationModeForPhrase);   
4347                        string navigationOnClue = System.IO.Path.Combine ( System.AppDomain.CurrentDomain.BaseDirectory, "FineNavigationOn.wav") ;
4348                        if (mView.ObiForm.Settings.Audio_AudioClues &&  System.IO.File.Exists(navigationOnClue))
4349                        {
4350                            System.Media.SoundPlayer player = new System.Media.SoundPlayer(navigationOnClue);
4351                            player.Play();
4352                        }
4353                        // add sound here
4354                    }
4355                    else
4356                    {
4357                        if (m_FineNavigationPhrase != null) mView.UpdateBlockForFindNavigation(m_FineNavigationPhrase, m_FineNavigationModeForPhrase);
4358                        m_FineNavigationPhrase = null;
4359                        if(mView.ObiForm.Settings.Audio_AudioClues)  System.Media.SystemSounds.Exclamation.Play();
4360                        // add sound here
4361                    }
4362                   
4363
4364                    if (StateChanged != null) StateChanged(this, new AudioLib.AudioPlayer.StateChangedEventArgs(mPlayer.CurrentState) );
4365                }
4366            }
4367        }
4368
4369        public string FineNavigationStatusMsg
4370        {
4371            get { return FineNavigationModeForPhrase ? Localizer.Message ("StatusMsg_FineNavigation") : ""; }
4372        }
4373
4374        public string GetHelpTopicPath()
4375        {
4376            if (mTimeDisplayBox.ContainsFocus || mDisplayBox.ContainsFocus)
4377            {
4378                return "HTML Files\\Exploring the GUI\\Obi Views and Transport Bar\\Time Display.htm";
4379            }
4380            else if (mVUMeterPanel.ContainsFocus)
4381            {
4382                return "HTML Files\\Exploring the GUI\\Obi Views and Transport Bar\\Textual peak meter.htm";
4383            }
4384            else if (mFastPlayRateCombobox.ContainsFocus)
4385            {
4386                return "HTML Files\\Creating a DTB\\Working with Audio\\Fast Play.htm";
4387            }
4388            else if (mToDo_CustomClassMarkButton.ContainsFocus)
4389            {
4390                return "HTML Files\\Creating a DTB\\Working with Phrases\\Changing the Todo or Used Status.htm";
4391            }
4392            else
4393            { return "HTML Files\\Exploring the GUI\\Obi Views and Transport Bar\\Audio and Navigation controls.htm"; }
4394        }
4395
4396
4397        private void m_btnRecordingOptions_Click(object sender, EventArgs e)
4398        {
4399            Button btn = (Button)sender;
4400            Point ptLowerLeft = new Point(0, btn.Height);
4401            ptLowerLeft = btn.PointToScreen(ptLowerLeft);
4402            m_RecordingOptionsContextMenuStrip.Show(ptLowerLeft); 
4403
4404        }
4405
4406        private void RecordingOptions_Monitoring_Click(object sender, EventArgs e)
4407        {
4408            if (CanResumePlayback || mState == State.Stopped)
4409            {
4410                if (MonitorContinuously) StopMonitorContinuously(); //@MonitorContinuously
4411                SetupRecording(Monitoring, false); 
4412            }
4413        }
4414
4415        private void RecordingOptions_RecordWithDeleteFollowing_Click(object sender, EventArgs e)
4416        {
4417            RecordOverSubsequentPhrases();
4418        }
4419
4420        public void RecordOverSubsequentPhrases()
4421        {
4422            if (CanRecord )
4423            {
4424                if (mView.ObiForm.Settings.Audio_AllowOverwrite && CurrentState == State.Playing) Pause(); //@recordFromPlay
4425                //StartRecordingDirectly_Internal(true); //@deleterecording
4426                StartRecordingDirectly_Internal(CanRecordOnFollowingAudio);
4427            }
4428        }
4429
4430        private void m_RecordingtoolStripMenuItem_Click(object sender, EventArgs e)
4431        {
4432            this.Record();
4433        }
4434
4435        private void m_RecordingOptionsContextMenuStrip_Opening(object sender, System.ComponentModel.CancelEventArgs e)
4436        {
4437            if (IsPreviewBeforeRecordingEnabled)           
4438            {
4439                mPreviewBeforeRecToolStripMenuItem.Enabled = true;
4440            }
4441            else
4442            {
4443                mPreviewBeforeRecToolStripMenuItem.Enabled = false;
4444            }
4445
4446            if (mView.ObiForm.Settings.Audio_AllowOverwrite)
4447            {
4448                m_DeletePhrasestoolStripMenuItem.Enabled = !IsListening;
4449            }
4450            else
4451            {
4452                m_DeletePhrasestoolStripMenuItem.Enabled = false;
4453            }
4454
4455            mMonitorContinuouslyToolStripMenuItem.Checked = MonitorContinuously;//@MonitorContinuously
4456
4457        }
4458
4459        public string GetPredefinedProfilesDirectory()
4460        {
4461            string appDirectory = System.AppDomain.CurrentDomain.BaseDirectory;
4462            string defaultProfilesDirectory = System.IO.Path.Combine(appDirectory, "profiles");
4463            return defaultProfilesDirectory;
4464        }
4465
4466        public string GetCustomProfilesDirectory()
4467        {
4468            string ProfileDirectory = System.IO.Directory.GetParent(Settings_Permanent.GetSettingFilePath()).ToString();
4469            string customProfilesDirectory = System.IO.Path.Combine(ProfileDirectory, "profiles");
4470            return customProfilesDirectory;
4471        }
4472        public string[] ProfilesPaths
4473        {
4474            get
4475            {
4476                return m_filePaths;
4477            }
4478        }
4479        public void RemoveProfileFromSwitchProfile(string profileToRemove)
4480        {           
4481            if (m_ListOfSwitchProfiles.ContainsKey(profileToRemove))
4482            {
4483                m_SwitchProfileContextMenuStrip.Items.Remove(m_ListOfSwitchProfiles[profileToRemove]);
4484                m_ListOfSwitchProfiles.Remove(profileToRemove);
4485            } 
4486        }
4487        public void AddProfileToSwitchProfile(string profileToAdd)
4488        {
4489            ToolStripMenuItem SwitchProfile = new ToolStripMenuItem(profileToAdd, null, SwitchProfile_Click);
4490            m_SwitchProfileContextMenuStrip.Items.Add(SwitchProfile);
4491            m_ListOfSwitchProfiles.Add(profileToAdd, SwitchProfile);           
4492        }
4493        // To Initialize Switch Profile ToolStrip menu Items
4494        public void InitializeSwitchProfiles()
4495        {
4496            //string ProfileDirectory = System.AppDomain.CurrentDomain.BaseDirectory;
4497            //string defaultProfilesDirectory = System.IO.Path.Combine(ProfileDirectory, "profiles");
4498            m_ListOfSwitchProfiles.Clear();
4499            m_SwitchProfileContextMenuStrip.Items.Clear();
4500            m_CurrentCheckedProfile = null;
4501            string ProfileDirectory = GetPredefinedProfilesDirectory();
4502            m_filePaths = System.IO.Directory.GetFiles(ProfileDirectory, "*.xml");
4503            List<string> filePathsList = new List<string>();
4504            if (m_filePaths != null && m_filePaths.Length > 0)
4505            {
4506                //string[] profileFileNames = new string[m_filePaths.Length];
4507                for (int i = 0; i < m_filePaths.Length; i++)
4508                {
4509                    filePathsList.Add(System.IO.Path.GetFileNameWithoutExtension(m_filePaths[i]));
4510                    //   m_cb_SelectProfile.Items.Add(System.IO.Path.GetFileNameWithoutExtension(m_filePaths[i]));
4511                }
4512               
4513                if (filePathsList.Contains("Basic"))
4514                {
4515                    int index = filePathsList.IndexOf("Basic");
4516                    ToolStripMenuItem SwitchProfile = new ToolStripMenuItem(filePathsList[index], null, SwitchProfile_Click);
4517                    m_SwitchProfileContextMenuStrip.Items.Add(SwitchProfile);
4518                    m_ListOfSwitchProfiles.Add(filePathsList[index], SwitchProfile);
4519                    filePathsList.RemoveAt(index);
4520                }
4521                if (filePathsList.Contains("Intermediate"))
4522                {
4523                    int index = filePathsList.IndexOf("Intermediate");
4524                    ToolStripMenuItem SwitchProfile = new ToolStripMenuItem(filePathsList[index], null, SwitchProfile_Click);
4525                    m_SwitchProfileContextMenuStrip.Items.Add(SwitchProfile);
4526                    m_ListOfSwitchProfiles.Add(filePathsList[index], SwitchProfile);
4527                    filePathsList.RemoveAt(index);
4528                }
4529                foreach (string file in filePathsList)
4530                {
4531                    ToolStripMenuItem SwitchProfile = new ToolStripMenuItem(file, null, SwitchProfile_Click);
4532                    m_SwitchProfileContextMenuStrip.Items.Add(SwitchProfile);
4533                    m_ListOfSwitchProfiles.Add(file, SwitchProfile);                 
4534                }
4535
4536            }
4537
4538            //ProfileDirectory = System.IO.Directory.GetParent(Settings_Permanent.GetSettingFilePath()).ToString();
4539            //ProfileDirectory = System.IO.Path.Combine(ProfileDirectory, "profiles");
4540            ProfileDirectory = GetCustomProfilesDirectory();
4541            if (System.IO.Directory.Exists(ProfileDirectory))
4542            {
4543                string[] temp =  System.IO.Directory.GetFiles(ProfileDirectory, "*.xml");
4544                string[] tempFilePaths = new string[m_filePaths.Length + temp.Length];
4545                m_filePaths.CopyTo(tempFilePaths, 0);
4546                temp.CopyTo(tempFilePaths, m_filePaths.Length);
4547                m_filePaths = tempFilePaths;
4548
4549
4550                if (temp != null && temp.Length > 0)
4551                {
4552                    for (int i = 0; i < temp.Length; i++)
4553                    {
4554                        string filename = System.IO.Path.GetFileNameWithoutExtension(temp[i]);
4555                        if (!m_ListOfSwitchProfiles.ContainsKey(filename))
4556                        {
4557                            ToolStripMenuItem SwitchProfile = new ToolStripMenuItem(filename, null, SwitchProfile_Click);
4558                            m_SwitchProfileContextMenuStrip.Items.Add(SwitchProfile);
4559                            m_ListOfSwitchProfiles.Add(filename, SwitchProfile);
4560                        }
4561
4562                    }
4563                }
4564            }// directory exists check
4565
4566            if (mView != null && mView.ObiForm != null && mView.ObiForm.Settings != null)
4567            {
4568                mView.ObiForm.UpdateTitle();
4569            }
4570        }
4571        // LoadProfile is used to Load Profile from RT toggle and Transport bar Switch profile button.
4572        public void LoadProfile(string profilePath, string ProfileName)
4573        {
4574            if (this.MonitorContinuously) this.MonitorContinuously = false;
4575            if (this.IsRecorderActive || this.IsPlayerActive) this.Stop();
4576            Settings saveProfile = Settings.GetSettingsFromSavedProfile(profilePath);
4577            saveProfile.CopyPropertiesToExistingSettings(mView.ObiForm.Settings, PreferenceProfiles.Audio,ProfileName);
4578            saveProfile.CopyPropertiesToExistingSettings(mView.ObiForm.Settings, PreferenceProfiles.Colors,ProfileName);
4579            saveProfile.SettingsName = ProfileName;
4580            string strLoadedProfiles = " ";
4581            if (saveProfile.Compare(mView.ObiForm.Settings, PreferenceProfiles.All))
4582            {
4583                strLoadedProfiles += "all";
4584            }
4585            else
4586            {
4587                if (saveProfile.Compare(mView.ObiForm.Settings, PreferenceProfiles.Project))
4588                {
4589                    strLoadedProfiles += "project, ";
4590                }
4591                if (saveProfile.Compare(mView.ObiForm.Settings, PreferenceProfiles.Audio))
4592                {
4593                    strLoadedProfiles += "audio, ";
4594                }
4595                if (saveProfile.Compare(mView.ObiForm.Settings, PreferenceProfiles.UserProfile))
4596                {
4597                    strLoadedProfiles += "users profile, ";
4598                }
4599                if (saveProfile.Compare(mView.ObiForm.Settings, PreferenceProfiles.Colors))
4600                {
4601                    strLoadedProfiles += "colors";
4602                }
4603            }
4604            if (string.IsNullOrEmpty(strLoadedProfiles))
4605            {
4606                mView.ObiForm.Settings.SettingsName = "customized";
4607            }
4608            else
4609            {
4610                if (strLoadedProfiles.EndsWith(",")) strLoadedProfiles = strLoadedProfiles.Remove(strLoadedProfiles.Length - 2);
4611            }
4612            string text = string.Format(Localizer.Message("Preferences_ProfilesStatus"), saveProfile.SettingsName, strLoadedProfiles);
4613            mView.ObiForm.Settings.SettingsNameForManipulation = saveProfile.SettingsName + "   " + Localizer.Message("Profile_Audio");
4614            mView.ObiForm.Settings.SettingsName = text;
4615            UpdateButtons();
4616            mTransportBarTooltip.SetToolTip(m_btnSwitchProfile, Localizer.Message("Transport_SwitchProfile") + "\n" + ProfileName + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ContentView_TransportBarExpandSwitchProfile.Value.ToString()) + ")");
4617            m_btnSwitchProfile.AccessibleName = Localizer.Message("Transport_SwitchProfile") + ProfileName + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ContentView_TransportBarExpandSwitchProfile.Value.ToString());
4618
4619            if (m_CurrentCheckedProfile != null)
4620            {
4621                m_CurrentCheckedProfile.Checked = false;
4622            }
4623            if (m_ListOfSwitchProfiles.ContainsKey(ProfileName))
4624            {
4625                ToolStripMenuItem ProfileSelected = m_ListOfSwitchProfiles[ProfileName];
4626                ProfileSelected.Checked = true;
4627                m_CurrentCheckedProfile = ProfileSelected;
4628            }
4629               
4630            mView.ObiForm.UpdateRecordingToolBarButtons();
4631            mView.ObiForm.UpdateTitle();
4632            mView.ObiForm.UpdateColors();
4633        }
4634
4635    // Event is subscribed to ToolStripMenu items.
4636        void SwitchProfile_Click(object sender, EventArgs e)
4637        {
4638
4639            string ProfileName =   sender.ToString();
4640           
4641            List<string> filePathsList = new List<string>();
4642            if (m_filePaths != null && m_filePaths.Length > 0)
4643            {
4644                for (int i = 0; i < m_filePaths.Length; i++)
4645                {
4646                    filePathsList.Add(System.IO.Path.GetFileNameWithoutExtension(m_filePaths[i]));
4647                }
4648            }
4649            if (filePathsList.Contains(ProfileName))
4650            {
4651                int index = filePathsList.IndexOf(ProfileName);
4652
4653                LoadProfile(m_filePaths[index],ProfileName);
4654                List<string> installedTTSVoices = Obi.Audio.AudioFormatConverter.InstalledTTSVoices;
4655                if (installedTTSVoices != null && installedTTSVoices.Count > 0)
4656                {
4657                    if (!installedTTSVoices.Contains(mView.ObiForm.Settings.Audio_TTSVoice))
4658                    {
4659                        mView.ObiForm.Settings.Audio_TTSVoice = installedTTSVoices[0];
4660                    }
4661                }
4662            }
4663        }
4664        public void InitializeTooltipsForTransportpar()
4665        {
4666            keyboardShortcuts = mView.ObiForm.KeyboardShortcuts;
4667            if (keyboardShortcuts.MenuNameDictionary.ContainsKey("mPreviousPhraseToolStripMenuItem"))
4668            {
4669                mTransportBarTooltip.SetToolTip(mPrevPhraseButton, Localizer.Message("Transport_PreviousPhrase") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mPreviousPhraseToolStripMenuItem"].Value.ToString()) + ")");
4670                mPrevPhraseButton.AccessibleName = Localizer.Message("Transport_PreviousPhraseAcc") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mPreviousPhraseToolStripMenuItem"].Value.ToString());
4671            }
4672            if (keyboardShortcuts.MenuNameDictionary.ContainsKey("mPreviousSectionToolStripMenuItem"))
4673            {
4674                mTransportBarTooltip.SetToolTip(mPrevSectionButton, Localizer.Message("Transport_PreviousSection") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mPreviousSectionToolStripMenuItem"].Value.ToString()) + ")");
4675                mPrevSectionButton.AccessibleName = Localizer.Message("Transport_PreviousSectionAcc") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mPreviousSectionToolStripMenuItem"].Value.ToString());
4676            }
4677
4678            if (keyboardShortcuts.MenuNameDictionary.ContainsKey("mPreviousPageToolStripMenuItem"))
4679            {
4680                mTransportBarTooltip.SetToolTip(mPreviousPageButton, Localizer.Message("Transport_PreviousPage") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mPreviousPageToolStripMenuItem"].Value.ToString()) + ")");
4681                mPreviousPageButton.AccessibleName = Localizer.Message("Transport_PreviousPageAcc") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mPreviousPageToolStripMenuItem"].Value.ToString());
4682            }
4683            if (keyboardShortcuts.MenuNameDictionary.ContainsKey("mRewindToolStripMenuItem"))
4684            {
4685                mTransportBarTooltip.SetToolTip(mRewindButton, Localizer.Message("Transport_FastPlayBackward") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mRewindToolStripMenuItem"].Value.ToString()) + ")");
4686                mRewindButton.AccessibleName = Localizer.Message("Transport_FastPlayBackwardAcc") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mRewindToolStripMenuItem"].Value.ToString());           
4687            }
4688
4689           
4690            mTransportBarTooltip.SetToolTip(mPlayButton, Localizer.Message("Transport_StartPlayback") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ProjectView_PlayPauseUsingAudioCursor_Default.Value.ToString()) + ")");
4691            mTransportBarTooltip.SetToolTip(mPauseButton, Localizer.Message("Transport_StartPlayback") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ProjectView_PlayPauseUsingAudioCursor_Default.Value.ToString()) + ")");
4692
4693            mPlayButton.AccessibleName = Localizer.Message("Transport_StartPlaybackAcc") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ProjectView_PlayPauseUsingAudioCursor_Default.Value.ToString());
4694            mPauseButton.AccessibleName = Localizer.Message("Transport_StartPausebackAcc") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ProjectView_PlayPauseUsingAudioCursor_Default.Value.ToString());
4695
4696            if (keyboardShortcuts.MenuNameDictionary.ContainsKey("mStopToolStripMenuItem"))
4697            {
4698                mTransportBarTooltip.SetToolTip(mStopButton, Localizer.Message("Transport_StopPlayback") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mStopToolStripMenuItem"].Value.ToString()) + ")");
4699                mStopButton.AccessibleName = Localizer.Message("Transport_StopPlaybackAcc") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mStopToolStripMenuItem"].Value.ToString());
4700            }
4701            if (keyboardShortcuts.MenuNameDictionary.ContainsKey("mStartMonitoringToolStripMenuItem"))
4702            {
4703                mTransportBarTooltip.SetToolTip(mRecordButton, Localizer.Message("Transport_StartRecording") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mStartMonitoringToolStripMenuItem"].Value.ToString()) + ")");
4704            }
4705            if (keyboardShortcuts.MenuNameDictionary.ContainsKey("mNextPhraseToolStripMenuItem"))
4706            {
4707                mTransportBarTooltip.SetToolTip(mNextPhrase, Localizer.Message("Transport_NextPhrase") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mNextPhraseToolStripMenuItem"].Value.ToString()) + ")");
4708                mNextPhrase.AccessibleName = Localizer.Message("Transport_NextPhrase") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mNextPhraseToolStripMenuItem"].Value.ToString());
4709            }
4710
4711            if (keyboardShortcuts.MenuNameDictionary.ContainsKey("mNextPageToolStripMenuItem"))
4712            {
4713                mTransportBarTooltip.SetToolTip(mNextPageButton, Localizer.Message("Transport_NextPage") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mNextPageToolStripMenuItem"].Value.ToString()) + ")");
4714                mNextPageButton.AccessibleName = Localizer.Message("Transport_NextPage") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mNextPageToolStripMenuItem"].Value.ToString());
4715            }
4716            if (keyboardShortcuts.MenuNameDictionary.ContainsKey("mNextSectionToolStripMenuItem"))
4717            {
4718                mTransportBarTooltip.SetToolTip(mNextSectionButton, Localizer.Message("Transport_NextSection") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mNextSectionToolStripMenuItem"].Value.ToString()) + ")");
4719                mNextSectionButton.AccessibleName = Localizer.Message("Transport_NextSection") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mNextSectionToolStripMenuItem"].Value.ToString());
4720            }
4721            if (keyboardShortcuts.MenuNameDictionary.ContainsKey("mPhrases_PhraseIsTODOMenuItem"))
4722            {
4723                mTransportBarTooltip.SetToolTip(mToDo_CustomClassMarkButton, Localizer.Message("Transport_AddTodo") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mPhrases_PhraseIsTODOMenuItem"].Value.ToString()) + ")");
4724                mToDo_CustomClassMarkButton.AccessibleName = Localizer.Message("Transport_AddTodoAcc") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mPhrases_PhraseIsTODOMenuItem"].Value.ToString());
4725            }
4726            if (keyboardShortcuts.MenuNameDictionary.ContainsKey("mFastForwardToolStripMenuItem"))
4727            {
4728                mTransportBarTooltip.SetToolTip(mFastForwardButton, Localizer.Message("Transport_FastPlayForward") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mFastForwardToolStripMenuItem"].Value.ToString()) + ")");
4729                mFastForwardButton.AccessibleName = Localizer.Message("Transport_FastPlayForwardAcc") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.MenuNameDictionary["mFastForwardToolStripMenuItem"].Value.ToString()); 
4730            }
4731
4732            mTransportBarTooltip.SetToolTip(m_btnPlayingOptions, Localizer.Message("Transport_PlayingOptions") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ContentView_TransportBarExpandPlayOptions.Value.ToString()) + ")");
4733            m_btnPlayingOptions.AccessibleName = Localizer.Message("Transport_PlayingOptions") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ContentView_TransportBarExpandPlayOptions.Value.ToString());
4734
4735            mTransportBarTooltip.SetToolTip(m_btnRecordingOptions, Localizer.Message("Transport_RecordingOptions") + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ContentView_TransportBarExpandRecordOptions.Value.ToString()) + ")");
4736            m_btnRecordingOptions.AccessibleName = Localizer.Message("Transport_RecordingOptions") + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ContentView_TransportBarExpandRecordOptions.Value.ToString());
4737
4738            string tempSettingsName = mView.ObiForm.Settings.SettingsNameForManipulation;
4739            string[] str = tempSettingsName.Split(new string[] { "   " }, StringSplitOptions.None);
4740            mTransportBarTooltip.SetToolTip(m_btnSwitchProfile, Localizer.Message("Transport_SwitchProfile") + "\n" + str[0] + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ContentView_TransportBarExpandSwitchProfile.Value.ToString()) + ")");
4741            m_btnSwitchProfile.AccessibleName = Localizer.Message("Transport_SwitchProfile") + str[0] + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ContentView_TransportBarExpandSwitchProfile.Value.ToString());
4742
4743            mTransportBarTooltip.SetToolTip(mDisplayBox, mDisplayBox.SelectedItem.ToString());
4744           
4745        }
4746
4747        private void m_btnPlayingOptions_Click(object sender, EventArgs e)
4748        {
4749            Button btn = (Button)sender;
4750            Point ptLowerLeft = new Point(0, btn.Height);
4751            ptLowerLeft = btn.PointToScreen(ptLowerLeft);
4752            m_PlayingOptionsContextMenuStrip.Show(ptLowerLeft); 
4753        }
4754
4755        private void m_PlaySectiontoolStripMenuItem_Click(object sender, EventArgs e)
4756        {
4757            PlaySection();           
4758           
4759        }
4760        public void PlaySection()
4761        {
4762            EmptyNode phrase = null;
4763            ObiNode nodeSelect = null;
4764            if (mView != null && mView.Selection != null)
4765            {
4766
4767
4768                if (mView.Selection.Node is EmptyNode)
4769                {
4770                    phrase = (EmptyNode)mView.Selection.Node;
4771                    nodeSelect = phrase.ParentAs<SectionNode>();
4772                }
4773                else if (mView.Selection.Node is SectionNode)
4774                {
4775                    nodeSelect = mView.Selection.Node;
4776                }
4777                if (nodeSelect != null)
4778                {
4779
4780                    m_IsPlaySectionInspiteOfPhraseSelection = true;
4781                    double time = -1;
4782                    if (IsPlayerActive)
4783                    {
4784                        if (mCurrentPlaylist.CurrentPhrase == mView.Selection.Node) time = mCurrentPlaylist.CurrentTimeInAsset;
4785                    }
4786                    else if (mView.Selection is AudioSelection && ((AudioSelection)mView.Selection).AudioRange != null)
4787                    {
4788                        AudioSelection audioSel = (AudioSelection)mView.Selection;
4789                        if (audioSel.AudioRange.HasCursor) time = audioSel.AudioRange.CursorTime;
4790                        else time = audioSel.AudioRange.SelectionBeginTime;
4791                    }
4792
4793                    if (IsPlayerActive) Stop();
4794
4795                    if (time > 0  && mView.Selection.Node is PhraseNode) 
4796                    {
4797                        bool playOnNavigateStatus = SelectionChangedPlaybackEnabled;
4798                        SelectionChangedPlaybackEnabled = false;
4799                        mView.Selection = new AudioSelection((PhraseNode) mView.Selection.Node, mView.Selection.Control, new AudioRange(time));
4800                        SelectionChangedPlaybackEnabled = playOnNavigateStatus;
4801                        }
4802
4803                    try
4804                    {
4805                        PlayOrResume(nodeSelect);
4806                    }
4807                    catch (System.Exception ex)
4808                    {
4809                        mView.WriteToLogFile(ex.ToString());
4810                        if (mCurrentPlaylist != null) mCurrentPlaylist.ForcedStopForError();
4811                        MessageBox.Show(string.Format(Localizer.Message("TransportBar_PlayerExceptionMsg"), "\n\n", ex.ToString()));
4812                    }
4813                }
4814            }
4815        }
4816
4817        private void m_PlayAlltoolStripMenuItem_Click(object sender, EventArgs e)
4818        {
4819            if (!mView.ObiForm.Settings.Audio_PlaySectionUsingPlayBtn)
4820            {
4821                PlayAllSections();
4822            }
4823            else
4824            {
4825                PlayOrResume();
4826            }
4827
4828        }
4829        public void PlayAllSections()
4830        {
4831            if (!mView.IsZoomWaveformActive)//@zoomwaveform: if zoom waveform is not active, start play all else start play selection
4832            {
4833                PlayAll();
4834            }
4835            else
4836            {
4837                PlayOrResume();
4838            }
4839        }
4840
4841        private void m_PreviewFromtoolStripMenuItem_Click(object sender, EventArgs e)
4842        {
4843            Preview(From, UseAudioCursor);
4844        }
4845
4846        private void m_PreviewUptotoolStripMenuItem_Click(object sender, EventArgs e)
4847        {
4848            Preview(Upto, UseAudioCursor);
4849        }
4850
4851        private void m_PlayingOptionsContextMenuStrip_Opening(object sender, System.ComponentModel.CancelEventArgs e)
4852        {
4853            if (!mView.ObiForm.Settings.Audio_PlaySectionUsingPlayBtn)
4854            {
4855                m_PlayAlltoolStripMenuItem.Enabled = mView.CanPlay || mView.CanResume;
4856            }
4857            else
4858            {
4859                m_PlayAlltoolStripMenuItem.Enabled = mView.CanPlaySelection || mView.CanResume;
4860            }
4861            m_PlaySectiontoolStripMenuItem.Enabled = mView.CanPlaySelection || mView.CanResume;
4862            m_playHeadingToolStripMenuItem.Enabled = mView.CanPlaySelection || mView.CanResume;
4863
4864            m_PreviewFromtoolStripMenuItem.Enabled = mView.CanPreview || mView.CanPreviewAudioSelection;
4865            m_PreviewUptotoolStripMenuItem.Enabled = mView.CanPreview || mView.CanPreviewAudioSelection;
4866           
4867        }
4868
4869        private void mPreviewBeforeRecToolStripMenuItem_Click(object sender, EventArgs e)
4870        {
4871            PreviewBeforeRecording();
4872        }
4873        public void PreviewBeforeRecording()
4874        {
4875            StartRecordingDirectly(true);
4876        }
4877
4878        public bool PreviewBeforeRecordingActive
4879        {
4880            get { return m_PreviewBeforeRecordingActive; }
4881        }
4882
4883        private void m_playHeadingToolStripMenuItem_Click(object sender, EventArgs e)
4884        {
4885            PlayHeading();       
4886           
4887        }
4888        public void PlayHeading()
4889        {
4890            PhraseNode pharse = null;
4891            SectionNode nodeSelect = null;
4892            EmptyNode emptyNode = null;
4893            if (mView != null )
4894            {
4895                if (mView.Selection == null)
4896                {
4897                    nodeSelect = mView.Presentation.FirstSection;
4898                }
4899                if (mView.Selection.Node is EmptyNode)
4900                {
4901                    nodeSelect = mView.Selection.Node.ParentAs<SectionNode>();
4902                }
4903                else if (mView.Selection.Node is SectionNode)
4904                {
4905                    nodeSelect = (SectionNode)mView.Selection.Node;
4906                }
4907               
4908                if (nodeSelect != null)
4909                {
4910                    if (IsPlayerActive) Stop();
4911                    PlayHeadingPhrase(nodeSelect);
4912                }
4913            }
4914        }
4915        public bool ExpandPlayOptions()
4916        {
4917            if (m_btnPlayingOptions.Enabled)
4918            {
4919                Point pt = new Point(0, m_btnPlayingOptions.Height);
4920                pt = m_btnPlayingOptions.PointToScreen(pt);
4921                m_PlayingOptionsContextMenuStrip.Show(pt);
4922                return true;
4923            }
4924            else
4925            {
4926                return false;
4927            }
4928           
4929        }
4930        public bool ExpandRecordOptions()
4931        {
4932            if (m_btnRecordingOptions.Enabled)
4933            {
4934                Point pt = new Point(0, m_btnRecordingOptions.Height);
4935                pt = m_btnRecordingOptions.PointToScreen(pt);
4936                m_RecordingOptionsContextMenuStrip.Show(pt);
4937                return true;
4938            }
4939            else
4940            {
4941                return false;
4942            }
4943
4944        }
4945        public bool ExpandSwitchProfile()
4946        {
4947            if (m_btnSwitchProfile.Enabled)
4948            {
4949                Point pt = new Point(0, m_btnSwitchProfile.Height);
4950                pt = m_btnSwitchProfile.PointToScreen(pt);
4951                m_SwitchProfileContextMenuStrip.Show(pt);
4952                ShowSwitchProfileContextMenu();
4953                return true;
4954            }
4955            else
4956            {
4957                return false;
4958            }
4959
4960        }
4961
4962        public bool IsPreviewBeforeRecordingEnabled
4963        {
4964            get
4965            {
4966                if (mView != null && mView.ObiForm != null && mView.ObiForm.Settings != null && mView.Selection != null && CurrentState != State.Monitoring
4967&& 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)))
4968                {
4969                    return true;
4970                }
4971                else
4972                {
4973                    return false;
4974                }
4975
4976            }
4977        }
4978
4979        //@MonitorContinuously
4980        public bool MonitorContinuously
4981        {
4982            get { return m_MonitorContinuously; }
4983            set
4984            {
4985                Console.WriteLine("value of monitor continuously" + value);
4986                if (value && mView.ObiForm != null )
4987                {
4988                   
4989                    m_MonitorContinuously = value;
4990                    StartMonitorContinuously();
4991                }
4992                else
4993                {
4994                    StopMonitorContinuously();
4995                    m_MonitorContinuously = value;
4996                    // trigger state changed event again because the MonitorContinuesly goes false after the state changed event
4997                    if (StateChanged != null) StateChanged(this, new AudioLib.AudioPlayer.StateChangedEventArgs(mPlayer.CurrentState));
4998                }
4999               
5000            }
5001        }
5002
5003        //@MonitorContinuously
5004        private void StartMonitorContinuously()
5005        {
5006            if (m_MonitorContinuously && mPlayer.CurrentState == AudioLib.AudioPlayer.State.Stopped && mRecorder.CurrentState == AudioLib.AudioRecorder.State.Stopped)
5007            {
5008                mRecordingSession = new RecordingSession(mView.Presentation, mRecorder, mView.ObiForm.Settings);
5009                mRecordingSession.StartMonitoring();
5010                mVUMeterPanel.BeepEnable = true;
5011            }
5012        }
5013
5014        //@MonitorContinuously
5015        private void StopMonitorContinuously()
5016        {
5017            if (m_MonitorContinuously && mRecordingSession != null && mRecorder.CurrentState == AudioLib.AudioRecorder.State.Monitoring)
5018            {
5019                mRecordingSession.Stop();
5020                mRecordingSession = null;
5021                mVUMeterPanel.BeepEnable = false;                 
5022            }
5023        }
5024
5025        //@MonitorContinuously
5026        System.ComponentModel.BackgroundWorker m_MonitorContinuouslyWorker= null;
5027        private void StartMonitorContinuouslyWithDelay()
5028        {
5029            m_MonitorContinuouslyWorker = new System.ComponentModel.BackgroundWorker();
5030                m_MonitorContinuouslyWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(delegate(object sender, System.ComponentModel.DoWorkEventArgs e)
5031                {
5032                    Thread.Sleep(1500);
5033                 });
5034
5035m_MonitorContinuouslyWorker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(delegate(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
5036                {
5037                    if (m_MonitorContinuously && CurrentState == State.Stopped)
5038                    {
5039                        StartMonitorContinuously();
5040                    }
5041                });
5042m_MonitorContinuouslyWorker.RunWorkerAsync();
5043               
5044        }
5045
5046        private void mMonitorContinuouslyToolStripMenuItem_Click(object sender, EventArgs e)
5047        {
5048            if (mMonitorContinuouslyToolStripMenuItem.Checked)
5049            {
5050                MonitorContinuously = true;
5051            }
5052            else
5053            {
5054                MonitorContinuously = false;
5055            }
5056        }
5057
5058        private void m_SwitchProfile_Click(object sender, EventArgs e)
5059        {
5060            Point pt = new Point(0, m_btnSwitchProfile.Height);
5061            pt = m_btnSwitchProfile.PointToScreen(pt);
5062            m_SwitchProfileContextMenuStrip.Show(pt);
5063            ShowSwitchProfileContextMenu();
5064        }
5065        public void ShowSwitchProfileContextMenu()
5066        {
5067
5068            string[] str = mView.ObiForm.Settings.SettingsNameForManipulation.Split(new string[] { "   " }, StringSplitOptions.None);
5069            //     if (m_CurrentCheckedProfile == null || m_CurrentCheckedProfile.ToString() != str[0])
5070
5071            if (m_ListOfSwitchProfiles.ContainsKey(str[0]))
5072            {
5073                if (m_CurrentCheckedProfile != null)
5074                {
5075                    m_CurrentCheckedProfile.Checked = false;
5076                }
5077                ToolStripMenuItem ProfileSelected = m_ListOfSwitchProfiles[str[0]];
5078                ProfileSelected.Checked = true;
5079                m_CurrentCheckedProfile = ProfileSelected;
5080                mTransportBarTooltip.SetToolTip(m_btnSwitchProfile, Localizer.Message("Transport_SwitchProfile") + "\n" + str[0] + "(" + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ContentView_TransportBarExpandSwitchProfile.Value.ToString()) + ")");
5081                m_btnSwitchProfile.AccessibleName = Localizer.Message("Transport_SwitchProfile") + str[0] + keyboardShortcuts.FormatKeyboardShorcut(keyboardShortcuts.ContentView_TransportBarExpandSwitchProfile.Value.ToString());
5082                mView.ObiForm.UpdateTitle();
5083
5084            }
5085
5086        }
5087
5088        public void SetFont()//@fontconfig
5089        {
5090            mTransportBarTooltip.OwnerDraw = true;
5091            mTransportBarTooltip.IsBalloon = false;
5092            this.Font = new Font(mView.ObiForm.Settings.ObiFont, this.Font.Size, FontStyle.Regular);
5093            m_PlayingOptionsContextMenuStrip.Font = m_RecordingOptionsContextMenuStrip.Font = new Font(mView.ObiForm.Settings.ObiFont, this.Font.Size, FontStyle.Regular);
5094        }
5095        private void mTransportBarTooltip_Draw(object sender, DrawToolTipEventArgs e)//@fontconfig
5096        {
5097            Font tooltipFont = new Font(mView.ObiForm.Settings.ObiFont, this.Font.Size);
5098            Font tooltipTitleFont = new Font(mView.ObiForm.Settings.ObiFont, this.Font.Size, FontStyle.Bold);
5099            e.Graphics.Clear(Color.White);
5100
5101            e.Graphics.DrawString(mTransportBarTooltip.ToolTipTitle, tooltipTitleFont, Brushes.Blue, new PointF(0, 0));
5102            e.Graphics.DrawString(" \n" + e.ToolTipText, tooltipFont, Brushes.Black, new PointF(0, 0));
5103
5104        }
5105
5106        private void mTransportBarTooltip_Popup(object sender, PopupEventArgs e)//@fontconfig
5107        {
5108            e.ToolTipSize = TextRenderer.MeasureText(mTransportBarTooltip.ToolTipTitle + "\n" + mTransportBarTooltip.GetToolTip(e.AssociatedControl), new Font(mView.ObiForm.Settings.ObiFont, this.Font.Size));
5109        }
5110
5111        private System.Text.StringBuilder m_MissedNotificationMessages = new System.Text.StringBuilder();
5112        private void LogRecorderMissedNotificationMsg(object sender, AudioLib.AudioRecorder.CircularBufferNotificationTimerMessageEventArgs e)
5113        {
5114            if (e != null && !string.IsNullOrEmpty(e.Msg))
5115            {
5116                m_MissedNotificationMessages.AppendLine(e.Msg);
5117                if (m_MissedNotificationMessages != null &&  m_MissedNotificationMessages.Length > 4000)
5118                {
5119                    WriteLogMsgForRecorderMissedNotification();
5120                }
5121            }
5122        }
5123
5124        private void WriteLogMsgForRecorderMissedNotification ()
5125        {
5126            if (m_MissedNotificationMessages != null &&  m_MissedNotificationMessages.Length > 0)
5127            {
5128                m_MissedNotificationMessages.AppendLine("adding next set of missed notification messages");
5129                mView.WriteToLogFile(m_MissedNotificationMessages.ToString());
5130                m_MissedNotificationMessages = null;
5131                m_MissedNotificationMessages = new System.Text.StringBuilder();
5132            }
5133        }
5134
5135
5136    }
5137}
Note: See TracBrowser for help on using the repository browser.