player.cc Source File (libkmid Library)

| # libkmid Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# player.cc

    00001 /**************************************************************************
    00002
    00003     player.cc  - class MidiPlayer. Plays a set of tracks
    00004     This file is part of LibKMid 0.9.5
    00005     Copyright (C) 1997,98,99,2000  Antonio Larrosa Jimenez
    00006     LibKMid's homepage : http://www.arrakis.es/~rlarrosa/libkmid.html
    00007
    00008     This library is free software; you can redistribute it and/or
    00009     modify it under the terms of the GNU Library General Public
    00010     License as published by the Free Software Foundation; either
    00011     version 2 of the License, or (at your option) any later version.
    00012
    00013     This library is distributed in the hope that it will be useful,
    00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00016     Library General Public License for more details.
    00017
    00018     You should have received a copy of the GNU Library General Public License
    00019     along with this library; see the file COPYING.LIB.  If not, write to
    00020     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    00021     Boston, MA 02111-1307, USA.
    00022
    00023     $Id: player.cc,v 1.42.2.1 2002/12/07 16:53:35 waba Exp $
    00024
    00025     Send comments and bug fixes to Antonio Larrosa <larrosa@kde.org>
    00026
    00027 ***************************************************************************/
    00028 #include "player.h"
    00029 #include "sndcard.h"
    00030 #include "midispec.h"
    00031 #include <string.h>
    00032 #include <unistd.h>
    00033 #include <sys/time.h>
    00034 #include "midistat.h"
    00035 #include "mt32togm.h"
    00036
    00037 //#define PLAYERDEBUG
    00038 //#define GENERAL_DEBUG_MESSAGES
    00039
    00040 #define T2MS(ticks) (((double)ticks)*(double)60000L)/((double)tempoToMetronomeTempo(tempo)*(double)info->ticksPerCuarterNote)
    00041
    00042 #define MS2T(ms) (((ms)*(double)tempoToMetronomeTempo(tempo)*(double)info->ticksPerCuarterNote)/((double)60000L))
    00043
    00044 #define REMOVEDUPSTRINGS
    00045
    00046 MidiPlayer::MidiPlayer(DeviceManager *midi_,PlayerController *pctl)
    00047 {
    00048   midi=midi_;
    00049   info=NULL;
    00050   tracks=NULL;
    00051   songLoaded=0;
    00052   ctl=pctl;
    00053   spev=NULL;
    00054   na=NULL;
    00055   parsesong=true;
    00056   generatebeats=false;
    00057 }
    00058
    00059 MidiPlayer::~MidiPlayer()
    00060 {
    00061   removeSpecialEvents();
    00062   removeSong();
    00063 }
    00064
    00065 void MidiPlayer::removeSong(void)
    00066 {
    00067   if ((songLoaded)&&(tracks!=NULL))
    00068   {
    00069 #ifdef PLAYERDEBUG
    00070     printf("Removing song from memory\n");
    00071 #endif
    00072     int i=0;
    00073     while (i<info->ntracks)
    00074     {
    00075       if (tracks[i]!=NULL) delete tracks[i];
    00076       i++;
    00077     }
    00078     delete tracks;
    00079     tracks=NULL;
    00080     if (info!=NULL)
    00081     {
    00082       delete info;
    00083       info=NULL;
    00084     }
    00085   }
    00086   songLoaded=0;
    00087 }
    00088
    00089 int MidiPlayer::loadSong(const char *filename)
    00090 {
    00091   removeSong();
    00092 #ifdef PLAYERDEBUG
    00093   printf("Loading Song : %s\n",filename);
    00094 #endif
    00095   info=new MidiFileInfo;
    00096   int ok;
    00097   tracks=readMidiFile(filename,info,ok);
    00098   if (ok<0) return ok;
    00099   if (tracks==NULL) return -4;
    00100
    00101   parseInfoData(info,tracks,ctl->ratioTempo);
    00102
    00103   if (parsesong)
    00104   {
    00105     parseSpecialEvents();
    00106     if (generatebeats) generateBeats();
    00107   }
    00108
    00109   songLoaded=1;
    00110   return 0;
    00111 }
    00112
    00113 void MidiPlayer::insertBeat(SpecialEvent *ev,ulong ms,int num,int den)
    00114 {
    00115   SpecialEvent *beat=new SpecialEvent;
    00116   beat->next=ev->next;
    00117   ev->next=beat;
    00118   beat->id=1;
    00119   beat->type=7;
    00120   beat->absmilliseconds=ms;
    00121   beat->num=num;
    00122   beat->den=den;
    00123 }
    00124
    00125
    00126 void MidiPlayer::generateBeats(void)
    00127 {
    00128 #ifdef PLAYERDEBUG
    00129   printf("player::Generating Beats...\n");
    00130 #endif
    00131
    00132   if (spev==NULL) return;
    00133   SpecialEvent *ev=spev;
    00134   SpecialEvent *nextev=ev->next;
    00135   ulong tempo=(ulong)(500000 * ctl->ratioTempo);
    00136   int i=1;
    00137   int num=4;
    00138   int den=4;
    00139   //    ulong beatstep=((double)tempo*4/(den*1000));
    00140   //    ulong beatstep=T2MS(info->ticksPerCuarterNote*(4/den));
    00141   double ticksleft=(((double)info->ticksPerCuarterNote*4)/den);
    00142
    00143   double beatstep=T2MS(ticksleft);
    00144   double nextbeatms=0;
    00145   double lastbeatms=0;
    00146   double measurems=0;
    00147
    00148   while (nextev!=NULL)
    00149   {
    00150     switch (ev->type)
    00151     {
    00152       case (0): // End of list
    00153         {
    00154         };break;
    00155       case (1): // Text
    00156       case (2): // Lyrics
    00157         {
    00158         };break;
    00159       case (3): // Change Tempo
    00160         {
    00161           lastbeatms=ev->absmilliseconds;
    00162           ticksleft=MS2T(nextbeatms-lastbeatms);
    00163           tempo=ev->tempo;
    00164           nextbeatms=lastbeatms+T2MS(ticksleft);
    00165           // printf("Change at %lu to %d\n",ev->absmilliseconds,ev->tempo);
    00166           // beatstep=((double)tempo*4/(den*1000));
    00167           beatstep=T2MS(((static_cast<double>(info->ticksPerCuarterNote)*4)/den));
    00168         };break;
    00169       case (6): // Change number of beats per measure
    00170         {
    00171           num=ev->num;
    00172           i=1;
    00173           den=ev->den;
    00174           // printf("Change at %lu to %d/%d\n",ev->absmilliseconds,num,den);
    00175           // beatstep=((double)tempo*4/(den*1000));
    00176           // beatstep=T2MS(info->ticksPerCuarterNote*(4/den));
    00177           beatstep=T2MS((((double)info->ticksPerCuarterNote*4)/den));
    00178           nextbeatms=ev->absmilliseconds;
    00179         };break;
    00180     };
    00181     if (nextev->absmilliseconds>nextbeatms)
    00182     {
    00183       //printf("Adding %d,%d\n",num,tot);
    00184       //printf("beat at %g , %d/%d\n",nextbeatms,i,num);
    00185       //printf("  %ld %d\n",nextev->absmilliseconds,nextev->type);
    00186       if (i == 1) {
    00187           measurems=nextbeatms;
    00188       }
    00189       insertBeat(ev, static_cast<unsigned long>(nextbeatms), i++, num);
    00190       if (i > num) {
    00191           i=1;
    00192       }
    00193       lastbeatms=nextbeatms;
    00194       nextbeatms+=beatstep;
    00195       // nextbeatms=measurems+beatstep*i;
    00196
    00197       ticksleft = ( (static_cast<double>(info->ticksPerCuarterNote)*4) / den);
    00198
    00199     }
    00200
    00201     ev=ev->next;
    00202     nextev=ev->next;
    00203   }
    00204
    00205   /* ev==NULL doesn't indicate the end of the song, so continue generating beats */
    00206
    00207   if (ev!=NULL)
    00208   {
    00209     if (ev->type==0)
    00210     {
    00211       ev=spev;
    00212       /* Looking if ev->next is NULL is not needed because
    00213          we are sure that a ev->type == 0 exists, we just have
    00214          to assure that the first spev is not the only one */
    00215       if (ev->next!=NULL)
    00216         while (ev->next->type!=0) ev=ev->next;
    00217     }
    00218     while (nextbeatms<info->millisecsTotal)
    00219     {
    00220       //            printf("beat2 at %g , %d/%d\n",nextbeatms,i,num);
    00221       if (i==1) measurems=nextbeatms;
    00222       insertBeat(ev, static_cast<unsigned long>(nextbeatms), i++, num);
    00223       if (i>num) i=1;
    00224       nextbeatms+=beatstep;
    00225       ev=ev->next;
    00226     }
    00227   }
    00228
    00229   /* Regenerate IDs */
    00230
    00231   ev=spev;
    00232   i=1;
    00233   while (ev!=NULL)
    00234   {
    00235     ev->id=i++;
    00236     ev=ev->next;
    00237   }
    00238
    00239
    00240 #ifdef PLAYERDEBUG
    00241   printf("player::Beats Generated\n");
    00242 #endif
    00243
    00244 }
    00245
    00246 void MidiPlayer::removeSpecialEvents(void)
    00247 {
    00248   SpecialEvent * ev=spev;
    00249   while (spev!=NULL)
    00250   {
    00251     ev=spev->next;
    00252     delete spev;
    00253     spev=ev;
    00254   }
    00255   delete na;
    00256   na=0;
    00257 }
    00258
    00259 void MidiPlayer::parseSpecialEvents(void)
    00260 {
    00261 #ifdef PLAYERDEBUG
    00262   printf("player::Parsing...\n");
    00263 #endif
    00264   removeSpecialEvents();
    00265   spev=new SpecialEvent;
    00266   if (spev==NULL) return;
    00267   SpecialEvent *pspev=spev;
    00268   pspev->type=0;
    00269   pspev->ticks=0;
    00270   if (na) delete na;
    00271   na=new NoteArray();
    00272   if (!na) { delete spev; spev=0L; return; };
    00273   int trk;
    00274   int minTrk;
    00275   double minTime=0;
    00276   double maxTime;
    00277   ulong tempo=(ulong)(500000 * (ctl->ratioTempo));
    00278   ulong firsttempo=0;
    00279   for (int i=0;i<info->ntracks;i++)
    00280   {
    00281     tracks[i]->init();
    00282     tracks[i]->changeTempo(tempo);
    00283   }
    00284   MidiEvent *ev=new MidiEvent;
    00285   //ulong mspass;
    00286   double prevms=0;
    00287   int spev_id=1;
    00288   int j;
    00289   int parsing=1;
    00290 #ifdef REMOVEDUPSTRINGS
    00291   char lasttext[1024];
    00292   ulong lasttexttime=0;
    00293   lasttext[0]=0;
    00294   int lasttexttype=0;
    00295 #endif
    00296   while (parsing)
    00297   {
    00298     prevms=minTime;
    00299     trk=0;
    00300     minTrk=0;
    00301     maxTime=minTime + 2 * 60000L;
    00302     minTime=maxTime;
    00303     parsing=0;
    00304     while (trk<info->ntracks)
    00305     {
    00306       if (tracks[trk]->absMsOfNextEvent()<minTime)
    00307       {
    00308         minTrk=trk;
    00309         minTime=tracks[minTrk]->absMsOfNextEvent();
    00310         parsing=1;
    00311       }
    00312       trk++;
    00313     }
    00314     //  if ((minTime==maxTime))
    00315     if (parsing==0)
    00316     {
    00317       // parsing=0;
    00318 #ifdef PLAYERDEBUG
    00319       printf("END of parsing\n");
    00320 #endif
    00321     }
    00322     else
    00323     {
    00324       // mspass=(ulong)(minTime-prevms);
    00325       trk=0;
    00326       while (trk<info->ntracks)
    00327       {
    00328         tracks[trk]->currentMs(minTime);
    00329         trk++;
    00330       }
    00331     }
    00332     trk=minTrk;
    00333     tracks[trk]->readEvent(ev);
    00334     switch (ev->command)
    00335     {
    00336       case (MIDI_NOTEON) :
    00337         if (ev->vel==0) na->add((ulong)minTime,ev->chn,0, ev->note);
    00338         else na->add((ulong)minTime,ev->chn,1,ev->note);
    00339         break;
    00340       case (MIDI_NOTEOFF) :
    00341         na->add((ulong)minTime,ev->chn,0, ev->note);
    00342         break;
    00343       case (MIDI_PGM_CHANGE) :
    00344         na->add((ulong)minTime,ev->chn, 2,ev->patch);
    00345         break;
    00346       case (MIDI_SYSTEM_PREFIX) :
    00347         {
    00348           if ((ev->command|ev->chn)==META_EVENT)
    00349           {
    00350             switch (ev->d1)
    00351             {
    00352               case (1) :
    00353               case (5) :
    00354                 {
    00355                   if (pspev!=NULL)
    00356                   {
    00357                     pspev->absmilliseconds=(ulong)minTime;
    00358                     pspev->type=ev->d1;
    00359                     pspev->id=spev_id++;
    00360 #ifdef PLAYERDEBUG
    00361                     printf("ev->length %ld\n",ev->length);
    00362
    00363 #endif
    00364                     strncpy(pspev->text,(char *)ev->data,
    00365                         (ev->length>1024)? (1023) : (ev->length) );
    00366                     pspev->text[(ev->length>1024)? (1023):(ev->length)]=0;
    00367 #ifdef PLAYERDEBUG
    00368                     printf("(%s)(%s)\n",pspev->text,lasttext);
    00369 #endif
    00370 #ifdef REMOVEDUPSTRINGS
    00371                     if ((strcmp(pspev->text,lasttext)!=0)||(pspev->absmilliseconds!=lasttexttime)||(pspev->type!=lasttexttype))
    00372                     {
    00373                       lasttexttime=pspev->absmilliseconds;
    00374                       lasttexttype=pspev->type;
    00375                       strncpy(lasttext, pspev->text, 1024);
    00376                       lasttext[1023] = 0;
    00377 #endif
    00378                       pspev->next=new SpecialEvent;
    00379 #ifdef PLAYERDEBUG
    00380                       if (pspev->next==NULL) printf("pspev->next=NULL\n");
    00381 #endif
    00382                       pspev=pspev->next;
    00383 #ifdef REMOVEDUPSTRINGS
    00384                     }
    00385 #endif
    00386                   }
    00387                 }
    00388                 break;
    00389               case (ME_SET_TEMPO) :
    00390                 {
    00391                   if (pspev!=NULL)
    00392                   {
    00393                     pspev->absmilliseconds=(ulong)minTime;
    00394                     pspev->type=3;
    00395                     pspev->id=spev_id++;
    00396                     tempo=(ulong)(((ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2])) * ctl->ratioTempo);
    00397                     pspev->tempo=tempo;
    00398                     if (firsttempo==0) firsttempo=tempo;
    00399                     for (j=0;j<info->ntracks;j++)
    00400                     {
    00401                       tracks[j]->changeTempo(tempo);
    00402                     }
    00403                     pspev->next=new SpecialEvent;
    00404                     pspev=pspev->next;
    00405                   }
    00406                 }
    00407                 break;
    00408               case (ME_TIME_SIGNATURE) :
    00409                 {
    00410                   if (pspev!=NULL)
    00411                   {
    00412                     pspev->absmilliseconds=(ulong)minTime;
    00413                     pspev->type=6;
    00414                     pspev->id=spev_id++;
    00415                     pspev->num=ev->d2;
    00416                     pspev->den=ev->d3;
    00417                     pspev->next=new SpecialEvent;
    00418                     pspev=pspev->next;
    00419                   }
    00420                 }
    00421                 break;
    00422             }
    00423           }
    00424         }
    00425         break;
    00426     }
    00427   }
    00428
    00429   delete ev;
    00430   pspev->type=0;
    00431   pspev->absmilliseconds=(ulong)prevms;
    00432   pspev->next=NULL;
    00433   if (firsttempo==0) firsttempo=tempo;
    00434   ctl->tempo=firsttempo;
    00435
    00436   //writeSPEV();
    00437   for (int i=0;i<info->ntracks;i++)
    00438   {
    00439     tracks[i]->init();
    00440   }
    00441 }
    00442
    00443 /*
    00444 NoteArray *MidiPlayer::parseNotes(void)
    00445 {
    00446 #ifdef PLAYERDEBUG
    00447   printf("player::Parsing Notes...\n");
    00448 #endif
    00449   NoteArray *na=new NoteArray();
    00450   int trk;
    00451   int minTrk;
    00452   double minTime=0;
    00453   double maxTime;
    00454   for (int i=0;i<info->ntracks;i++)
    00455   {
    00456     tracks[i]->init();
    00457   };
    00458   ulong tempo=1000000;
    00459   ulong tmp;
    00460   Midi_event *ev=new Midi_event;
    00461   //ulong mspass;
    00462   double prevms=0;
    00463   int j;
    00464   int parsing=1;
    00465   while (parsing)
    00466   {
    00467     prevms=minTime;
    00468     trk=0;
    00469     minTrk=0;
    00470     maxTime=minTime + 2 * 60000L;
    00471     minTime=maxTime;
    00472     while (trk<info->ntracks)
    00473     {
    00474       if (tracks[trk]->absMsOfNextEvent()<minTime)
    00475       {
    00476         minTrk=trk;
    00477         minTime=tracks[minTrk]->absMsOfNextEvent();
    00478       };
    00479       trk++;
    00480     };
    00481     if ((minTime==maxTime))
    00482     {
    00483       parsing=0;
    00484 #ifdef PLAYERDEBUG
    00485       printf("END of parsing\n");
    00486 #endif
    00487     }
    00488     else
    00489     {
    00490       //        mspass=(ulong)(minTime-prevms);
    00491       trk=0;
    00492       while (trk<info->ntracks)
    00493       {
    00494         tracks[trk]->currentMs(minTime);
    00495         trk++;
    00496       };
    00497     };
    00498     trk=minTrk;
    00499     tracks[trk]->readEvent(ev);
    00500     if (ev->command==MIDI_NOTEON)
    00501     {
    00502       if (ev->vel==0) {printf("note off at %g\n",minTime);na->add((ulong)minTime,ev->chn,0, ev->note);}
    00503       else {printf("note on at %g\n",minTime);na->add((ulong)minTime,ev->chn,1,ev->note);}
    00504     }
    00505     else
    00506       if (ev->command==MIDI_NOTEOFF) na->add((ulong)minTime,ev->chn,0, ev->note);
    00507     if (ev->command==MIDI_PGM_CHANGE) na->add((ulong)minTime,ev->chn, 2,ev->patch);
    00508     if (ev->command==MIDI_SYSTEM_PREFIX)
    00509     {
    00510       if (((ev->command|ev->chn)==META_EVENT)&&(ev->d1==ME_SET_TEMPO))
    00511       {
    00512         tempo=(ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2]);
    00513         for (j=0;j<info->ntracks;j++)
    00514         {
    00515           tracks[j]->changeTempo(tempo);
    00516         };
    00517       };
    00518     };
    00519
    00520   };
    00521
    00522   delete ev;
    00523   for (int i=0;i<info->ntracks;i++)
    00524   {
    00525     tracks[i]->init();
    00526   };
    00527   return na;
    00528 };
    00529 */
    00530
    00531 void MidiPlayer::play(bool calloutput,void output(void))
    00532 {
    00533 #ifdef PLAYERDEBUG
    00534   printf("Playing...\n");
    00535 #endif
    00536
    00537   if (midi->midiPorts()+midi->synthDevices()==0)
    00538   {
    00539     fprintf(stderr,"Player :: There are no midi ports !\n");
    00540     ctl->error=1;
    00541     return;
    00542   }
    00543
    00544   midi->openDev();
    00545   if (midi->ok()==0)
    00546   {
    00547     fprintf(stderr,"Player :: Couldn't play !\n");
    00548     ctl->error=1;
    00549     return;
    00550   }
    00551   midi->setVolumePercentage(ctl->volumepercentage);
    00552   midi->initDev();
    00553   //    parsePatchesUsed(tracks,info,ctl->gm);
    00554   midi->setPatchesToUse(info->patchesUsed);
    00555
    00556   int trk;
    00557   int minTrk;
    00558   double minTime=0;
    00559   double maxTime;
    00560   int i;
    00561   ulong tempo=(ulong)(500000 * ctl->ratioTempo);
    00562   for (i=0;i<info->ntracks;i++)
    00563   {
    00564     tracks[i]->init();
    00565     tracks[i]->changeTempo(tempo);
    00566   }
    00567
    00568   midi->tmrStart(info->ticksPerCuarterNote);
    00569   MidiEvent *ev=new MidiEvent;
    00570   ctl->ev=ev;
    00571   ctl->ticksTotal=info->ticksTotal;
    00572   ctl->ticksPlayed=0;
    00573   //ctl->millisecsPlayed=0;
    00574   ulong ticksplayed=0;
    00575   double absTimeAtChangeTempo=0;
    00576   double absTime=0;
    00577   double diffTime=0;
    00578   MidiStatus *midistat;
    00579   //ulong mspass;
    00580   double prevms=0;
    00581   int j;
    00582   int halt=0;
    00583   ctl->tempo=tempo;
    00584   ctl->num=4;
    00585   ctl->den=4;
    00586   int playing;
    00587   ctl->paused=0;
    00588   if ((ctl->message!=0)&&(ctl->message & PLAYER_SETPOS))
    00589   {
    00590     ctl->moving=1;
    00591     ctl->message&=~PLAYER_SETPOS;
    00592     midi->sync(1);
    00593     midi->tmrStop();
    00594     midi->closeDev();
    00595     midistat = new MidiStatus();
    00596     setPos(ctl->gotomsec,midistat);
    00597     minTime=ctl->gotomsec;
    00598     prevms=(ulong)minTime;
    00599     midi->openDev();
    00600     midi->tmrStart(info->ticksPerCuarterNote);
    00601     diffTime=ctl->gotomsec;
    00602     midistat->sendData(midi,ctl->gm);
    00603     delete midistat;
    00604     midi->setPatchesToUse(info->patchesUsed);
    00605     ctl->moving=0;
    00606   } else
    00607     for (i=0;i<16;i++)
    00608     {
    00609       if (ctl->forcepgm[i])
    00610       {
    00611         midi->chnPatchChange(i, ctl->pgm[i]);
    00612       }
    00613     }
    00614
    00615   timeval begintv;
    00616   gettimeofday(&begintv, NULL);
    00617   ctl->beginmillisec=begintv.tv_sec*1000+begintv.tv_usec/1000;
    00618   ctl->OK=1;
    00619   ctl->playing=playing=1;
    00620
    00621   while (playing)
    00622     {
    00623       /*
    00624       if (ctl->message!=0)
    00625       {
    00626         if (ctl->message & PLAYER_DOPAUSE)
    00627         {
    00628           diffTime=minTime;
    00629           ctl->message&=~PLAYER_DOPAUSE;
    00630           midi->sync(1);
    00631           midi->tmrStop();
    00632           ctl->paused=1;
    00633           midi->closeDev();
    00634           while ((ctl->paused)&&(!(ctl->message&PLAYER_DOSTOP))
    00635               &&(!(ctl->message&PLAYER_HALT))) sleep(1);
    00636           midi->openDev();
    00637           midi->tmrStart();
    00638           ctl->OK=1;
    00639           printf("Continue playing ... \n");
    00640         };
    00641         if (ctl->message & PLAYER_DOSTOP)
    00642         {
    00643           ctl->message&=~PLAYER_DOSTOP;
    00644           playing=0;
    00645         };
    00646         if (ctl->message & PLAYER_HALT)
    00647         {
    00648           ctl->message&=~PLAYER_HALT;
    00649           playing=0;
    00650           halt=1;
    00651         };
    00652         if (ctl->message & PLAYER_SETPOS)
    00653         {
    00654           ctl->moving=1;
    00655           ctl->message&=~PLAYER_SETPOS;
    00656           midi->sync(1);
    00657           midi->tmrStop();
    00658           midi->closeDev();
    00659           midistat = new midiStat();
    00660           SetPos(ctl->gotomsec,midistat);
    00661           minTime=ctl->gotomsec;
    00662           prevms=(ulong)minTime;
    00663           midi->openDev();
    00664           midi->tmrStart();
    00665           diffTime=ctl->gotomsec;
    00666           ctl->moving=0;
    00667           midistat->sendData(midi,ctl->gm);
    00668           delete midistat;
    00669           ctl->OK=1;
    00670           while (ctl->OK==1) ;
    00671           ctl->moving=0;
    00672         };
    00673       };
    00674       */
    00675         prevms=minTime;
    00676       //    ctl->millisecsPlayed=minTime;
    00677       trk=0;
    00678       minTrk=0;
    00679       maxTime=minTime + 120000L /* milliseconds */;
    00680         minTime=maxTime;
    00681       playing=0;
    00682       while (trk<info->ntracks)
    00683       {
    00684         if (tracks[trk]->absMsOfNextEvent()<minTime)
    00685         {
    00686           minTrk=trk;
    00687           minTime=tracks[minTrk]->absMsOfNextEvent();
    00688           playing=1;
    00689         }
    00690         trk++;
    00691       }
    00692 #ifdef PLAYERDEBUG
    00693       printf("minTime %g\n",minTime);
    00694 #endif
    00695       // if ((minTime==maxTime)/* || (minTicks> 60000L)*/)
    00696       if (playing==0)
    00697       {
    00698         // playing=0;
    00699 #ifdef PLAYERDEBUG
    00700         printf("END of playing\n");
    00701 #endif
    00702       }
    00703       else
    00704       {
    00705         // mspass=(ulong)(minTime-prevms);
    00706         trk=0;
    00707         while (trk<info->ntracks)
    00708         {
    00709           tracks[trk]->currentMs(minTime);
    00710           trk++;
    00711         }
    00712         midi->wait(minTime-diffTime);
    00713       }
    00714       trk=minTrk;
    00715       tracks[trk]->readEvent(ev);
    00716       switch (ev->command)
    00717       {
    00718         case (MIDI_NOTEON) :
    00719           midi->noteOn(ev->chn, ev->note, ev->vel);break;
    00720         case (MIDI_NOTEOFF):
    00721           midi->noteOff(ev->chn, ev->note, ev->vel);break;
    00722         case (MIDI_KEY_PRESSURE) :
    00723           midi->keyPressure(ev->chn, ev->note,ev->vel);break;
    00724         case (MIDI_PGM_CHANGE) :
    00725           if (!ctl->forcepgm[ev->chn])
    00726             midi->chnPatchChange(ev->chn, (ctl->gm==1)?(ev->patch):(MT32toGM[ev->patch]));break;
    00727         case (MIDI_CHN_PRESSURE) :
    00728           midi->chnPressure(ev->chn, ev->vel);break;
    00729         case (MIDI_PITCH_BEND) :
    00730           midi->chnPitchBender(ev->chn, ev->d1,ev->d2);break;
    00731         case (MIDI_CTL_CHANGE) :
    00732           midi->chnController(ev->chn, ev->ctl,ev->d1);break;
    00733         case (MIDI_SYSTEM_PREFIX) :
    00734           if ((ev->command|ev->chn)==META_EVENT)
    00735           {
    00736             if ((ev->d1==5)||(ev->d1==1))
    00737             {
    00738               ctl->SPEVplayed++;
    00739             }
    00740             if (ev->d1==ME_SET_TEMPO)
    00741             {
    00742               absTimeAtChangeTempo=absTime;
    00743               ticksplayed=0;
    00744               ctl->SPEVplayed++;
    00745               tempo=(ulong)(((ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2]))*ctl->ratioTempo);
    00746 #ifdef PLAYERDEBUG
    00747               printf("Tempo : %ld %g (ratio : %g)\n",tempo,tempoToMetronomeTempo(tempo),ctl->ratioTempo);
    00748 #endif
    00749               midi->tmrSetTempo((int)tempoToMetronomeTempo(tempo));
    00750               ctl->tempo=tempo;
    00751               for (j=0;j<info->ntracks;j++)
    00752               {
    00753                 tracks[j]->changeTempo(tempo);
    00754               }
    00755             }
    00756             if (ev->d1==ME_TIME_SIGNATURE)
    00757             {
    00758               ctl->num=ev->d2;
    00759               ctl->den=ev->d3;
    00760               ctl->SPEVplayed++;
    00761             }
    00762           }
    00763           break;
    00764       }
    00765       if (calloutput)
    00766       {
    00767         midi->sync();
    00768         output();
    00769       }
    00770
    00771     }
    00772   ctl->ev=NULL;
    00773   delete ev;
    00774 #ifdef PLAYERDEBUG
    00775   printf("Syncronizing ...\n");
    00776 #endif
    00777   if (halt)
    00778     midi->sync(1);
    00779   else
    00780     midi->sync();
    00781 #ifdef PLAYERDEBUG
    00782   printf("Closing device ...\n");
    00783 #endif
    00784   midi->allNotesOff();
    00785   midi->closeDev();
    00786   ctl->playing=0;
    00787 #ifdef PLAYERDEBUG
    00788   printf("Bye...\n");
    00789 #endif
    00790   ctl->OK=1;
    00791   ctl->finished=1;
    00792 }
    00793
    00794
    00795 void MidiPlayer::setPos(ulong gotomsec,MidiStatus *midistat)
    00796 {
    00797   int trk,minTrk;
    00798   ulong tempo=(ulong)(500000 * ctl->ratioTempo);
    00799   double minTime=0,maxTime,prevms=0;
    00800   int i,j,likeplaying=1;
    00801
    00802   MidiEvent *ev=new MidiEvent;
    00803   ctl->SPEVplayed=0;
    00804   for (i=0;i<info->ntracks;i++)
    00805   {
    00806     tracks[i]->init();
    00807     tracks[i]->changeTempo(tempo);
    00808   }
    00809
    00810   for (i=0;i<16;i++)
    00811   {
    00812     if (ctl->forcepgm[i]) midistat->chnPatchChange(i, ctl->pgm[i]);
    00813   }
    00814
    00815   while (likeplaying)
    00816   {
    00817     trk=0;
    00818     minTrk=0;
    00819     maxTime=minTime + 120000L; /*milliseconds (2 minutes)*/
    00820     minTime=maxTime;
    00821     while (trk<info->ntracks)
    00822     {
    00823       if (tracks[trk]->absMsOfNextEvent()<minTime)
    00824       {
    00825         minTrk=trk;
    00826         minTime=tracks[minTrk]->absMsOfNextEvent();
    00827       }
    00828       trk++;
    00829     }
    00830     if (minTime==maxTime)
    00831     {
    00832       likeplaying=0;
    00833 #ifdef GENERAL_DEBUG_MESSAGES
    00834       printf("END of likeplaying\n");
    00835 #endif
    00836     }
    00837     else
    00838     {
    00839       if (minTime>=gotomsec)
    00840       {
    00841         prevms=gotomsec;
    00842         likeplaying=0;
    00843 #ifdef GENERAL_DEBUG_MESSAGES
    00844         printf("Position reached !! \n");
    00845 #endif
    00846         minTime=gotomsec;
    00847       }
    00848       else
    00849       {
    00850         prevms=minTime;
    00851       }
    00852       trk=0;
    00853       while (trk<info->ntracks)
    00854       {
    00855         tracks[trk]->currentMs(minTime);
    00856         trk++;
    00857       }
    00858     }
    00859
    00860     if (likeplaying)
    00861     {
    00862       trk=minTrk;
    00863       tracks[trk]->readEvent(ev);
    00864       switch (ev->command)
    00865       {
    00866         /*  case (MIDI_NOTEON) :
    00867             midistat->noteOn(ev->chn, ev->note, ev->vel);break;
    00868             case (MIDI_NOTEOFF):
    00869             midistat->noteOff(ev->chn, ev->note, ev->vel);break;
    00870             case (MIDI_KEY_PRESSURE) :
    00871             midistat->keyPressure(ev->chn, ev->note,ev->vel);break;
    00872          */
    00873         case (MIDI_PGM_CHANGE) :
    00874           if (!ctl->forcepgm[ev->chn]) midistat->chnPatchChange(ev->chn, ev->patch);break;
    00875         case (MIDI_CHN_PRESSURE) :
    00876           midistat->chnPressure(ev->chn, ev->vel);break;
    00877         case (MIDI_PITCH_BEND) :
    00878           midistat->chnPitchBender(ev->chn, ev->d1,ev->d2);break;
    00879         case (MIDI_CTL_CHANGE) :
    00880           midistat->chnController(ev->chn, ev->ctl,ev->d1);break;
    00881         case (MIDI_SYSTEM_PREFIX) :
    00882           if ((ev->command|ev->chn)==META_EVENT)
    00883           {
    00884             if ((ev->d1==5)||(ev->d1==1))
    00885             {
    00886               ctl->SPEVplayed++;
    00887             }
    00888             if (ev->d1==ME_SET_TEMPO)
    00889             {
    00890               ctl->SPEVplayed++;
    00891               tempo=(ulong)(((ev->data[0]<<16)|(ev->data[1]<<8)|(ev->data[2]))*ctl->ratioTempo);
    00892
    00893               midistat->tmrSetTempo((int)tempoToMetronomeTempo(tempo));
    00894               for (j=0;j<info->ntracks;j++)
    00895               {
    00896                 tracks[j]->changeTempo(tempo);
    00897               }
    00898             }
    00899             if (ev->d1==ME_TIME_SIGNATURE)
    00900             {
    00901               ctl->num=ev->d2;
    00902               ctl->den=ev->d3;
    00903               ctl->SPEVplayed++;
    00904             }
    00905           }
    00906           break;
    00907       }
    00908     }
    00909   }
    00910   delete ev;
    00911   ctl->tempo=tempo;
    00912 }
    00913
    00914
    00915 void MidiPlayer::debugSpecialEvents(void)
    00916 {
    00917   SpecialEvent *pspev=spev;
    00918   printf("**************************************\n");
    00919   while ((pspev!=NULL)&&(pspev->type!=0))
    00920   {
    00921     printf("t:%d ticks:%d diff:%ld abs:%ld s:%s tempo:%ld\n",pspev->type,pspev->ticks,pspev->diffmilliseconds,pspev->absmilliseconds,pspev->text,pspev->tempo);
    00922     pspev=pspev->next;
    00923   }
    00924
    00925 }
    00926
    00927 void MidiPlayer::setParseSong(bool b)
    00928 {
    00929   parsesong=b;
    00930 }
    00931
    00932 void MidiPlayer::setGenerateBeats(bool b)
    00933 {
    00934   generatebeats=b;
    00935 }
    00936
    00937 void MidiPlayer::setTempoRatio(double ratio)
    00938 {
    00939   if (songLoaded)
    00940   {
    00941     ctl->ratioTempo=ratio;
    00942     parseInfoData(info,tracks,ctl->ratioTempo);
    00943     if (parsesong)
    00944     {
    00945       parseSpecialEvents();
    00946       if (generatebeats) generateBeats();
    00947
    00948     }
    00949   }
    00950   else
    00951   {
    00952     ctl->tempo=(ulong)((ctl->tempo*ctl->ratioTempo)/ratio);
    00953     ctl->ratioTempo=ratio;
    00954   }
    00955
    00956 }
    00957
    00958 #undef T2MS
    00959 #undef MS2T

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:28:30 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001