jdkmidi class library documentation

Copyright © 2004 J.D. Koftinoff Software, Ltd.

Released under the GNU General Public License (GPL)




Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

src/jdkmidi_manager.cpp

Go to the documentation of this file.
00001 /*
00002  *  libjdkmidi-2004 C++ Class Library for MIDI
00003  *
00004  *  Copyright (C) 2004  J.D. Koftinoff Software, Ltd.
00005  *  www.jdkoftinoff.com
00006  *  jeffk@jdkoftinoff.com
00007  *
00008  *  *** RELEASED UNDER THE GNU GENERAL PUBLIC LICENSE (GPL) April 27, 2004 ***
00009  *
00010  *  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU General Public License for more details.
00019  *
00020  *  You should have received a copy of the GNU General Public License
00021  *  along with this program; if not, write to the Free Software
00022  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023 */
00024 #include "jdkmidi/world.h"
00025 #include "jdkmidi/manager.h"
00026 
00027 namespace jdkmidi
00028 {
00029   
00030   
00031   MIDIManager::MIDIManager(
00032     MIDIDriver *drv,
00033     MIDISequencerGUIEventNotifier *n,
00034     MIDISequencer *seq_
00035     ) 
00036     :
00037     driver(drv),
00038     sequencer(seq_),
00039     sys_time_offset(0),
00040     seq_time_offset(0),
00041     play_mode(false),
00042     stop_mode(true),
00043     notifier( n ),
00044     repeat_play_mode(false),
00045     repeat_start_measure(0),
00046     repeat_end_measure(0)
00047   {
00048     driver->SetTickProc( this );
00049   } 
00050   
00051   MIDIManager::~MIDIManager() 
00052   {
00053   } 
00054   
00055   
00056   void MIDIManager::Reset() 
00057   {
00058     SeqStop();
00059     sys_time_offset = 0;
00060     seq_time_offset = 0;
00061     play_mode = false;
00062     stop_mode = true;
00063     
00064     if( notifier )
00065     {
00066       notifier->Notify( sequencer, MIDISequencerGUIEvent( MIDISequencerGUIEvent::GROUP_ALL ) );
00067     }
00068   } 
00069   
00070   
00071 // to set and get the current sequencer
00072   void MIDIManager::SetSeq( MIDISequencer *seq ) 
00073   {
00074     if( notifier )
00075     {
00076       notifier->Notify( sequencer, MIDISequencerGUIEvent( MIDISequencerGUIEvent::GROUP_ALL ) );
00077     }
00078     
00079     sequencer = seq;
00080   } 
00081   
00082   
00083   MIDISequencer *MIDIManager::GetSeq() 
00084   {
00085     return sequencer;
00086   } 
00087   
00088   const MIDISequencer *MIDIManager::GetSeq() const 
00089   {
00090     return sequencer;
00091   } 
00092   
00093   
00094 // to set and get the system time offset
00095   void MIDIManager::SetTimeOffset( unsigned long off ) 
00096   {
00097     sys_time_offset = off;
00098   } 
00099   
00100   unsigned long MIDIManager::GetTimeOffset() 
00101   {
00102     return sys_time_offset;
00103   } 
00104   
00105 // to set and get the sequencer time offset
00106   void MIDIManager::SetSeqOffset( unsigned long seqoff ) 
00107   {
00108     seq_time_offset = seqoff;
00109   } 
00110   
00111   unsigned long MIDIManager::GetSeqOffset() 
00112   {
00113     return seq_time_offset;
00114   } 
00115   
00116 // to manage the playback of the sequencer
00117   void MIDIManager::SeqPlay() 
00118   {
00119     stop_mode = false;
00120     play_mode = true;
00121     
00122     if( notifier )
00123     {
00124       notifier->Notify(  sequencer,
00125                          MIDISequencerGUIEvent(
00126                            MIDISequencerGUIEvent::GROUP_TRANSPORT,
00127                            0,
00128                            MIDISequencerGUIEvent::GROUP_TRANSPORT_MODE
00129                            ) );
00130     }
00131     
00132   } 
00133   
00134 // to manage the repeat playback of the sequencer
00135   void MIDIManager::SetRepeatPlay(
00136     bool flag,
00137     unsigned long start_measure,
00138     unsigned long end_measure
00139     ) 
00140   {
00141     // shut off repeat play while we muck with values
00142     repeat_play_mode = false;
00143     repeat_start_measure = start_measure;
00144     repeat_end_measure = end_measure;
00145     
00146     // set repeat mode flag to how we want it.
00147     repeat_play_mode = flag;
00148   } 
00149   
00150   void MIDIManager::SeqStop() 
00151   {
00152     play_mode = false;
00153     stop_mode = true;
00154     
00155     if( notifier )
00156     {
00157       notifier->Notify( sequencer,
00158                         MIDISequencerGUIEvent(
00159                           MIDISequencerGUIEvent::GROUP_TRANSPORT,
00160                           0,
00161                           MIDISequencerGUIEvent::GROUP_TRANSPORT_MODE
00162                           ) );
00163     }
00164     
00165   } 
00166   
00167 // status request functions
00168   bool MIDIManager::IsSeqPlay() const 
00169   {
00170     return play_mode;
00171   } 
00172   
00173   bool MIDIManager::IsSeqStop() const 
00174   {
00175     return stop_mode;
00176   } 
00177   
00178   bool MIDIManager::IsSeqRepeat() const
00179   {
00180     return repeat_play_mode && play_mode;
00181   }
00182   
00183   void MIDIManager::TimeTick( unsigned long sys_time_ ) 
00184   {
00185     if( play_mode )
00186     {
00187       TimeTickPlayMode(sys_time_);
00188     }
00189     else if( stop_mode )
00190     {
00191       TimeTickStopMode(sys_time_);
00192     }
00193     
00194     
00195   } 
00196   
00197   void MIDIManager::TimeTickPlayMode( unsigned long sys_time_ ) 
00198   {
00199     double sys_time = (double)sys_time_ - (double)sys_time_offset;
00200     float next_event_time = 0.0;
00201     int ev_track;
00202     MIDITimedBigMessage ev;
00203     
00204     // if we are in repeat mode, repeat if we hit end of the repeat region
00205     if( repeat_play_mode
00206         && sequencer->GetCurrentMeasure()>=repeat_end_measure
00207       )
00208     {
00209       // yes we hit the end of our repeat block
00210       // shut off all notes on
00211       driver->AllNotesOff();
00212       
00213       // now move the sequencer to our start position
00214       
00215       sequencer->GoToMeasure( repeat_start_measure );
00216       
00217       // our current raw system time is now the new system time offset
00218       
00219       sys_time_offset = sys_time_;
00220       
00221       sys_time = 0;
00222       
00223       // the sequencer time offset now must be reset to the
00224       // time in milliseconds of the sequence start point
00225       
00226       seq_time_offset = (unsigned long)sequencer->GetCurrentTimeInMs();
00227     }
00228     
00229     // find all events that exist before or at this time,
00230     // but only if we have space in the output queue to do so!
00231     
00232     // also limit ourselves to 100 midi events max.
00233     
00234     int output_count=100;
00235     
00236     while(
00237       sequencer->GetNextEventTimeMs( &next_event_time )
00238       && (next_event_time-seq_time_offset)<=sys_time
00239       && driver->CanOutputMessage()
00240       && (--output_count)>0
00241       )
00242     {
00243       // found an event! get it!
00244       
00245       if( sequencer->GetNextEvent( &ev_track, &ev ) )
00246       {
00247         // ok, tell the driver the send this message now
00248         
00249         driver->OutputMessage( ev );
00250       }
00251     }
00252     
00253     
00254     
00255     
00256     // auto stop at end of sequence
00257     
00258     if( !sequencer->GetNextEventTimeMs( &next_event_time ) )
00259     {
00260       // no events left
00261       stop_mode = true;
00262       play_mode = false;
00263       
00264       if( notifier )
00265       {
00266         notifier->Notify( sequencer,
00267                           MIDISequencerGUIEvent(
00268                             MIDISequencerGUIEvent::GROUP_TRANSPORT,
00269                             0,
00270                             MIDISequencerGUIEvent::GROUP_TRANSPORT_MODE
00271                             ) );
00272         
00273         notifier->Notify( sequencer,
00274                           MIDISequencerGUIEvent(
00275                             MIDISequencerGUIEvent::GROUP_TRANSPORT,
00276                             0,
00277                             MIDISequencerGUIEvent::GROUP_TRANSPORT_ENDOFSONG
00278                             ) );
00279         
00280       }
00281     }
00282     
00283   } 
00284   
00285   void MIDIManager::TimeTickStopMode( unsigned long sys_time_ ) 
00286   {
00287   } 
00288 }