win_midiout.cc

Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2000, 2001, 2002  Ryan Nunn
00003 
00004 This program is free software; you can redistribute it and/or
00005 modify it under the terms of the GNU General Public License
00006 as published by the Free Software Foundation; either version 2
00007 of the License, or (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00017 */
00018 
00019 #ifdef HAVE_CONFIG_H
00020 #  include <config.h>
00021 #endif
00022 
00023 
00024 //Windows-specific code
00025 #if defined(WIN32) && !defined(UNDER_CE)
00026 
00027 #ifndef WIN32_LEAN_AND_MEAN
00028 #define WIN32_LEAN_AND_MEAN
00029 #endif
00030 
00031 // These will prevent inclusion of mmsystem sections
00032 #define MMNODRV         // Installable driver support
00033 #define MMNOSOUND       // Sound support
00034 #define MMNOWAVE        // Waveform support
00035 #define MMNOAUX         // Auxiliary audio support
00036 #define MMNOMIXER       // Mixer support
00037 #define MMNOTIMER       // Timer support
00038 #define MMNOJOY         // Joystick support
00039 #define MMNOMCI         // MCI support
00040 #define MMNOMMIO        // Multimedia file I/O support
00041 
00042 #include <windows.h>
00043 #include <mmsystem.h>
00044 #include <winbase.h>
00045 
00046 #include <string>
00047 
00048 #include "win_midiout.h"
00049 #include "../xmidi.h"
00050 
00051 #include "../../files/utils.h"
00052 #include "../../conf/Configuration.h"
00053 
00054 extern  Configuration *config;
00055 
00056 #define W32MO_THREAD_COM_READY    0
00057 #define W32MO_THREAD_COM_PLAY   1
00058 #define W32MO_THREAD_COM_STOP   2
00059 #define W32MO_THREAD_COM_INIT   3
00060 #define W32MO_THREAD_COM_INIT_FAILED  4
00061 #define W32MO_THREAD_COM_EXIT   -1
00062 
00063 const unsigned short Windows_MidiOut::centre_value = 0x2000;
00064 const unsigned char Windows_MidiOut::fine_value = centre_value & 127;
00065 const unsigned char Windows_MidiOut::coarse_value = centre_value >> 7;
00066 const unsigned short Windows_MidiOut::combined_value = (coarse_value << 8) | fine_value;
00067 
00068 //#define DO_SMP_TEST
00069 
00070 #ifdef DO_SMP_TEST
00071 #define giveinfo() std::cerr << __FILE__ << ":" << __LINE__ << std::endl; std::cerr.flush();
00072 #else
00073 #define giveinfo()
00074 #endif
00075 
00076 using std::string;
00077 using std::cout;
00078 using std::cerr;
00079 using std::endl;
00080 
00081 Windows_MidiOut::Windows_MidiOut() : dev_num(-1)
00082 {
00083   giveinfo();
00084   InterlockedExchange (&playing, false);
00085   InterlockedExchange (&s_playing, false);
00086   InterlockedExchange (&is_available, false);
00087   giveinfo();
00088   init_device();
00089   giveinfo();
00090 }
00091 
00092 Windows_MidiOut::~Windows_MidiOut()
00093 {
00094   giveinfo();
00095   if (!is_available) return;
00096 
00097   giveinfo();
00098   while (thread_com != W32MO_THREAD_COM_READY) Sleep (1);
00099   
00100   giveinfo();
00101   InterlockedExchange (&thread_com, W32MO_THREAD_COM_EXIT);
00102 
00103   giveinfo();
00104   int count = 0;
00105   
00106   giveinfo();
00107   while (count < 100)
00108   {
00109     giveinfo();
00110     DWORD code;
00111     GetExitCodeThread (thread_handle, &code);
00112     
00113     giveinfo();
00114     // Wait 1 MS before trying again
00115     if (code == STILL_ACTIVE) Sleep (1);
00116     else break;
00117     giveinfo();
00118     
00119     count++;
00120   }
00121 
00122   // We waited a second and it still didn't terminate
00123   giveinfo();
00124   if (count == 100 && is_available)
00125     TerminateThread (thread_handle, 1);
00126 
00127   giveinfo();
00128   InterlockedExchange (&is_available, false);
00129   giveinfo();
00130 }
00131 
00132 void Windows_MidiOut::init_device()
00133 {
00134   string s;
00135     
00136   // Opened, lets open the thread
00137   giveinfo();
00138   InterlockedExchange (&thread_com, W32MO_THREAD_COM_INIT);
00139   
00140   // Get Win32 Midi Device num
00141   config->value("config/audio/midi/win32_device", dev_num, -1);
00142 
00143   giveinfo();
00144   thread_handle = (HANDLE*) CreateThread (NULL, 0, thread_start, this, 0, &thread_id);
00145   
00146   giveinfo();
00147   while (thread_com == W32MO_THREAD_COM_INIT) Sleep (1);
00148 
00149   // Set Win32 Midi Device num
00150   config->set("config/audio/midi/win32_device", dev_num, true);
00151   
00152   giveinfo();
00153   if (thread_com == W32MO_THREAD_COM_INIT_FAILED) cerr << "Failure to initialize midi playing thread" << endl;
00154   giveinfo();
00155 }
00156 
00157 DWORD __stdcall Windows_MidiOut::thread_start(void *data)
00158 {
00159   giveinfo();
00160   Windows_MidiOut *ptr=static_cast<Windows_MidiOut *>(data);
00161   giveinfo();
00162   return ptr->thread_main();
00163 }
00164 
00165 DWORD Windows_MidiOut::thread_main()
00166 {
00167   int i;
00168   thread_data = NULL;
00169   giveinfo();
00170   InterlockedExchange (&playing, false);
00171   InterlockedExchange (&s_playing, false);
00172 
00173   giveinfo();
00174 
00175   // List all the midi devices.
00176   MIDIOUTCAPS caps;
00177   signed long dev_count = (signed long) midiOutGetNumDevs(); 
00178   std::cout << dev_count << " Midi Devices Detected" << endl;
00179   std::cout << "Listing midi devices:" << endl;
00180 
00181   for (i = -1; i < dev_count; i++)
00182   {
00183     midiOutGetDevCaps ((UINT) i, &caps, sizeof(caps));
00184     std::cout << i << ": " << caps.szPname << endl;
00185   }
00186 
00187   if (dev_num < -1 || dev_num >= dev_count)
00188   {
00189     std::cerr << "Warning Midi device in config is out of range." << endl;
00190     dev_num = -1;
00191   }
00192   midiOutGetDevCaps ((UINT) dev_num, &caps, sizeof(caps));
00193   std::cout << "Using device " << dev_num << ": "<< caps.szPname << endl;
00194 
00195   UINT mmsys_err = midiOutOpen (&midi_port, dev_num, 0, 0, 0);
00196 
00197   giveinfo();
00198   if (mmsys_err != MMSYSERR_NOERROR)
00199   {
00200     TCHAR buf[512];
00201 
00202     giveinfo();
00203     mciGetErrorString(mmsys_err, buf, 512);
00204 
00205 #ifdef UNICODE
00206     std::wcerr << TEXT("Unable to open device: ") << buf << endl;
00207 #else
00208     cerr << "Unable to open device: " << buf << endl;
00209 #endif
00210     giveinfo();
00211     InterlockedExchange (&thread_com, W32MO_THREAD_COM_INIT_FAILED);
00212     giveinfo();
00213     return 1;
00214   }
00215   giveinfo();
00216   InterlockedExchange (&is_available, true);
00217   
00218 //  SetThreadPriority (thread_handle, THREAD_PRIORITY_HIGHEST);
00219   giveinfo();
00220   SetThreadPriority (thread_handle, THREAD_PRIORITY_TIME_CRITICAL);
00221   
00222   giveinfo();
00223   InterlockedExchange (&thread_com, W32MO_THREAD_COM_READY);
00224   InterlockedExchange (&sfx_com, W32MO_THREAD_COM_READY);
00225 
00226   giveinfo();
00227   thread_play();
00228   giveinfo();
00229 
00230   giveinfo();
00231   midiOutClose (midi_port);
00232   giveinfo();
00233   InterlockedExchange (&is_available, false);
00234   giveinfo();
00235   return 0;
00236 }
00237 
00238 void Windows_MidiOut::thread_play ()
00239 {
00240   int       repeat = false;
00241   uint32      aim = 0;
00242   sint32      diff = 0;
00243   uint32      last_tick = 0;
00244   XMIDIEventList  *evntlist = NULL;
00245   midi_event    *event = NULL;
00246   NoteStack   notes_on;
00247   midi_event    *note = NULL;
00248 
00249   //
00250   // Xmidi Looping
00251   //
00252 
00253   // The for loop event
00254   midi_event  *loop_event[XMIDI_MAX_FOR_LOOP_COUNT];
00255 
00256   // The amount of times we have left that we can loop
00257   int   loop_count[XMIDI_MAX_FOR_LOOP_COUNT];
00258 
00259   // The level of the loop we are currently in
00260   int   loop_num = -1;    
00261 
00262   giveinfo();
00263 
00264   int       s_track = 0;
00265   uint32      s_aim = 0;
00266   sint32      s_diff = 0;
00267   uint32      s_last_tick = 0;
00268   NoteStack   s_notes_on;
00269   XMIDIEventList  *s_evntlist = NULL;
00270   midi_event    *s_event = NULL;
00271 
00272   giveinfo();
00273 
00274   // Play while there isn't a message waiting
00275   while (1)
00276   {
00277     if (thread_com == W32MO_THREAD_COM_EXIT && !playing && !s_playing) break;
00278     
00279     if (thread_com == W32MO_THREAD_COM_STOP)
00280     {
00281       giveinfo();
00282       InterlockedExchange (&playing, FALSE);
00283       InterlockedExchange (&thread_com, W32MO_THREAD_COM_READY);
00284 
00285       // Handle note off's here
00286       while (note = notes_on.Pop())
00287         midiOutShortMsg (midi_port, note->status + (note->data[0] << 8));
00288 
00289       giveinfo();
00290       // Clean up
00291       for (int i = 0; i < 16; i++) reset_channel (i); 
00292       midiOutReset (midi_port);
00293       giveinfo();
00294       if (evntlist) evntlist->DecerementCounter();
00295       giveinfo();
00296       evntlist = NULL;
00297       event = NULL;
00298       giveinfo();
00299 
00300       // If stop was requested, we are ready to receive another song
00301 
00302       loop_num = -1;
00303 
00304       wmoInitClock ();
00305       last_tick = 0;
00306     }
00307 
00308     // Handle note off's here
00309     while (note = notes_on.PopTime(wmoGetRealTime()))
00310       midiOutShortMsg (midi_port, note->status + (note->data[0] << 8));
00311 
00312     while (note = s_notes_on.PopTime(wmoGetRealTime()))
00313       midiOutShortMsg (midi_port, note->status + (note->data[0] << 8));
00314 
00315     while (event && thread_com != W32MO_THREAD_COM_STOP)
00316     {
00317       aim = (event->time-last_tick)*50;
00318       diff = aim - wmoGetTime ();
00319 
00320       if (diff > 0) break;
00321 
00322       last_tick = event->time;
00323       wmoAddOffset(aim);
00324     
00325         // XMIDI For Loop
00326       if ((event->status >> 4) == MIDI_STATUS_CONTROLLER && event->data[0] == XMIDI_CONTROLLER_FOR_LOOP)
00327       {
00328         if (loop_num < XMIDI_MAX_FOR_LOOP_COUNT) loop_num++;
00329 
00330         loop_count[loop_num] = event->data[1];
00331         loop_event[loop_num] = event;
00332 
00333       } // XMIDI Next/Break
00334       else if ((event->status >> 4) == MIDI_STATUS_CONTROLLER && event->data[0] == XMIDI_CONTROLLER_NEXT_BREAK)
00335       {
00336         if (loop_num != -1)
00337         {
00338           if (event->data[1] < 64)
00339           {
00340             loop_num--;
00341           }
00342         }
00343         event = NULL;
00344 
00345       }  // Not SysEx
00346       else if (event->status < 0xF0)
00347       {
00348         int type = event->status >> 4;
00349 
00350         if ((type != MIDI_STATUS_NOTE_ON || event->data[1]) && type != MIDI_STATUS_NOTE_OFF) {
00351           if (type == MIDI_STATUS_NOTE_ON) {
00352             notes_on.Remove(event);
00353             notes_on.Push (event, event->duration * 50 + wmoGetStart());
00354           }
00355 
00356           midiOutShortMsg (midi_port, event->status + (event->data[0] << 8) + (event->data[1] << 16));
00357         }
00358       }
00359     
00360       if (event) event = event->next;
00361   
00362       if (!event || thread_com != W32MO_THREAD_COM_READY)
00363       {
00364         bool clean = !repeat || (thread_com != W32MO_THREAD_COM_READY) || last_tick == 0;
00365 
00366         if (clean)
00367         {
00368           InterlockedExchange (&playing, FALSE);
00369           if (thread_com == W32MO_THREAD_COM_STOP)
00370             InterlockedExchange (&thread_com, W32MO_THREAD_COM_READY);
00371 
00372           // Handle note off's here
00373           while (note = notes_on.Pop())
00374             midiOutShortMsg (midi_port, note->status + (note->data[0] << 8));
00375 
00376           // Clean up
00377           for (int i = 0; i < 16; i++) reset_channel (i); 
00378           midiOutReset (midi_port);
00379           if (evntlist) evntlist->DecerementCounter();
00380           evntlist = NULL;
00381           event = NULL;
00382 
00383           loop_num = -1;
00384           wmoInitClock ();
00385         }
00386 
00387         last_tick = 0;
00388 
00389         if (evntlist)
00390         {
00391           if (loop_num == -1) event = evntlist->events;
00392           else
00393           {
00394             event = loop_event[loop_num]->next;
00395             last_tick = loop_event[loop_num]->time;
00396 
00397             if (loop_count[loop_num])
00398               if (!--loop_count[loop_num])
00399                 loop_num--;
00400           }
00401         }
00402       }
00403     }
00404 
00405 
00406     // Got issued a music play command
00407     // set up the music playing routine
00408     if (thread_com == W32MO_THREAD_COM_PLAY)
00409     {
00410       // Handle note off's here
00411       while (note = notes_on.Pop())
00412         midiOutShortMsg (midi_port, note->status + (note->data[0] << 8));
00413 
00414       // Manual Reset since I don't trust midiOutReset()
00415       giveinfo();
00416       for (int i = 0; i < 16; i++) reset_channel (i);
00417       midiOutReset (midi_port);
00418 
00419       if (evntlist) evntlist->DecerementCounter();
00420       evntlist = NULL;
00421       event = NULL;
00422       InterlockedExchange (&playing, FALSE);
00423 
00424       // Make sure that the data exists
00425       giveinfo();
00426       while (!thread_data) Sleep(1);
00427       
00428       giveinfo();
00429       evntlist = thread_data->list;
00430       repeat = thread_data->repeat;
00431 
00432       giveinfo();
00433       InterlockedExchange ((LONG*) &thread_data, (LONG) NULL);
00434       giveinfo();
00435       InterlockedExchange (&thread_com, W32MO_THREAD_COM_READY);
00436       
00437       giveinfo();
00438       if (evntlist) event = evntlist->events;
00439       else event = 0;
00440 
00441       giveinfo();
00442       last_tick = 0;
00443       
00444       giveinfo();
00445       wmoInitClock ();
00446   
00447       // Reset XMIDI Looping
00448       loop_num = -1;
00449 
00450       giveinfo();
00451       InterlockedExchange (&playing, true);
00452     }
00453 
00454     if (s_event)
00455     {
00456       s_aim = (s_event->time-s_last_tick)*50;
00457       s_diff = s_aim - wmoGetSFXTime ();
00458     }
00459     else 
00460       s_diff = 1;
00461   
00462     if (s_diff <= 0)
00463     {
00464       s_last_tick = s_event->time;
00465       wmoAddSFXOffset(s_aim);
00466     
00467       // Not SysEx
00468       if ((s_event->status >> 4) != MIDI_STATUS_SYSEX)
00469       {
00470         int type = s_event->status >> 4;
00471 
00472         if ((type != MIDI_STATUS_NOTE_ON || s_event->data[1]) && type != MIDI_STATUS_NOTE_OFF) {
00473           if (type == MIDI_STATUS_NOTE_ON) {
00474             s_notes_on.Remove(s_event);
00475             s_notes_on.Push (s_event, s_event->duration * 50 + wmoGetSFXStart());
00476           }
00477 
00478           midiOutShortMsg (midi_port, s_event->status + (s_event->data[0] << 8) + (s_event->data[1] << 16));
00479         }
00480         s_track |= 1 << (s_event->status & 0xF);
00481       }
00482 
00483       s_event = s_event->next;
00484     }
00485     if (s_evntlist && (!s_event || thread_com == W32MO_THREAD_COM_EXIT || sfx_com != W32MO_THREAD_COM_READY))
00486     {
00487       // Play all the remaining note offs 
00488       while (note = s_notes_on.Pop())
00489         midiOutShortMsg (midi_port, note->status + (note->data[0] << 8));
00490       
00491       // Also reset the played tracks
00492       for (int i = 0; i < 16; i++) if ((s_track >> i)&1) reset_channel (i);
00493 
00494       s_evntlist->DecerementCounter();
00495       s_evntlist = NULL;
00496       s_event = NULL;
00497       InterlockedExchange (&s_playing, false);
00498       if (sfx_com != W32MO_THREAD_COM_PLAY) InterlockedExchange (&sfx_com, W32MO_THREAD_COM_READY);
00499     }
00500 
00501     // Got issued a sound effect play command
00502     // set up the sound effect playing routine
00503     if (!s_evntlist && sfx_com == W32MO_THREAD_COM_PLAY)
00504     {
00505       giveinfo();
00506       cout << "Play sfx command" << endl;
00507 
00508       // Play all the remaining note offs 
00509       while (note = s_notes_on.Pop())
00510         midiOutShortMsg (midi_port, note->status + (note->data[0] << 8));
00511 
00512       // Make sure that the data exists
00513       while (!sfx_data) Sleep(1);
00514       
00515       giveinfo();
00516       s_evntlist = sfx_data->list;
00517 
00518       giveinfo();
00519       InterlockedExchange ((LONG*) &sfx_data, (LONG) NULL);
00520       InterlockedExchange (&sfx_com, W32MO_THREAD_COM_READY);
00521       giveinfo();
00522       
00523       if (s_evntlist) s_event = s_evntlist->events;
00524       else s_event = 0;
00525 
00526       giveinfo();
00527   
00528       s_last_tick = 0;
00529       
00530       giveinfo();
00531       wmoInitSFXClock ();
00532 
00533       giveinfo();
00534       InterlockedExchange (&s_playing, true);
00535       
00536       giveinfo();
00537       // Reset thet track counter
00538       s_track = 0;
00539     }
00540 
00541     if (event)
00542     {
00543       aim = (event->time-last_tick)*50;
00544       diff = aim - wmoGetTime ();
00545     }
00546     else 
00547       diff = 6;
00548 
00549     if (s_event)
00550     {
00551       s_aim = (s_event->time-s_last_tick)*50;
00552       s_diff = s_aim - wmoGetSFXTime ();
00553     }
00554     else 
00555       s_diff = 6;
00556 
00557     //std::cout << sfx_com << endl;
00558 
00559     if (diff > 5 && s_diff > 5) Sleep (1);
00560   }
00561   // Handle note off's here
00562   while (note = notes_on.Pop())
00563     midiOutShortMsg (midi_port, note->status + (note->data[0] << 8));
00564 
00565   // Play all the remaining note offs 
00566   while (note = s_notes_on.PopTime(wmoGetRealTime()))
00567     midiOutShortMsg (midi_port, note->status + (note->data[0] << 8));
00568 
00569   if (evntlist) evntlist->DecerementCounter();
00570   evntlist = NULL;
00571   if (s_evntlist) s_evntlist->DecerementCounter();
00572   s_evntlist = NULL;
00573   for (int i = 0; i < 16; i++) reset_channel (i); 
00574   midiOutReset (midi_port);
00575 }
00576 
00577 void Windows_MidiOut::reset_channel (int i)
00578 {
00579   // Pitch Wheel
00580   midiOutShortMsg (midi_port, i | (MIDI_STATUS_PITCH_WHEEL << 4) | (combined_value << 8));
00581   
00582   // All controllers off
00583   midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (121 << 8));
00584 
00585   // All notes off
00586   midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (123 << 8));
00587 
00588   // Bank Select
00589   midiOutShortMsg (midi_port, i | (MIDI_STATUS_PROG_CHANGE << 4) | (0 << 8));
00590   midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (0 << 8));
00591   midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (32 << 8));
00592 
00593   // Modulation Wheel
00594   midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (1 << 8) | (coarse_value << 16));
00595   midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (33 << 8) | (fine_value << 16));
00596   
00597   // Volume
00598   midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (7 << 8) | (coarse_value << 16));
00599   midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (39 << 8) | (fine_value << 16));
00600 
00601   // Pan
00602   midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (8 << 8) | (coarse_value << 16));
00603   midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (40 << 8) | (fine_value << 16));
00604 
00605   // Balance
00606   midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (10 << 8) | (coarse_value << 16));
00607   midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (42 << 8) | (fine_value << 16));
00608 
00609   // Effects (Reverb)
00610   midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (91 << 8));
00611 
00612   // Chorus
00613   midiOutShortMsg (midi_port, i | (MIDI_STATUS_CONTROLLER << 4) | (93 << 8));
00614 }
00615 
00616 void Windows_MidiOut::start_track (XMIDIEventList *xmidi, bool repeat)
00617 {
00618   giveinfo();
00619   if (!is_available)
00620     init_device();
00621 
00622   giveinfo();
00623   if (!is_available)
00624     return;
00625     
00626   giveinfo();
00627   while (thread_com != W32MO_THREAD_COM_READY) Sleep (1);
00628   
00629   giveinfo();
00630   xmidi->IncerementCounter();
00631   data.list = xmidi;
00632   data.repeat = repeat;
00633 //  xmidi->Write("winmidi_out.mid");
00634   
00635   giveinfo();
00636   InterlockedExchange ((LONG*) &thread_data, (LONG) &data);
00637   giveinfo();
00638   InterlockedExchange (&thread_com, W32MO_THREAD_COM_PLAY);
00639   giveinfo();
00640 }
00641 
00642 void Windows_MidiOut::start_sfx(XMIDIEventList *xmidi)
00643 {
00644   giveinfo();
00645   if (!is_available)
00646     init_device();
00647 
00648   giveinfo();
00649   if (!is_available)
00650     return;
00651   
00652   giveinfo();
00653   while (sfx_com != W32MO_THREAD_COM_READY) Sleep (1);
00654 
00655   giveinfo();
00656   xmidi->IncerementCounter();
00657   sdata.list = xmidi;
00658   sdata.repeat;
00659   
00660   giveinfo();
00661   InterlockedExchange ((LONG*) &sfx_data, (LONG) &sdata);
00662   giveinfo();
00663   InterlockedExchange (&sfx_com, W32MO_THREAD_COM_PLAY);
00664   giveinfo();
00665 }
00666 
00667 
00668 void Windows_MidiOut::stop_track(void)
00669 {
00670   giveinfo();
00671   if (!is_available)
00672     return;
00673 
00674   giveinfo();
00675   if (!playing) return;
00676 
00677   giveinfo();
00678   while (thread_com != W32MO_THREAD_COM_READY) Sleep (1);
00679   giveinfo();
00680   InterlockedExchange (&thread_com, W32MO_THREAD_COM_STOP);
00681   giveinfo();
00682   while (thread_com != W32MO_THREAD_COM_READY) Sleep (1);
00683   giveinfo();
00684 }
00685 
00686 void Windows_MidiOut::stop_sfx(void)
00687 {
00688   giveinfo();
00689   if (!is_available)
00690     return;
00691 
00692   giveinfo();
00693   if (!s_playing) return;
00694 
00695   giveinfo();
00696   while (sfx_com != W32MO_THREAD_COM_READY) Sleep (1);
00697   giveinfo();
00698   InterlockedExchange (&sfx_com, W32MO_THREAD_COM_STOP);
00699   giveinfo();
00700 }
00701 
00702 bool Windows_MidiOut::is_playing(void)
00703 {
00704   giveinfo();
00705   return playing!=0;
00706 }
00707 
00708 const char *Windows_MidiOut::copyright(void)
00709 {
00710   giveinfo();
00711   return "Internal Win32 Midiout Midi Player for Exult and Pentagram.";
00712 }
00713 
00714 
00715 #endif

Generated on Mon Jul 9 14:42:42 2007 for ExultEngine by  doxygen 1.5.1