2 Copyright (C) 2009 Grame.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 (at your option) any later version.
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "JackSystemDeps.h"
21 #include "JackMidiDriver.h"
23 #include "JackError.h"
24 #include "JackEngineControl.h"
26 #include "JackGraphManager.h"
27 #include "JackException.h"
35 JackMidiDriver::JackMidiDriver(const char* name
, const char* alias
, JackLockedEngine
* engine
, JackSynchro
* table
)
36 : JackDriver(name
, alias
, engine
, table
)
39 JackMidiDriver::~JackMidiDriver()
42 int JackMidiDriver::Open(bool capturing
,
47 const char* capture_driver_name
,
48 const char* playback_driver_name
,
49 jack_nframes_t capture_latency
,
50 jack_nframes_t playback_latency
)
52 fCaptureChannels
= inchannels
;
53 fPlaybackChannels
= outchannels
;
54 return JackDriver::Open(0, 0, capturing
, playing
, inchannels
, outchannels
, monitor
, capture_driver_name
, playback_driver_name
, capture_latency
, playback_latency
);
57 int JackMidiDriver::Attach()
60 jack_port_id_t port_index
;
61 char name
[REAL_JACK_PORT_NAME_SIZE
+1];
62 char alias
[REAL_JACK_PORT_NAME_SIZE
+1];
65 jack_log("JackMidiDriver::Attach fBufferSize = %ld fSampleRate = %ld", fEngineControl
->fBufferSize
, fEngineControl
->fSampleRate
);
67 for (i
= 0; i
< fCaptureChannels
; i
++) {
68 snprintf(alias
, sizeof(alias
), "%s:%s:out%d", fAliasName
, fCaptureDriverName
, i
+ 1);
69 snprintf(name
, sizeof(name
), "%s:capture_%d", fClientControl
.fName
, i
+ 1);
70 if (fEngine
->PortRegister(fClientControl
.fRefNum
, name
, JACK_DEFAULT_MIDI_TYPE
, CaptureDriverFlags
, fEngineControl
->fBufferSize
, &port_index
) < 0) {
71 jack_error("driver: cannot register port for %s", name
);
74 port
= fGraphManager
->GetPort(port_index
);
75 port
->SetAlias(alias
);
76 fCapturePortList
[i
] = port_index
;
77 jack_log("JackMidiDriver::Attach fCapturePortList[i] port_index = %ld", port_index
);
80 for (i
= 0; i
< fPlaybackChannels
; i
++) {
81 snprintf(alias
, sizeof(alias
), "%s:%s:in%d", fAliasName
, fPlaybackDriverName
, i
+ 1);
82 snprintf(name
, sizeof(name
), "%s:playback_%d", fClientControl
.fName
, i
+ 1);
83 if (fEngine
->PortRegister(fClientControl
.fRefNum
, name
, JACK_DEFAULT_MIDI_TYPE
, PlaybackDriverFlags
, fEngineControl
->fBufferSize
, &port_index
) < 0) {
84 jack_error("driver: cannot register port for %s", name
);
87 port
= fGraphManager
->GetPort(port_index
);
88 port
->SetAlias(alias
);
89 fPlaybackPortList
[i
] = port_index
;
90 jack_log("JackMidiDriver::Attach fPlaybackPortList[i] port_index = %ld", port_index
);
97 int JackMidiDriver::Detach()
100 jack_log("JackMidiDriver::Detach");
102 for (i
= 0; i
< fCaptureChannels
; i
++) {
103 fEngine
->PortUnRegister(fClientControl
.fRefNum
, fCapturePortList
[i
]);
106 for (i
= 0; i
< fPlaybackChannels
; i
++) {
107 fEngine
->PortUnRegister(fClientControl
.fRefNum
, fPlaybackPortList
[i
]);
113 void JackMidiDriver::UpdateLatencies()
115 jack_latency_range_t range
;
117 for (int i
= 0; i
< fCaptureChannels
; i
++) {
118 range
.max
= range
.min
= fEngineControl
->fBufferSize
;
119 fGraphManager
->GetPort(fCapturePortList
[i
])->SetLatencyRange(JackCaptureLatency
, &range
);
122 for (int i
= 0; i
< fPlaybackChannels
; i
++) {
123 if (! fEngineControl
->fSyncMode
) {
124 range
.max
= range
.min
= fEngineControl
->fBufferSize
* 2;
126 fGraphManager
->GetPort(fPlaybackPortList
[i
])->SetLatencyRange(JackPlaybackLatency
, &range
);
130 int JackMidiDriver::SetBufferSize(jack_nframes_t buffer_size
)
136 int JackMidiDriver::ProcessReadSync()
140 // Read input buffers for the current cycle
142 jack_error("JackMidiDriver::ProcessReadSync: read error");
146 if (ResumeRefNum() < 0) {
147 jack_error("JackMidiDriver::ProcessReadSync: ResumeRefNum error");
154 int JackMidiDriver::ProcessWriteSync()
158 if (SuspendRefNum() < 0) {
159 jack_error("JackMidiDriver::ProcessWriteSync: SuspendRefNum error");
163 // Write output buffers from the current cycle
165 jack_error("JackMidiDriver::ProcessWriteSync: write error");
172 int JackMidiDriver::ProcessReadAsync()
176 // Read input buffers for the current cycle
178 jack_error("JackMidiDriver::ProcessReadAsync: read error");
182 // Write output buffers from the previous cycle
184 jack_error("JackMidiDriver::ProcessReadAsync: write error");
188 if (ResumeRefNum() < 0) {
189 jack_error("JackMidiDriver::ProcessReadAsync: ResumeRefNum error");
196 int JackMidiDriver::ProcessWriteAsync()
201 JackMidiBuffer
* JackMidiDriver::GetInputBuffer(int port_index
)
203 assert(fCapturePortList
[port_index
]);
204 return (JackMidiBuffer
*)fGraphManager
->GetBuffer(fCapturePortList
[port_index
], fEngineControl
->fBufferSize
);
207 JackMidiBuffer
* JackMidiDriver::GetOutputBuffer(int port_index
)
209 assert(fPlaybackPortList
[port_index
]);
210 return (JackMidiBuffer
*)fGraphManager
->GetBuffer(fPlaybackPortList
[port_index
], fEngineControl
->fBufferSize
);
213 } // end of namespace