~s-cecilio/lenmus/v5.3

« back to all changes in this revision

Viewing changes to packages/wxMidi/src/wxMidi.cpp

  • Committer: cecilios
  • Date: 2012-09-11 16:59:18 UTC
  • Revision ID: svn-v4:2587a929-2f0e-0410-ae78-fe6f687d5efe:branches/TRY-5.0:730
Paths: fixed problem with installation folders. Fixed Chinese ISO language code

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//=====================================================================================
 
2
// wxMidi: A MIDI interface based on PortMidi, the Portable Real-Time MIDI Library
 
3
// --------------------------------------------------------------------------------
 
4
//
 
5
// Author:      Cecilio Salmeron
 
6
// Copyright:   (c) 2005-2007 Cecilio Salmeron
 
7
// Licence:     wxWidgets licence, version 3.1 or later at your choice.
 
8
//=====================================================================================
 
9
#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
 
10
#pragma implementation "wxMidi.h"
 
11
#endif
 
12
 
 
13
// For compilers that support precompilation, includes "wx.h".
 
14
#include "wx/wxprec.h"
 
15
 
 
16
#ifdef __BORLANDC__
 
17
#pragma hdrstop
 
18
#endif
 
19
 
 
20
#include "wxMidi.h"
 
21
 
 
22
/*
 
23
        To do, when a new version of portmidi:
 
24
        1. Review error messages (method GetErrorText(), copied and adapted from pormidi.c)
 
25
 
 
26
 
 
27
*/
 
28
 
 
29
// Private global functions
 
30
//---------------------------------------------------------------------------------
 
31
wxMidiTimestamp wxMidiGetTime() { return Pt_Time(); }
 
32
 
 
33
//Define the new command event to inform that MIDI input data is available
 
34
DEFINE_EVENT_TYPE(wxEVT_MIDI_INPUT)
 
35
 
 
36
//================================================================================
 
37
// Implementation of classes wxMidiPmEvent, wxMidiShortEvent and wxMidiSysExEvent
 
38
//================================================================================
 
39
 
 
40
#define SYSEX_CHUNK_SIZE                4                                                               // PmEvent size
 
41
#define SYSEX_BUFFER_SIZE               (SYSEX_CHUNK_SIZE * 1024)               // alloc in 4K chunks
 
42
 
 
43
wxMidiSysExMessage::wxMidiSysExMessage()
 
44
                : wxMidiMessage()
 
45
{
 
46
        m_type = wxMIDI_SYSEX_MSG;
 
47
        m_pMessage = (wxByte*) NULL;
 
48
        m_nSize = 0;
 
49
        m_nError =      wxMIDI_NO_ERROR;
 
50
        m_timestamp = 0;
 
51
}
 
52
 
 
53
 
 
54
wxMidiSysExMessage::wxMidiSysExMessage(wxByte* msg, wxMidiTimestamp timestamp)
 
55
                : wxMidiMessage()
 
56
{
 
57
        m_type = wxMIDI_SYSEX_MSG;
 
58
        m_pMessage = (wxByte*) NULL;
 
59
        m_nSize = 0;
 
60
        m_nError =      wxMIDI_NO_ERROR;
 
61
        m_timestamp = timestamp;
 
62
 
 
63
        //verify start of message
 
64
        if (*msg != 0xF0) {
 
65
                m_nError = wxMIDI_ERROR_BadSysExMsg_Start;
 
66
                return;
 
67
        }
 
68
 
 
69
        //determine size of message
 
70
        wxByte* pData = msg;
 
71
        for (; m_nSize < 10000 && *pData != 0xF7; pData++) {
 
72
                m_nSize++;
 
73
        }
 
74
        if (m_nSize == 10000) {
 
75
                m_nError = wxMIDI_ERROR_BadSysExMsg_Length;
 
76
                return;
 
77
        }
 
78
 
 
79
        // allocate the buffer
 
80
        m_nSize++;              //include the end of sysex byte 0xF7
 
81
        m_pMessage = new wxByte[m_nSize];
 
82
 
 
83
        // copy the data
 
84
        memcpy(m_pMessage, msg, m_nSize);
 
85
 
 
86
}
 
87
 
 
88
wxMidiSysExMessage::~wxMidiSysExMessage()
 
89
{
 
90
        if (m_pMessage) {
 
91
                delete [] m_pMessage;
 
92
                m_pMessage = (wxByte*) NULL;
 
93
        }
 
94
}
 
95
 
 
96
//================================================================================
 
97
// Implementation of class wxMidiDevice
 
98
//================================================================================
 
99
 
 
100
 
 
101
wxMidiDevice::wxMidiDevice(wxMidiDeviceID nDevice)
 
102
{
 
103
        m_nDevice = nDevice;
 
104
        int devices = Pm_CountDevices();
 
105
        if (m_nDevice > devices-1) m_nDevice = 0;
 
106
        m_pInfo = Pm_GetDeviceInfo(m_nDevice);
 
107
        m_stream = (PortMidiStream*)NULL;
 
108
}
 
109
 
 
110
wxMidiDevice::~wxMidiDevice()
 
111
{
 
112
        /*
 
113
    WARNING: Pm_GetDeviceInfo() returns a pointer to a PmDeviceInfo structure
 
114
    referring to the device specified by id. The returned structure is owned by
 
115
        the PortMidi implementation and must not be manipulated or freed.
 
116
        */
 
117
        //if (m_pInfo) delete m_pInfo;
 
118
}
 
119
 
 
120
const wxString wxMidiDevice::DeviceName()
 
121
{
 
122
        if (m_pInfo) {
 
123
#if defined(_UNICODE) || defined(UNICODE)
 
124
                return wxString(m_pInfo->name, wxConvUTF8);
 
125
#else
 
126
                return m_pInfo->name;
 
127
#endif
 
128
        }
 
129
        else {
 
130
                wxString sMsg = _("Error: Device not properly created");
 
131
                return sMsg;
 
132
        }
 
133
}
 
134
 
 
135
const wxString wxMidiDevice::InterfaceUsed()
 
136
{
 
137
        if (m_pInfo) {
 
138
#if defined(_UNICODE) || defined(UNICODE)
 
139
                return wxString(m_pInfo->interf, wxConvUTF8);
 
140
#else
 
141
                return m_pInfo->interf;
 
142
#endif
 
143
        }
 
144
        else {
 
145
                wxString sMsg = _("Error: Device not properly created");
 
146
                return sMsg;
 
147
        }
 
148
}
 
149
 
 
150
bool wxMidiDevice::IsInputPort()
 
151
{
 
152
        if (m_pInfo)
 
153
                return (m_pInfo->input != 0);
 
154
        else
 
155
                return false;
 
156
}
 
157
 
 
158
bool wxMidiDevice::IsOutputPort()
 
159
{
 
160
        if (m_pInfo)
 
161
                return (m_pInfo->output != 0);
 
162
        else
 
163
                return false;
 
164
}
 
165
 
 
166
 
 
167
//================================================================================
 
168
// Class wxMidiOutDevice implementation
 
169
//================================================================================
 
170
 
 
171
wxMidiError wxMidiOutDevice::Open(long latency, void *DriverInfo)
 
172
{
 
173
        // bufferSize = 0    How to set up an optimum value?
 
174
        return (wxMidiError)Pm_OpenOutput(&m_stream, m_nDevice, DriverInfo,
 
175
                                                                          0, NULL, NULL, latency );
 
176
}
 
177
 
 
178
wxMidiError wxMidiOutDevice::Write(wxMidiShortMessage* pMsg)
 
179
{
 
180
        return (wxMidiError)Pm_Write(m_stream, pMsg->GetBuffer(), 1);
 
181
}
 
182
 
 
183
wxMidiError wxMidiOutDevice::Write(wxMidiSysExMessage* pMsg)
 
184
{
 
185
        wxMidiError nError = pMsg->Error();
 
186
        if (nError != wxMIDI_NO_ERROR)
 
187
                return nError;
 
188
        else
 
189
                return (wxMidiError)Pm_WriteSysEx(m_stream,
 
190
                                                                          pMsg->GetTimestamp(),
 
191
                                                                          (unsigned char *)pMsg->GetMessage() );
 
192
}
 
193
 
 
194
wxMidiError wxMidiOutDevice::Write(wxByte* msg, wxMidiTimestamp when)
 
195
{
 
196
        return (wxMidiError)Pm_WriteSysEx(m_stream,
 
197
                                                                          when,
 
198
                                                                          (unsigned char *)msg );
 
199
}
 
200
 
 
201
wxMidiError     wxMidiOutDevice::NoteOff(int channel, int note, int velocity)
 
202
{
 
203
        //0x80?0x8F             Note off
 
204
        wxMidiShortMessage msg(0x80+channel, note, velocity);
 
205
        return Write(&msg);
 
206
}
 
207
 
 
208
wxMidiError     wxMidiOutDevice::NoteOn(int channel, int note, int velocity)
 
209
{
 
210
    //0x90?0x9F         Note on
 
211
        wxMidiShortMessage msg(0x90+channel, note, velocity);
 
212
        return Write(&msg);
 
213
}
 
214
 
 
215
wxMidiError     wxMidiOutDevice::ProgramChange(int channel, int instrument)
 
216
{
 
217
    //0xC0?0xCF         Program change
 
218
        wxMidiShortMessage msg(0xC0+channel, instrument, 0);
 
219
        return Write(&msg);
 
220
}
 
221
 
 
222
wxMidiError wxMidiOutDevice::AllSoundsOff()
 
223
{
 
224
        wxMidiPmEvent buffer[32];
 
225
        wxMidiTimestamp now = ::wxMidiGetTime();
 
226
        int channel, i;
 
227
        for (i=0, channel=0; channel < 16; channel++) {
 
228
                buffer[i].message = Pm_Message(0xB0+channel, 0x78, 0);
 
229
                buffer[i].timestamp = now;
 
230
                i++;
 
231
                buffer[i].message = Pm_Message(0xB0+channel, 0x7B, 0);
 
232
                buffer[i].timestamp = now;
 
233
                i++;
 
234
        }
 
235
        return (wxMidiError)Pm_Write(m_stream, buffer, 32);
 
236
}
 
237
 
 
238
 
 
239
//================================================================================
 
240
// Class wxMidiInDevice implementation
 
241
//================================================================================
 
242
 
 
243
wxMidiInDevice::wxMidiInDevice(wxMidiDeviceID nDevice)
 
244
        : wxMidiDevice(nDevice)
 
245
{
 
246
        m_pThread = (wxMidiThread*)NULL;
 
247
        m_SysexBuffer = (wxByte*)NULL;
 
248
        m_fReadingSysex = false;
 
249
        m_fEventPending = false;
 
250
}
 
251
 
 
252
wxMidiInDevice::~wxMidiInDevice()
 
253
{
 
254
        if (m_pThread) {
 
255
                StopListening();
 
256
        }
 
257
        if (m_SysexBuffer) delete [] m_SysexBuffer;
 
258
}
 
259
 
 
260
wxMidiError wxMidiInDevice::Open(void *DriverInfo)
 
261
{
 
262
        // bufferSize = 50    How to set up an optimum value?
 
263
        return (wxMidiError)Pm_OpenInput(&m_stream, m_nDevice, DriverInfo,
 
264
                                                                         50, NULL, NULL);
 
265
}
 
266
 
 
267
wxMidiError wxMidiInDevice::Read(wxMidiPmEvent *buffer, long* length )
 
268
{
 
269
        /*
 
270
        If no error, the real number of buffers read is returned in "length" and
 
271
        value PmNoError is returned.
 
272
        In case of error, the error type is returned.
 
273
        */
 
274
 
 
275
        int nErr = (int) Pm_Read(m_stream, buffer, *length);
 
276
        /* Pm_Read() retrieves midi data into a buffer, and returns the number
 
277
    of events read. Result is a non-negative number unless an error occurs,
 
278
    in which case a wxMidiError value will be returned. */
 
279
        if (nErr < 0)
 
280
                //error
 
281
                return (wxMidiError)nErr;
 
282
        else {
 
283
                *length = (long)nErr;
 
284
                return wxMIDI_NO_ERROR;
 
285
        }
 
286
 
 
287
}
 
288
 
 
289
wxMidiMessage* wxMidiInDevice::Read(wxMidiError* pError)
 
290
{
 
291
        /*
 
292
        According to pormidi documentation, portmidi is allowed to pass real-time MIDI
 
293
        messages embedded within the chunks of a sysex message, and it is up to the client
 
294
        to detect, process, and remove these messages as they arrive.
 
295
 
 
296
        To deal with this, xMidiInDevice will maintain buffers with data not yet delivered.
 
297
        Flag m_fReadingSysex will signal that a sysex message was interrupted by a real-time one
 
298
        Flag m_fEventPending will signal that there is a PmEvent pending to be processed and
 
299
        delivered, as consecuence of a previous truncated sysex message.
 
300
 
 
301
        */
 
302
 
 
303
        // get data from midi stream
 
304
        PmEvent buffer;
 
305
        wxMidiError nError;
 
306
 
 
307
        if (m_fEventPending) {
 
308
                buffer = m_event;
 
309
                m_fEventPending = false;
 
310
        }
 
311
        else {
 
312
                nError = (wxMidiError) Pm_Read( m_stream, &buffer, 1 );
 
313
 
 
314
                // if read was not successful return the error
 
315
                if (nError < wxMIDI_NO_ERROR) {
 
316
                        *pError = nError;
 
317
                        return (wxMidiMessage*)NULL;
 
318
                }
 
319
 
 
320
                // check if something read
 
321
                if (nError == 0) {
 
322
                        *pError = wxMIDI_ERROR_NoDataAvailable;
 
323
                        return (wxMidiMessage*)NULL;
 
324
                }
 
325
        }
 
326
 
 
327
        // check what type of message we are receiving
 
328
        if (m_fReadingSysex || (Pm_MessageStatus( buffer.message ) == 0xF0))
 
329
        {
 
330
                // Start or continuation of a Sysex message. Move data to buffer and
 
331
                // continue reading until end of message
 
332
 
 
333
                //create the message object
 
334
                wxMidiSysExMessage* pSysExMsg = new wxMidiSysExMessage();
 
335
 
 
336
                if (!m_fReadingSysex)
 
337
                {
 
338
                        //store timestamp
 
339
                        m_timestamp = buffer.timestamp;
 
340
 
 
341
                        // alloc a new buffer
 
342
                        m_SizeOfSysexBuffer = SYSEX_BUFFER_SIZE;
 
343
                        m_SysexBuffer = new wxByte[ m_SizeOfSysexBuffer ];
 
344
                        m_CurSysexDataPtr = m_SysexBuffer;
 
345
 
 
346
                        m_fReadingSysex = true;
 
347
                }
 
348
 
 
349
                //move data to buffer and continue reading until end of sysex message
 
350
                bool fEndSysex = MoveDataToSysExBuffer(buffer.message);
 
351
 
 
352
                while(!fEndSysex) {
 
353
                        nError = (wxMidiError) Pm_Read( m_stream, &buffer, 1 );
 
354
                        if (nError < wxMIDI_NO_ERROR) {
 
355
                                *pError = nError;
 
356
                                delete pSysExMsg;
 
357
                                delete [] m_SysexBuffer;
 
358
                                m_SysexBuffer = (wxByte*)NULL;
 
359
                                m_fReadingSysex = false;
 
360
                                return (wxMidiMessage*)NULL;
 
361
                        }
 
362
 
 
363
                        // check if it is a real-time message inserted into the sysex chunks stream
 
364
                        if (Pm_MessageStatus( buffer.message ) == 0xF8) {
 
365
                                //it is a real time message. Deliver it inmediately and save sysex buffer
 
366
                                *pError = wxMIDI_NO_ERROR;
 
367
                                wxMidiShortMessage* pShortMsg = new wxMidiShortMessage(
 
368
                                                                                                                Pm_MessageStatus( buffer.message ),
 
369
                                                                                                                0, 0 );
 
370
                                pShortMsg->SetTimestamp( buffer.timestamp );
 
371
                                delete pSysExMsg;
 
372
                                return pShortMsg;
 
373
                        }
 
374
 
 
375
                        /*
 
376
                        When receiving sysex messages, if you get a non-real-time status byte
 
377
                        but there was no EOX byte, it means the sysex message was somehow truncated.
 
378
                        This is not     considered an error; e.g., a missing EOX can result from the user
 
379
                        disconnecting a MIDI cable during sysex transmission.
 
380
                        */
 
381
 
 
382
                        // lets check if there is a status byte different from end-of-sysex
 
383
                        if (Pm_MessageStatus( buffer.message ) != 0xF7 &&
 
384
                                Pm_MessageStatus( buffer.message ) & 0x80 )
 
385
                        {
 
386
                                //The systex message is somehow truncated. Return the sysex message
 
387
                                // and store the new message received
 
388
 
 
389
                                // save the PmEvent
 
390
                                m_fEventPending = true;
 
391
                                m_event.message = buffer.message;
 
392
                                m_event.timestamp = buffer.timestamp;
 
393
 
 
394
                                //terminate the current sysex message
 
395
                                fEndSysex = true;
 
396
                        }
 
397
                        else {
 
398
                                // it is a chunck of the sysex message. Move data to the sysex buffer
 
399
                                fEndSysex = MoveDataToSysExBuffer(buffer.message);
 
400
                        }
 
401
                }
 
402
 
 
403
                //prepare the sysex message to return it
 
404
                pSysExMsg->SetTimestamp( m_timestamp );
 
405
                pSysExMsg->SetBuffer( m_SysexBuffer );
 
406
                pSysExMsg->SetLength( m_CurSysexDataPtr - m_SysexBuffer );
 
407
                *pError = wxMIDI_NO_ERROR;
 
408
 
 
409
                //reset the wxMidiInDevice buffer
 
410
                m_SysexBuffer = (wxByte*)NULL;
 
411
                m_CurSysexDataPtr = (wxByte*)NULL;
 
412
                m_fReadingSysex = false;
 
413
 
 
414
                return pSysExMsg;
 
415
        }
 
416
        else
 
417
        {
 
418
                //it is not a sysex message
 
419
                *pError = wxMIDI_NO_ERROR;
 
420
                wxMidiShortMessage* pShortMsg = new wxMidiShortMessage(
 
421
                                                                                                Pm_MessageStatus( buffer.message ),
 
422
                                                                                                Pm_MessageData1( buffer.message ),
 
423
                                                                                                Pm_MessageData2( buffer.message ) );
 
424
                pShortMsg->SetTimestamp( buffer.timestamp );
 
425
                return pShortMsg;
 
426
        }
 
427
 
 
428
}
 
429
 
 
430
bool wxMidiInDevice::MoveDataToSysExBuffer(PmMessage message)
 
431
{
 
432
        /*
 
433
        Moves the chunk received to the sysex buffer, allocating a greater buffer
 
434
        if necessary.
 
435
        Returns true if with this chunk the sysex message is ended, false otherwise
 
436
        */
 
437
 
 
438
        // if we are at the end of the buffer
 
439
        if( m_CurSysexDataPtr > (m_SysexBuffer + m_SizeOfSysexBuffer - SYSEX_CHUNK_SIZE) )
 
440
        {
 
441
                // keep previous size for usage
 
442
                long oldSize = m_SizeOfSysexBuffer;
 
443
 
 
444
                // increment size
 
445
                m_SizeOfSysexBuffer += SYSEX_BUFFER_SIZE;
 
446
 
 
447
                // allocate the new buffer
 
448
                wxByte* newSysexBuffer = new wxByte[ m_SizeOfSysexBuffer ];
 
449
 
 
450
                //wxLogMessage(wxString::Format(
 
451
                //      _T("Increasing buffer size from %d to %d"), oldSize, m_SizeOfSysexBuffer ));
 
452
 
 
453
                // move the data from old buffer
 
454
                memcpy( newSysexBuffer, m_SysexBuffer, oldSize );
 
455
 
 
456
                // delete the old buffer
 
457
                delete [] m_SysexBuffer;
 
458
 
 
459
                // point to the new buffer
 
460
                m_SysexBuffer = newSysexBuffer;
 
461
 
 
462
                // set the write data pointer
 
463
                m_CurSysexDataPtr = m_SysexBuffer + oldSize;
 
464
        }
 
465
 
 
466
        // move data to the buffer. See portmidi/pm_test/sysex.c function receive_sysex()
 
467
        int shift = 0;
 
468
        int data = 0;
 
469
        for (shift = 0; shift < 32 && (data != 0xF7); shift += 8)
 
470
        {
 
471
                data = (message >> shift) & 0xFF;
 
472
                *m_CurSysexDataPtr = data;
 
473
                ++m_CurSysexDataPtr;
 
474
 
 
475
                        /* portmidi:
 
476
                        When receiving sysex messages, the sysex message is terminated
 
477
                        by either an EOX status byte (anywhere in the 4 byte messages) or
 
478
                        by a non-real-time status byte in the low order byte of the message.
 
479
                        If you get a non-real-time status byte but there was no EOX byte, it
 
480
                        means the sysex message was somehow truncated. This is not
 
481
                        considered an error; e.g., a missing EOX can result from the user
 
482
                        disconnecting a MIDI cable during sysex transmission.
 
483
                        */
 
484
 
 
485
        // if this is a status byte that is not EOX, the sysex
 
486
        // message is incomplete and there is no more sysex data
 
487
                //
 
488
                // WARNING: Is this true? Shouldn't portmidi send the status byte
 
489
                // in a new PmEvent? See portmidi/pm_test/sysex.c function receive_sysex()
 
490
                //
 
491
                // TODO: if we break without doing anything else, the status byte and
 
492
                // remaining bytes will be lost !!!
 
493
        if (data & 0x80 && data != 0xF0 && data != 0xF7) break;
 
494
        }
 
495
 
 
496
        return (data & 0x80 && data != 0xF0);
 
497
 
 
498
}
 
499
 
 
500
void wxMidiInDevice::Flush()
 
501
{
 
502
    // empty the buffer
 
503
        wxMidiPmEvent buffer[1];
 
504
        long nNumEvents;
 
505
    while (Poll()) {
 
506
                nNumEvents = 1;                 //initialize with buffer size before calling Read
 
507
        Read(buffer, &nNumEvents);
 
508
    }
 
509
 
 
510
}
 
511
 
 
512
wxMidiError wxMidiInDevice::StartListening(wxWindow* pWindow, unsigned long nPollingRate)
 
513
{
 
514
 
 
515
        if (m_pThread) return wxMIDI_ERROR_AlreadyListening;
 
516
 
 
517
    //Create a new thread. The thread object is created in the suspended state
 
518
        m_pThread = new wxMidiThread(this, pWindow, nPollingRate);
 
519
        if ( m_pThread->Create() != wxTHREAD_NO_ERROR )
 
520
    {
 
521
        return wxMIDI_ERROR_CreateThread;               //Can't create thread!
 
522
    }
 
523
 
 
524
    //wxCriticalSectionLocker enter(wxGetApp().m_critsect);
 
525
 
 
526
        //Start the thread execution
 
527
    if (m_pThread->Run() != wxTHREAD_NO_ERROR )
 
528
    {
 
529
        return wxMIDI_ERROR_StartThread;                //Can't start thread!
 
530
    }
 
531
 
 
532
        return wxMIDI_NO_ERROR;
 
533
}
 
534
 
 
535
wxMidiError wxMidiInDevice::StopListening()
 
536
{
 
537
        //stop the thread and wait for its termination
 
538
        m_pThread->Delete();
 
539
        delete m_pThread;
 
540
        m_pThread = (wxMidiThread*)NULL;
 
541
        return wxMIDI_NO_ERROR;
 
542
}
 
543
 
 
544
//================================================================================
 
545
// Class wxMidiThread implementation
 
546
//================================================================================
 
547
 
 
548
// In MSWin32 all threads are joinable. So for platform independence I will
 
549
// always use joinable threads
 
550
wxMidiThread::wxMidiThread(wxMidiInDevice* pDev, wxWindow* pWindow, unsigned long milliseconds)
 
551
        : wxThread(wxTHREAD_JOINABLE)
 
552
{
 
553
        m_pDev = pDev;
 
554
        m_pWindow = pWindow;
 
555
        m_nMilliseconds = milliseconds;
 
556
}
 
557
 
 
558
wxMidiThread::~wxMidiThread()
 
559
{
 
560
}
 
561
 
 
562
void* wxMidiThread::Entry()
 
563
{
 
564
    while(true)
 
565
        {
 
566
        // check if the thread was asked to exit and do it
 
567
        if (TestDestroy()) break;
 
568
 
 
569
                // check if Midi data is available
 
570
                if ( m_pDev->Poll() ) {
 
571
                        // Data available. Create a Midi event
 
572
                        wxCommandEvent event( wxEVT_MIDI_INPUT );
 
573
                        ::wxPostEvent( m_pWindow, event );
 
574
                        //m_pWindow->GetEventHandler()->AddPendingEvent(event); // Add it to the queue
 
575
                }
 
576
 
 
577
        // pause the thread execution during polling rate interval
 
578
        wxThread::Sleep(m_nMilliseconds);
 
579
    }
 
580
 
 
581
    return NULL;
 
582
}
 
583
 
 
584
 
 
585
 
 
586
//================================================================================
 
587
// Class wxMidiSystem implementation
 
588
//
 
589
//      Acording to documentation Pm_Initialize and Pm_Terminate return a error code, but
 
590
//      looking at the source code they always return pmNoError. So it is useless to
 
591
//      try to preserve the return code by forcing the user to explicitly call
 
592
//      these methods. It is easier to initialize and terminate in
 
593
//      the constructor and destructor, respectively
 
594
//================================================================================
 
595
 
 
596
wxMidiSystem* wxMidiSystem::m_pInstance = (wxMidiSystem*)NULL;
 
597
 
 
598
wxMidiSystem::~wxMidiSystem()
 
599
{
 
600
        Terminate();
 
601
        wxMidiDatabaseGM* pGM = wxMidiDatabaseGM::GetInstance();
 
602
        delete pGM;
 
603
}
 
604
 
 
605
wxMidiError wxMidiSystem::Initialize()
 
606
{
 
607
        Pt_Start(1, 0, 0);                                              // start the timer
 
608
        return (wxMidiError)Pm_Initialize();    // initialize portmidi package
 
609
}
 
610
 
 
611
wxMidiError wxMidiSystem::Terminate()
 
612
{
 
613
        Pt_Stop();                              //stop the timer
 
614
        return (wxMidiError)Pm_Terminate();
 
615
}
 
616
 
 
617
const wxString wxMidiSystem::GetErrorText( wxMidiError errnum )
 
618
{
 
619
    wxString sError;
 
620
    switch(errnum)
 
621
    {
 
622
    case wxMIDI_NO_ERROR:
 
623
                sError = _T("wxMidi: 'No error'");
 
624
                return sError;
 
625
    case wxMIDI_ERROR_HostError:
 
626
        sError = _("PortMidi: `Host error'");
 
627
                return sError;
 
628
    case wxMIDI_ERROR_InvalidDeviceId:
 
629
                sError = _("PortMidi: `Invalid device ID'");
 
630
                return sError;
 
631
    case wxMIDI_ERROR_InsufficientMemory:
 
632
        sError = _("PortMidi: `Insufficient memory'");
 
633
                return sError;
 
634
    case wxMIDI_ERROR_BufferTooSmall:
 
635
        sError = _("PortMidi: 'Buffer too small'");
 
636
                return sError;
 
637
    case wxMIDI_ERROR_BadPtr:
 
638
        sError = _("PortMidi: `Bad pointer'");
 
639
                return sError;
 
640
    case wxMIDI_ERROR_InternalError:
 
641
        sError = _("PortMidi: 'Internal PortMidi Error'");
 
642
                return sError;
 
643
    case wxMIDI_ERROR_BufferOverflow:
 
644
        sError = _("PortMidi: 'Buffer overflow'");
 
645
                return sError;
 
646
    case wxMIDI_ERROR_BadData:
 
647
                sError = _("PortMidi: 'Invalid MIDI message Data'");
 
648
                return sError;
 
649
        case wxMIDI_ERROR_BufferMaxSize:
 
650
                sError = _("PortMidi: 'Buffer is already as large as it can be'");
 
651
                return sError;
 
652
 
 
653
        // Additional error messages for wxMidi
 
654
        case wxMIDI_ERROR_AlreadyListening:
 
655
        sError = _("wxMidi: 'Already lisening!'");
 
656
                return sError;
 
657
        case wxMIDI_ERROR_CreateThread:
 
658
        sError = _("wxMidi: 'Error while creating the thread object'");
 
659
                return sError;
 
660
        case wxMIDI_ERROR_StartThread:
 
661
        sError = _("wxMidi: 'Error while starting the thread execution'");
 
662
                return sError;
 
663
        case wxMIDI_ERROR_BadSysExMsg_Start:
 
664
                sError = _("wxMidi. 'Bad sysex msg: It does not start with 0xF0'");
 
665
                return sError;
 
666
        case wxMIDI_ERROR_BadSysExMsg_Length:
 
667
                sError = _("wxMidi. 'Bad sysex msg: Length greater than 10000 or no final byte 0xF7'");
 
668
                return sError;
 
669
        case wxMIDI_ERROR_NoDataAvailable:
 
670
                sError = _("wxMidi. 'There are no MIDI messages pending to be read'");
 
671
                return sError;
 
672
 
 
673
        default:
 
674
        sError = _("wxMidi: 'Illegal error number'");
 
675
                return sError;
 
676
   }
 
677
}
 
678
 
 
679
 
 
680
wxString wxMidiSystem::GetHostErrorText()
 
681
{
 
682
        //TODO: review this
 
683
        char msg[1000];
 
684
        Pm_GetHostErrorText(&msg[0], 1000);
 
685
        return wxString( (const wxChar *)&msg[0] );
 
686
}
 
687
 
 
688
wxMidiSystem* wxMidiSystem::GetInstance()
 
689
{
 
690
        if (!m_pInstance) {
 
691
                m_pInstance = new wxMidiSystem();
 
692
                m_pInstance->Initialize();
 
693
        }
 
694
        return m_pInstance;
 
695
}
 
696