root/trunk/libs/hydrogen/src/IO/portmidi_driver.cpp @ 298

Revision 298, 5.8 KB (checked in by smoors, 5 years ago)

ported portmidi_driver.cpp to QString

Line 
1/*
2 * Hydrogen
3 * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
4 *
5 * http://www.hydrogen-music.org
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY, without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20 *
21 */
22
23#include "PortMidiDriver.h"
24
25#include <hydrogen/Preferences.h>
26
27#ifdef WIN32
28#include <windows.h>
29#endif
30
31#ifdef PORTMIDI_SUPPORT
32
33#include <porttime.h>
34#define TIME_PROC ((long (*)(void *)) Pt_Time)
35#define TIME_START Pt_Start(1, 0, 0) /* timer started w/millisecond accuracy */
36
37#include <pthread.h>
38
39namespace H2Core
40{
41
42pthread_t PortMidiDriverThread;
43
44void* PortMidiDriver_thread( void* param )
45{
46        PortMidiDriver *instance = ( PortMidiDriver* )param;
47        _INFOLOG( "PortMidiDriver_thread starting" );
48
49        PmError status;
50        PmError length;
51        PmEvent buffer[1];
52        while ( instance->m_bRunning ) {
53                status = Pm_Poll( instance->m_pMidiIn );
54                if ( status == TRUE ) {
55                        length = Pm_Read( instance->m_pMidiIn, buffer, 1 );
56                        if ( length > 0 ) {
57                                MidiMessage msg;
58
59                                int nEventType = Pm_MessageStatus( buffer[0].message );
60                                if ( ( nEventType >= 128 ) && ( nEventType < 144 ) ) {  // note off
61                                        msg.m_nChannel = nEventType - 128;
62                                        msg.m_type = MidiMessage::NOTE_OFF;
63                                } else if ( ( nEventType >= 144 ) && ( nEventType < 160 ) ) {   // note on
64                                        msg.m_nChannel = nEventType - 144;
65                                        msg.m_type = MidiMessage::NOTE_ON;
66                                } else if ( ( nEventType >= 160 ) && ( nEventType < 176 ) ) {   // Polyphonic Key Pressure (After-touch)
67                                        msg.m_nChannel = nEventType - 160;
68                                        msg.m_type = MidiMessage::POLYPHONIC_KEY_PRESSURE;
69                                } else if ( ( nEventType >= 176 ) && ( nEventType < 192 ) ) {   // Control Change
70                                        msg.m_nChannel = nEventType - 176;
71                                        msg.m_type = MidiMessage::CONTROL_CHANGE;
72                                } else if ( ( nEventType >= 192 ) && ( nEventType < 208 ) ) {   // Program Change
73                                        msg.m_nChannel = nEventType - 192;
74                                        msg.m_type = MidiMessage::PROGRAM_CHANGE;
75                                } else if ( ( nEventType >= 208 ) && ( nEventType < 224 ) ) {   // Channel Pressure (After-touch)
76                                        msg.m_nChannel = nEventType - 208;
77                                        msg.m_type = MidiMessage::CHANNEL_PRESSURE;
78                                } else if ( ( nEventType >= 224 ) && ( nEventType < 240 ) ) {   // Pitch Wheel Change
79                                        msg.m_nChannel = nEventType - 224;
80                                        msg.m_type = MidiMessage::PITCH_WHEEL;
81                                } else if ( ( nEventType >= 240 ) && ( nEventType < 256 ) ) {   // System Exclusive
82                                        msg.m_nChannel = nEventType - 240;
83                                        msg.m_type = MidiMessage::SYSTEM_EXCLUSIVE;
84                                } else {
85                                        _ERRORLOG( "Unhandled midi message type: " + QString::number( nEventType ) );
86                                        _INFOLOG( "MIDI msg: " );
87                                        _INFOLOG( QString::number( buffer[0].timestamp ) );
88                                        _INFOLOG( QString::number( Pm_MessageStatus( buffer[0].message ) ) );
89                                        _INFOLOG( QString::number( Pm_MessageData1( buffer[0].message ) ) );
90                                        _INFOLOG( QString::number( Pm_MessageData2( buffer[0].message ) ) );
91                                }
92
93                                msg.m_nData1 = Pm_MessageData1( buffer[0].message );
94                                msg.m_nData2 = Pm_MessageData2( buffer[0].message );
95
96                                instance->handleMidiMessage( msg );
97                        }
98                } else {
99#ifdef WIN32
100                        Sleep( 1 );
101#else
102                        usleep( 100 );
103#endif
104                }
105        }
106
107
108
109        _INFOLOG( "MIDI Thread DESTROY" );
110        pthread_exit( NULL );
111        return NULL;
112}
113
114
115PortMidiDriver::PortMidiDriver()
116                : MidiInput( "PortMidiDriver" )
117                , m_bRunning( false )
118{
119        Pm_Initialize();
120}
121
122
123PortMidiDriver::~PortMidiDriver()
124{
125        Pm_Terminate();
126}
127
128
129
130
131void PortMidiDriver::open()
132{
133        INFOLOG( "[open]" );
134
135        int nInputBufferSize = 100;
136
137        int nDeviceId = -1;
138        QString sMidiPortName = Preferences::getInstance()->m_sMidiPortName;
139        int nDevices = Pm_CountDevices();
140        for ( int i = 0; i < nDevices; i++ ) {
141                const PmDeviceInfo *info = Pm_GetDeviceInfo( i );
142                if ( info == NULL ) {
143                        ERRORLOG( "Could not open input device" );
144                }
145
146                if ( info->input == TRUE ) {
147                        if ( info->name == sMidiPortName.toStdString() ) {
148                                nDeviceId = i;
149                        }
150                }
151        }
152
153        if ( nDeviceId == -1 ) {
154                INFOLOG( "Midi input device not found." );
155                return;
156        }
157
158        const PmDeviceInfo *info = Pm_GetDeviceInfo( nDeviceId );
159        if ( info == NULL ) {
160                ERRORLOG( "Error opening midi input device" );
161        }
162
163        //INFOLOG( string( "Device: " ).append( info->interf ).append( " " ).append( info->name ) );
164        TIME_START;
165
166        PmError err = Pm_OpenInput(
167                          &m_pMidiIn,
168                          nDeviceId,
169                          NULL,
170                          nInputBufferSize,
171                          TIME_PROC,
172                          NULL
173                      );
174
175        if ( err != pmNoError ) {
176                ERRORLOG( "Error in Pm_OpenInput" );
177        }
178
179        m_bRunning = true;
180
181        pthread_attr_t attr;
182        pthread_attr_init( &attr );
183        pthread_create( &PortMidiDriverThread, &attr, PortMidiDriver_thread, ( void* )this );
184}
185
186
187void PortMidiDriver::close()
188{
189        INFOLOG( "[close]" );
190        if ( m_bRunning ) {
191                m_bRunning = false;
192                pthread_join( PortMidiDriverThread, NULL );
193                PmError err = Pm_Close( m_pMidiIn );
194                if ( err != pmNoError ) {
195                        ERRORLOG( "Error in Pm_OpenInput" );
196                }
197        }
198}
199
200
201
202std::vector<QString> PortMidiDriver::getOutputPortList()
203{
204        std::vector<QString> portList;
205
206        int nDevices = Pm_CountDevices();
207        for ( int i = 0; i < nDevices; i++ ) {
208                const PmDeviceInfo *info = Pm_GetDeviceInfo( i );
209                if ( info == NULL ) {
210                        ERRORLOG( "Could not open input device" );
211                }
212
213                if ( info->input == TRUE ) {
214                        INFOLOG( info->name );
215                        portList.push_back( info->name );
216                }
217        }
218
219        return portList;
220}
221
222};
223
224#endif  // PORTMIDI_SUPPORT
Note: See TracBrowser for help on using the browser.