javauis/mmapi_qt/baseline/src/cmmamidiplayer.cpp
changeset 23 98ccebc37403
child 26 dc7c549001d5
equal deleted inserted replaced
21:2a9601315dfc 23:98ccebc37403
       
     1 /*
       
     2 * Copyright (c) 2002-2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  This class is used for MIDI.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 //  INCLUDE FILES
       
    20 #include <mmf/server/mmffile.h>
       
    21 #include <logger.h>
       
    22 #include <e32base.h>
       
    23 #include <AudioPreference.h>
       
    24 
       
    25 #include "cmmamidiplayer.h"
       
    26 #include "mmmadisplay.h"
       
    27 
       
    28 const TInt KErrorMessageSize = 32;
       
    29 _LIT(KErrDefaultError, "Symbian OS Error: %d");
       
    30 const TInt KMidiDefaultBank = 0x3c80;
       
    31 const TInt KMidiDrumBank = 0x3c7c;
       
    32 const TInt KMidiDrumChannel = 9;
       
    33 const TInt KMidiChannels = 16;
       
    34 const TInt KMidiDefaultInstrument = 1;
       
    35 
       
    36 CMMAMIDIPlayer* CMMAMIDIPlayer::NewLC(const TDesC& aContentType,
       
    37                                       TFileName aFileName)
       
    38 {
       
    39     CMMAMIDIPlayer* self = new(ELeave) CMMAMIDIPlayer(aFileName);
       
    40     CleanupStack::PushL(self);
       
    41     self->ConstructL(aContentType);
       
    42     return self;
       
    43 }
       
    44 
       
    45 CMMAMIDIPlayer::~CMMAMIDIPlayer()
       
    46 {
       
    47     CloseClientUtility();
       
    48     // new function added to CMMAPlayer delete the controls before the destruction of iMidi.
       
    49     DeleteControls();
       
    50     delete iMidi;
       
    51     delete iActiveSchedulerWait;
       
    52     iObservers.Close();
       
    53 
       
    54     LOG( EJavaMMAPI, EInfo, "MMA::CMMAMIDIPlayer::~CMMAMIDIPlayer");
       
    55 }
       
    56 
       
    57 void CMMAMIDIPlayer::ConstructL(const TDesC& aContentType)
       
    58 {
       
    59     LOG( EJavaMMAPI, EInfo, "CMMAMIDIPlayer::ConstructL");
       
    60     iContentType = aContentType.AllocL();
       
    61     iActiveSchedulerWait = new(ELeave)CActiveSchedulerWait;
       
    62     iMidi = CMidiClientUtility::NewL(*this, KAudioPriorityRecording,
       
    63                                      KMMAMIDIPriorityPreference, ETrue);
       
    64 
       
    65     CMMAPlayer::ConstructL();
       
    66 }
       
    67 
       
    68 CMMAMIDIPlayer::CMMAMIDIPlayer(TFileName aFileName):
       
    69         iFileName(aFileName),
       
    70         iMediaTime(KTimeUnknown), iStartedEventTime(0)
       
    71 {
       
    72 }
       
    73 
       
    74 EXPORT_C CMidiClientUtility* CMMAMIDIPlayer::MidiClient() const
       
    75 {
       
    76     return iMidi;
       
    77 }
       
    78 
       
    79 
       
    80 void CMMAMIDIPlayer::RealizeL()
       
    81 {
       
    82     LOG( EJavaMMAPI, EInfo, "CMMAMIDIPlayer::RealizeL");
       
    83     CMMAPlayer::RealizeL();
       
    84 }
       
    85 
       
    86 void CMMAMIDIPlayer::PrefetchL()
       
    87 {
       
    88     LOG1( EJavaMMAPI, EInfo, "CMMAMIDIPlayer::PrefetchL stream count %d", iSourceStreams.Count());
       
    89     if (iFileName != KNullDesC)
       
    90     {
       
    91         iMidi->OpenFile(iFileName);
       
    92     }
       
    93     else if (iSourceStreams.Count() == 0)
       
    94     {
       
    95         // We have no data, but need to initialize the player
       
    96         // Preparing all channels
       
    97         for (TInt i = 0; i < KMidiChannels; i++)
       
    98         {
       
    99             iMidi->SetInstrumentL(i, KMidiDefaultBank,
       
   100                                   KMidiDefaultInstrument);
       
   101         }
       
   102 
       
   103         // Setting drums to channel 10
       
   104         iMidi->SetInstrumentL(KMidiDrumChannel, KMidiDrumBank,
       
   105                               KMidiDefaultInstrument);
       
   106 
       
   107         // Start it immediately in order to get MIDIControl work without
       
   108         // calling the start. This is how reference implementation works.
       
   109         iMidi->Play();
       
   110     }
       
   111     else
       
   112     {
       
   113         // Created with content, audio player will initialize controller
       
   114         // and data source.
       
   115         iSourceStreams[ 0 ]->ReadAllL();
       
   116     }
       
   117 }
       
   118 
       
   119 //
       
   120 // This method is called when CMMASourceStreamReader finished reading
       
   121 // initiated in PrefetchL
       
   122 //
       
   123 void CMMAMIDIPlayer::ReadCompletedL(TInt aStatus, const TDesC8& aData)
       
   124 {
       
   125     if (aStatus < KErrNone)
       
   126     {
       
   127         PostActionCompleted(aStatus);
       
   128     }
       
   129     else
       
   130     {
       
   131         // we're not finished yet
       
   132         iMidi->OpenDes(aData);      //wait for MMidiClientUtilityObserver::MmcuoStateChanged
       
   133     }
       
   134 }
       
   135 
       
   136 void CMMAMIDIPlayer::DeallocateL()
       
   137 {
       
   138     LOG( EJavaMMAPI, EInfo, "MMA: CMMAMidiPlayer: DeallocateL +");
       
   139     if (iState == EPrefetched)
       
   140     {
       
   141         CloseClientUtility();
       
   142         ResetSourceStreams();
       
   143         ChangeState(ERealized);
       
   144     }
       
   145     LOG( EJavaMMAPI, EInfo, "MMA: CMMAMidiPlayer: DeallocateL -");
       
   146 }
       
   147 
       
   148 void CMMAMIDIPlayer::StartL()
       
   149 {
       
   150     iMediaTime = KTimeUnknown;
       
   151 
       
   152     // Player is already started if this player is constructed with
       
   153     // device://midi locator.
       
   154     TBool isDeviceMidi = (iSourceStreams.Count() == 0 &&
       
   155                           iFileName == KNullDesC);
       
   156     if (!isDeviceMidi)
       
   157     {
       
   158         iMidi->Play();
       
   159     }
       
   160 
       
   161     // inform java side
       
   162     PostLongEvent(CMMAPlayerEvent::EStarted, iStartedEventTime);
       
   163     ChangeState(EStarted);
       
   164 
       
   165     // To achieve similar functionality as reference implementation,
       
   166     // END_OF_MEDIA must be sent right after Start on device://midi.
       
   167     if (isDeviceMidi)
       
   168     {
       
   169         PostLongEvent(CMMAPlayerEvent::EEndOfMedia, iStartedEventTime);
       
   170         ChangeState(EPrefetched);
       
   171     }
       
   172     PostActionCompletedStart();
       
   173     //PostActionCompleted(KErrNone);   // java start return
       
   174 }
       
   175 
       
   176 void CMMAMIDIPlayer::StopL(TBool aPostEvent)
       
   177 {
       
   178     LOG( EJavaMMAPI, EInfo, "MMA: CMMAMidiPlayer::StopL");
       
   179     if (iState == EStarted)
       
   180     {
       
   181         TInt64 time;
       
   182         GetMediaTime(&time);
       
   183         iStartedEventTime = time;
       
   184 
       
   185         // do the stop only if we are playing some content
       
   186         if ((iSourceStreams.Count() > 0) ||
       
   187                 (iFileName != KNullDesC))
       
   188         {
       
   189             // should actually pause!!!
       
   190             iMidi->Stop(TTimeIntervalMicroSeconds(0));
       
   191         }
       
   192 
       
   193         if (aPostEvent)
       
   194         {
       
   195             PostLongEvent(CMMAPlayerEvent::EStopped, time);
       
   196         }
       
   197         // go back to prefetched state
       
   198         ChangeState(EPrefetched);
       
   199     }
       
   200 }
       
   201 
       
   202 void CMMAMIDIPlayer::GetDuration(TInt64* aDuration)
       
   203 {
       
   204     // Special case for device://midi
       
   205     if ((iSourceStreams.Count() == 0) &&
       
   206             (iFileName == KNullDesC))
       
   207     {
       
   208         iDuration = KErrNone;
       
   209     }
       
   210     else if (iDuration == KTimeUnknown)
       
   211     {
       
   212         TRAPD(err, iDuration = iMidi->DurationMicroSecondsL().Int64());
       
   213         if (err != KErrNone)
       
   214         {
       
   215             // Duration was not available.
       
   216             iDuration = KTimeUnknown;
       
   217         }
       
   218     }
       
   219 
       
   220     *aDuration = iDuration;
       
   221 }
       
   222 
       
   223 void CMMAMIDIPlayer::SetMediaTimeL(TInt64* aTime)
       
   224 {
       
   225     TTimeIntervalMicroSeconds position(*aTime);
       
   226     iMidi->SetPositionMicroSecondsL(position);
       
   227 
       
   228     // Reset cached media time, because actual set position may be
       
   229     // something else than aTime.
       
   230     iMediaTime = KTimeUnknown;
       
   231 
       
   232     // Inform about the position change to the StateListeners
       
   233     ChangeState(iState);
       
   234 
       
   235     // Get the actual media time
       
   236     GetMediaTime(aTime);
       
   237 
       
   238     iStartedEventTime = iMediaTime;
       
   239 }
       
   240 
       
   241 void CMMAMIDIPlayer::GetMediaTime(TInt64* aMediaTime)
       
   242 {
       
   243     // Special case for device://midi
       
   244     if ((iSourceStreams.Count() == 0) &&
       
   245             (iFileName == KNullDesC))
       
   246     {
       
   247         iMediaTime = KErrNone;
       
   248     }
       
   249     else if (iMediaTime == KTimeUnknown || iState == EStarted)
       
   250     {
       
   251         TTimeIntervalMicroSeconds position(0);
       
   252         TRAPD(error, position = iMidi->PositionMicroSecondsL());
       
   253 
       
   254         if (error == KErrNone)
       
   255         {
       
   256             TInt64 newTime = position.Int64();
       
   257 
       
   258             // Sanity check for media time going backwards or beyond the
       
   259             // duration.
       
   260             // Some native controls may return zero media time for
       
   261             // a few moments just before playback will complete.
       
   262             if (newTime < iMediaTime ||
       
   263                     (iDuration > 0 && newTime > iDuration))
       
   264             {
       
   265                 GetDuration(&iMediaTime);
       
   266             }
       
   267             else
       
   268             {
       
   269                 // set return value
       
   270                 iMediaTime = newTime;
       
   271             }
       
   272         }
       
   273         else
       
   274         {
       
   275             // media time cannot be get
       
   276             iMediaTime = KTimeUnknown;
       
   277         }
       
   278     }
       
   279     *aMediaTime = iMediaTime;
       
   280 }
       
   281 
       
   282 void CMMAMIDIPlayer::ReInitializeMidiEngineL(const TDesC8* aMidiSequence)
       
   283 {
       
   284     LOG( EJavaMMAPI, EInfo, "MMA: CMMAMIDIPlayer: ReInitializeMidiEngineL: + ");
       
   285 
       
   286     CloseClientUtility();
       
   287 
       
   288     LOG( EJavaMMAPI, EInfo, "MMA: CMMAMidiPlayer: ReInitializeMidiEngineL: Opening descriptor");
       
   289 
       
   290     iMidi->OpenDes(*aMidiSequence);
       
   291     // Wait until asynchronous OpenDes call has completed
       
   292     if (!iActiveSchedulerWait->IsStarted())
       
   293     {
       
   294         iActiveSchedulerWait->Start();
       
   295     }
       
   296     ChangeState(EPrefetched);
       
   297     LOG( EJavaMMAPI, EInfo, "MMA: CMMAMIDIPlayer: ReInitializeMidiEngineL: - ");
       
   298 }
       
   299 
       
   300 void CMMAMIDIPlayer::addObserverL(MMidiClientUtilityObserver* aObserver)
       
   301 {
       
   302     iObservers.AppendL(aObserver);
       
   303 }
       
   304 
       
   305 void CMMAMIDIPlayer::CloseL()
       
   306 {
       
   307     CMMAPlayer::CloseL();
       
   308     CloseClientUtility();
       
   309 }
       
   310 
       
   311 const TDesC& CMMAMIDIPlayer::Type()
       
   312 {
       
   313     return KMMAMIDIPlayer;
       
   314 }
       
   315 
       
   316 void CMMAMIDIPlayer::PlayCompleteL(TInt aError)
       
   317 {
       
   318     LOG( EJavaMMAPI, EInfo, "MMA: CMMAMidiPlayer: PlayCompleteL +");
       
   319     ELOG1( EJavaMMAPI, "MMA: CMMAMidiPlayer: PlayCompleteL: Error=%d", aError);
       
   320     TInt64 duration;
       
   321     GetDuration(&duration);
       
   322     iMediaTime = duration;
       
   323     iStartedEventTime = 0;
       
   324 
       
   325     iMidi->Stop(TTimeIntervalMicroSeconds(0));
       
   326 
       
   327     // go back to prefetched state
       
   328     ChangeState(EPrefetched);   // ready to play again
       
   329 
       
   330     // Send 'Stopped' only when stop() is called.
       
   331     PostLongEvent(CMMAPlayerEvent::EEndOfMedia, duration);
       
   332 
       
   333     if (aError == KErrNone)
       
   334     {
       
   335         iRepeatCount++;
       
   336 
       
   337         if (iRepeatForever || iRepeatCount < iRepeatNumberOfTimes)
       
   338         {
       
   339             StartL();
       
   340         }
       
   341         else
       
   342         {
       
   343             iRepeatCount = 0;
       
   344         }
       
   345     }
       
   346     else
       
   347     {
       
   348         // error has occured, setting correct number of
       
   349         // repeats for next start
       
   350         SetLoopCount(iRepeatNumberOfTimes);
       
   351     }
       
   352     LOG( EJavaMMAPI, EInfo, "MMA: CMMAMidiPlayer: PlayCompleteL -");
       
   353 }
       
   354 
       
   355 void CMMAMIDIPlayer::MmcuoStateChanged(TMidiState aOldState,
       
   356                                        TMidiState aNewState,
       
   357                                        const TTimeIntervalMicroSeconds& aTime,
       
   358                                        TInt aError)
       
   359 {
       
   360     TInt err = aError;
       
   361 
       
   362     ELOG3( EJavaMMAPI, "MMA: CMMAMIDIPlayer: MmcuoStateChanged: Old=%d, New=%d, Error=%d",
       
   363                aOldState,
       
   364                aNewState,
       
   365                err);
       
   366     // Closing the utility or reinitialising
       
   367 #ifdef RD_JAVA_TMIDISTATECHANGE
       
   368     if (iActiveSchedulerWait->IsStarted() &&
       
   369             ((aNewState == EMidiStateClosedDisengaged) ||
       
   370              (aNewState == EMidiStateOpenDisengaged) ||
       
   371              (aNewState == EMidiStateClosedEngaged)))
       
   372 #else
       
   373     if (iActiveSchedulerWait->IsStarted() &&
       
   374             ((aNewState == EClosedDisengaged) ||
       
   375              (aNewState == EOpenDisengaged) ||
       
   376              (aNewState == EClosedEngaged)))
       
   377 #endif
       
   378     {
       
   379         iActiveSchedulerWait->AsyncStop();
       
   380     }
       
   381     // changing from realized to prefetched state
       
   382 #ifdef RD_JAVA_TMIDISTATECHANGE
       
   383     else if ((iState == ERealized) &&
       
   384              (aOldState == EMidiStateClosedDisengaged) &&
       
   385              ((aNewState == EMidiStateOpenDisengaged) ||
       
   386               (aNewState == EMidiStateClosedEngaged) ||
       
   387               (aNewState == EMidiStateClosedDisengaged)))
       
   388 #else
       
   389     else if ((iState == ERealized) &&
       
   390              (aOldState == EClosed) &&
       
   391              ((aNewState == EOpen) || (aNewState == EClosedEngaged) ||
       
   392               (aNewState == EClosed)))     // EClosed is EClosedDisengaged
       
   393 #endif
       
   394     {
       
   395         if (aError == KErrNone)
       
   396         {
       
   397             // prefetch succeed
       
   398             ChangeState(EPrefetched);
       
   399         }
       
   400         // else state remains realized
       
   401 
       
   402         // inform java
       
   403         PostActionCompleted(aError);
       
   404         err = KErrNone; // don't report the error again
       
   405     }
       
   406 #ifdef RD_JAVA_TMIDISTATECHANGE
       
   407     else if ((aOldState == EMidiStateOpenPlaying) &&
       
   408              (aNewState == EMidiStateOpenEngaged) &&
       
   409              (iState == EStarted))
       
   410 #else
       
   411     else if ((aOldState == EPlaying) &&
       
   412              (aNewState == EOpenEngaged) &&
       
   413              (iState == EStarted))
       
   414 #endif
       
   415     {
       
   416         // If iState is not EStarted PlayCompleteL may not be called because
       
   417         // player may be already stopped.
       
   418 
       
   419         // playing completed
       
   420         TRAPD(playErr, PlayCompleteL(aError));
       
   421         if (playErr != KErrNone)
       
   422         {
       
   423             err = playErr;
       
   424         }
       
   425     }
       
   426 
       
   427     if (err != KErrNone)
       
   428     {
       
   429         TBuf<KErrorMessageSize> errorMessage;
       
   430         errorMessage.Format(KErrDefaultError, err);
       
   431         PostStringEvent(CMMAPlayerEvent::EError, errorMessage);
       
   432         if (iActiveSchedulerWait->IsStarted())
       
   433         {
       
   434             iActiveSchedulerWait->AsyncStop();
       
   435         }
       
   436     }
       
   437 
       
   438     // notify observers
       
   439     TInt count = iObservers.Count();
       
   440     for (TInt i = 0; i < count; i++)
       
   441     {
       
   442         iObservers[ i ]->MmcuoStateChanged(aOldState, aNewState, aTime, aError);
       
   443     }
       
   444 
       
   445     LOG1( EJavaMMAPI, EInfo, "MMA: CMMAMIDIPlayer: MmcuoStateChanged: midi state %d",
       
   446               iMidi->State());
       
   447 }
       
   448 
       
   449 void CMMAMIDIPlayer::MmcuoTempoChanged(TInt aMicroBeatsPerMinute)
       
   450 {
       
   451     // notify observers
       
   452     TInt count = iObservers.Count();
       
   453     for (TInt i = 0; i < count; i++)
       
   454     {
       
   455         iObservers[ i ]->MmcuoTempoChanged(aMicroBeatsPerMinute);
       
   456     }
       
   457 }
       
   458 
       
   459 void CMMAMIDIPlayer::MmcuoVolumeChanged(TInt aChannel,TReal32 aVolumeInDecibels)
       
   460 {
       
   461     // notify observers
       
   462     TInt count = iObservers.Count();
       
   463     for (TInt i = 0; i < count; i++)
       
   464     {
       
   465         iObservers[ i ]->MmcuoVolumeChanged(aChannel, aVolumeInDecibels);
       
   466     }
       
   467 }
       
   468 
       
   469 void CMMAMIDIPlayer::MmcuoMuteChanged(TInt aChannel,TBool aMuted)
       
   470 {
       
   471     // notify observers
       
   472     TInt count = iObservers.Count();
       
   473     for (TInt i = 0; i < count; i++)
       
   474     {
       
   475         iObservers[ i ]->MmcuoMuteChanged(aChannel, aMuted);
       
   476     }
       
   477 }
       
   478 
       
   479 void CMMAMIDIPlayer::MmcuoSyncUpdate(const TTimeIntervalMicroSeconds& aMicroSeconds,TInt64 aMicroBeats)
       
   480 {
       
   481     // notify observers
       
   482     TInt count = iObservers.Count();
       
   483     for (TInt i = 0; i < count; i++)
       
   484     {
       
   485         iObservers[ i ]->MmcuoSyncUpdate(aMicroSeconds, aMicroBeats);
       
   486     }
       
   487 }
       
   488 
       
   489 void CMMAMIDIPlayer::MmcuoMetaDataEntryFound(const TInt aMetaDataEntryId,const TTimeIntervalMicroSeconds& aPosition)
       
   490 {
       
   491     // notify observers
       
   492     TInt count = iObservers.Count();
       
   493     for (TInt i = 0; i < count; i++)
       
   494     {
       
   495         iObservers[ i ]->MmcuoMetaDataEntryFound(aMetaDataEntryId, aPosition);
       
   496     }
       
   497 }
       
   498 
       
   499 void CMMAMIDIPlayer::MmcuoMipMessageReceived(const RArray<TMipMessageEntry>& aMessage)
       
   500 {
       
   501     // notify observers
       
   502     TInt count = iObservers.Count();
       
   503     for (TInt i = 0; i < count; i++)
       
   504     {
       
   505         iObservers[ i ]->MmcuoMipMessageReceived(aMessage);
       
   506     }
       
   507 }
       
   508 
       
   509 void CMMAMIDIPlayer::MmcuoPolyphonyChanged(TInt aNewPolyphony)
       
   510 {
       
   511     // notify observers
       
   512     TInt count = iObservers.Count();
       
   513     for (TInt i = 0; i < count; i++)
       
   514     {
       
   515         iObservers[ i ]->MmcuoPolyphonyChanged(aNewPolyphony);
       
   516     }
       
   517 }
       
   518 
       
   519 void CMMAMIDIPlayer::MmcuoInstrumentChanged(TInt aChannel,TInt aBankId,TInt aInstrumentId)
       
   520 {
       
   521     // notify observers
       
   522     TInt count = iObservers.Count();
       
   523     for (TInt i = 0; i < count; i++)
       
   524     {
       
   525         iObservers[ i ]->MmcuoInstrumentChanged(aChannel, aBankId, aInstrumentId);
       
   526     }
       
   527 }
       
   528 
       
   529 void CMMAMIDIPlayer::CloseClientUtility()
       
   530 {
       
   531     LOG( EJavaMMAPI, EInfo, "MMA: CMMAMidiPlayer: CloseClientUtility +");
       
   532     if (iMidi &&
       
   533             iActiveSchedulerWait &&
       
   534 #ifdef RD_JAVA_TMIDISTATECHANGE
       
   535             (iMidi->State() != EMidiStateClosedDisengaged))
       
   536 #else
       
   537             (iMidi->State() != EClosed))
       
   538 #endif
       
   539     {
       
   540         // Have to stop midi before closing,
       
   541         // this case is for device://midi
       
   542 #ifdef RD_JAVA_TMIDISTATECHANGE
       
   543         if (iMidi->State() == EMidiStateClosedEngaged)
       
   544 #else
       
   545         if (iMidi->State() == EClosedEngaged)
       
   546 #endif
       
   547         {
       
   548             iMidi->Stop(TTimeIntervalMicroSeconds(0));
       
   549             if (!iActiveSchedulerWait->IsStarted())
       
   550             {
       
   551                 iActiveSchedulerWait->Start();
       
   552             }
       
   553         }
       
   554         else
       
   555         {
       
   556             // Calling Close and Stop or Stop and Close should
       
   557             // always lead to EClosed state.
       
   558 
       
   559             // From EOpenEngaged or EOpenPlaying to EClosedEngaged
       
   560             // or from EOpenDisengaged to EClosedDisengaged
       
   561             iMidi->Close();
       
   562             if (!iActiveSchedulerWait->IsStarted())
       
   563             {
       
   564                 iActiveSchedulerWait->Start();
       
   565             }
       
   566 
       
   567             LOG1( EJavaMMAPI, EInfo, "State after Close: %d", iMidi->State());
       
   568 
       
   569             // If not in EClosedDisengaged yet
       
   570 #ifdef RD_JAVA_TMIDISTATECHANGE
       
   571             if (iMidi->State() != EMidiStateClosedDisengaged)
       
   572 #else
       
   573             if (iMidi->State() != EClosed)
       
   574 #endif
       
   575             {
       
   576                 // From EClosedEngaged to EClosedDisengaged
       
   577                 iMidi->Stop(TTimeIntervalMicroSeconds(0));
       
   578                 if (!iActiveSchedulerWait->IsStarted())
       
   579                 {
       
   580                     iActiveSchedulerWait->Start();
       
   581                 }
       
   582                 LOG1( EJavaMMAPI, EInfo, "State after Stop: %d", iMidi->State());
       
   583             }
       
   584         }
       
   585         LOG1( EJavaMMAPI, EInfo, "MMA: CMMAMidiPlayer: CloseClientUtility: State after close: %d", iMidi->State());
       
   586     }
       
   587     LOG( EJavaMMAPI, EInfo, "MMA: CMMAMidiPlayer: CloseClientUtility -");
       
   588 }
       
   589 
       
   590 //  END OF FILE