/[svn]/linuxsampler/trunk/src/drivers/midi/MidiInputDeviceJack.cpp
ViewVC logotype

Annotation of /linuxsampler/trunk/src/drivers/midi/MidiInputDeviceJack.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2494 - (hide annotations) (download)
Wed Jan 1 17:48:01 2014 UTC (10 years, 3 months ago) by schoenebeck
File size: 9995 byte(s)
* Enabled automatic svn "Revision" macro expansion on certain files.
* Bumped version to 1.0.0.svn24.

1 persson 1651 /***************************************************************************
2     * *
3 persson 2114 * Copyright (C) 2008 - 2010 Andreas Persson *
4 persson 1651 * *
5     * This program is free software; you can redistribute it and/or modify *
6     * it under the terms of the GNU General Public License as published by *
7     * the Free Software Foundation; either version 2 of the License, or *
8     * (at your option) any later version. *
9     * *
10     * This program is distributed in the hope that it will be useful, *
11     * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13     * GNU General Public License for more details. *
14     * *
15     * You should have received a copy of the GNU General Public License *
16     * along with this program; if not, write to the Free Software *
17     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, *
18     * MA 02110-1301 USA. *
19     ***************************************************************************/
20    
21     #include "MidiInputDeviceJack.h"
22     #include "../../common/global_private.h"
23     #include "../audio/AudioOutputDeviceJack.h"
24     #include <errno.h>
25    
26     #ifndef HAVE_JACK_MIDI_GET_EVENT_COUNT
27     #define jack_midi_get_event_count(port_buf, nframes) jack_midi_port_get_info(port_buf, nframes)->event_count
28     #endif
29    
30     namespace LinuxSampler {
31    
32     /// number of currently existing JACK midi input devices in LinuxSampler
33     static int existingJackDevices = 0;
34    
35     // *************** MidiInputPortJack::ParameterName ***************
36     // *
37    
38     MidiInputDeviceJack::MidiInputPortJack::ParameterName::ParameterName(MidiInputPortJack* pPort) throw (Exception) : MidiInputPort::ParameterName(pPort, "midi_in_" + ToString(pPort->GetPortNumber())) {
39     this->pPort = pPort;
40     }
41    
42     void MidiInputDeviceJack::MidiInputPortJack::ParameterName::OnSetValue(String s) throw (Exception) {
43     if (jack_port_set_name(pPort->hJackPort, s.c_str())) throw Exception("Failed to rename JACK port");
44     }
45    
46    
47     // *************** MidiInputPortJack::ParameterJackBindings ***************
48     // *
49    
50     MidiInputDeviceJack::MidiInputPortJack::ParameterJackBindings::ParameterJackBindings(MidiInputPortJack* pPort) : DeviceRuntimeParameterStrings(std::vector<String>()) {
51     this->pPort = pPort;
52     }
53    
54     String MidiInputDeviceJack::MidiInputPortJack::ParameterJackBindings::Description() {
55     return "Bindings to other JACK clients";
56     }
57    
58     bool MidiInputDeviceJack::MidiInputPortJack::ParameterJackBindings::Fix() {
59     return false;
60     }
61    
62     std::vector<String> MidiInputDeviceJack::MidiInputPortJack::ParameterJackBindings::PossibilitiesAsString() {
63     const char** pPortNames = jack_get_ports(pPort->pDevice->hJackClient, NULL, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput);
64     if (!pPortNames) return std::vector<String>();
65     std::vector<String> result;
66     for (int i = 0; pPortNames[i]; i++) result.push_back(pPortNames[i]);
67     free(pPortNames);
68     return result;
69     }
70    
71     void MidiInputDeviceJack::MidiInputPortJack::ParameterJackBindings::OnSetValue(std::vector<String> vS) {
72     String dst_name = ((DeviceCreationParameterString*)pPort->pDevice->Parameters["NAME"])->ValueAsString() + ":" +
73     ((DeviceRuntimeParameterString*)pPort->Parameters["NAME"])->ValueAsString();
74     // disconnect all current bindings first
75     for (int i = 0; i < Bindings.size(); i++) {
76     String src_name = Bindings[i];
77 schoenebeck 2429 /*int res =*/ jack_disconnect(pPort->pDevice->hJackClient, src_name.c_str(), dst_name.c_str());
78 persson 1651 }
79     // connect new bindings
80     for (int i = 0; i < vS.size(); i++) {
81     String src_name = vS[i];
82     int res = jack_connect(pPort->pDevice->hJackClient, src_name.c_str(), dst_name.c_str());
83     if (res == EEXIST) throw MidiInputException("Jack: Connection to port '" + dst_name + "' already established");
84     else if (res) throw MidiInputException("Jack: Cannot connect port '" + src_name + "' to port '" + dst_name + "'");
85     }
86     // remember bindings
87     Bindings = vS;
88     }
89    
90     String MidiInputDeviceJack::MidiInputPortJack::ParameterJackBindings::Name() {
91     return "JACK_BINDINGS";
92     }
93    
94    
95    
96     // *************** MidiInputPortJack ***************
97     // *
98    
99     MidiInputDeviceJack::MidiInputPortJack::MidiInputPortJack(MidiInputDeviceJack* pDevice) throw (MidiInputException) : MidiInputPort(pDevice, pDevice->Ports.size()) {
100     this->pDevice = pDevice;
101    
102     String port_id = "midi_in_" + ToString(portNumber);
103     hJackPort = jack_port_register(pDevice->hJackClient, port_id.c_str(), JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
104     if (!hJackPort) throw MidiInputException("Jack: Cannot register Jack MIDI input port.");
105    
106     delete Parameters["NAME"];
107     Parameters["NAME"] = new ParameterName(this);
108     Parameters["JACK_BINDINGS"] = new ParameterJackBindings(this);
109     }
110    
111     MidiInputDeviceJack::MidiInputPortJack::~MidiInputPortJack() {
112     jack_port_unregister(pDevice->hJackClient, hJackPort);
113     }
114    
115    
116     // *************** MidiInputDeviceJack::ParameterName ***************
117     // *
118    
119     MidiInputDeviceJack::ParameterName::ParameterName() : DeviceCreationParameterString() {
120     InitWithDefault(); // use default name
121     }
122    
123     MidiInputDeviceJack::ParameterName::ParameterName(String s) : DeviceCreationParameterString(s) {
124     }
125    
126     String MidiInputDeviceJack::ParameterName::Description() {
127     return "Arbitrary JACK client name";
128     }
129    
130     bool MidiInputDeviceJack::ParameterName::Fix() {
131     return true;
132     }
133    
134     bool MidiInputDeviceJack::ParameterName::Mandatory() {
135     return false;
136     }
137    
138     std::map<String,DeviceCreationParameter*> MidiInputDeviceJack::ParameterName::DependsAsParameters() {
139     return std::map<String,DeviceCreationParameter*>(); // no dependencies
140     }
141    
142     std::vector<String> MidiInputDeviceJack::ParameterName::PossibilitiesAsString(std::map<String,String> Parameters) {
143     return std::vector<String>();
144     }
145    
146     optional<String> MidiInputDeviceJack::ParameterName::DefaultAsString(std::map<String,String> Parameters) {
147     return (existingJackDevices) ? "LinuxSampler" + ToString(existingJackDevices) : "LinuxSampler";
148     }
149    
150     void MidiInputDeviceJack::ParameterName::OnSetValue(String s) throw (Exception) {
151     // not possible, as parameter is fix
152     }
153    
154     String MidiInputDeviceJack::ParameterName::Name() {
155     return "NAME";
156     }
157    
158    
159    
160     // *************** MidiInputDeviceJack ***************
161     // *
162    
163     MidiInputDeviceJack::MidiInputDeviceJack(std::map<String,DeviceCreationParameter*> Parameters, void* pSampler) : MidiInputDevice(Parameters, pSampler) {
164     pJackClient = JackClient::CreateMidi(((DeviceCreationParameterString*)Parameters["NAME"])->ValueAsString());
165     hJackClient = pJackClient->hJackClient;
166     existingJackDevices++;
167    
168 persson 2114 AcquirePorts(((DeviceCreationParameterInt*)Parameters["PORTS"])->ValueAsInt());
169     if (((DeviceCreationParameterBool*)Parameters["ACTIVE"])->ValueAsBool()) {
170 persson 1651 Listen();
171 persson 2114 }
172 persson 1651 }
173    
174     MidiInputDeviceJack::~MidiInputDeviceJack() {
175     StopListen();
176     // free the midi ports (we can't let the base class do this,
177     // as the MidiInputPortJack destructors need access to
178     // hJackClient)
179     for (std::map<int,MidiInputPort*>::iterator iter = Ports.begin(); iter != Ports.end() ; iter++) {
180     delete static_cast<MidiInputPortJack*>(iter->second);
181     }
182     Ports.clear();
183    
184     JackClient::ReleaseMidi(((DeviceCreationParameterString*)Parameters["NAME"])->ValueAsString());
185 schoenebeck 1993 existingJackDevices--; //FIXME: this is too simple, can lead to multiple clients with the same name
186 persson 1651 }
187    
188     MidiInputDeviceJack::MidiInputPortJack* MidiInputDeviceJack::CreateMidiPort() {
189     return new MidiInputPortJack(this);
190     }
191    
192     String MidiInputDeviceJack::Name() {
193     return "JACK";
194     }
195    
196     String MidiInputDeviceJack::Driver() {
197     return Name();
198     }
199    
200     void MidiInputDeviceJack::Listen() {
201     pJackClient->SetMidiInputDevice(this);
202     }
203    
204     void MidiInputDeviceJack::StopListen() {
205     pJackClient->SetMidiInputDevice(0);
206     }
207    
208     String MidiInputDeviceJack::Description() {
209     return "JACK Audio Connection Kit";
210     }
211    
212     String MidiInputDeviceJack::Version() {
213 schoenebeck 2494 String s = "$Revision$";
214 persson 1651 return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
215     }
216    
217     void MidiInputDeviceJack::Process(int nsamples) {
218     int nbPorts = Ports.size();
219     for (int i = 0 ; i < nbPorts ; i++) {
220     MidiInputPortJack* port = static_cast<MidiInputPortJack*>(Ports[i]);
221     void* port_buffer = jack_port_get_buffer(port->hJackPort, nsamples);
222    
223     #if JACK_MIDI_FUNCS_NEED_NFRAMES
224     int event_count = jack_midi_get_event_count(port_buffer, nsamples); // old jack version
225     #else
226     int event_count = jack_midi_get_event_count(port_buffer);
227     #endif
228 persson 2114 for (int i = 0 ; i < event_count ; i++) {
229 persson 1651 jack_midi_event_t ev;
230     #if JACK_MIDI_FUNCS_NEED_NFRAMES
231     jack_midi_event_get(&ev, port_buffer, i, nsamples); // old jack version
232     #else
233     jack_midi_event_get(&ev, port_buffer, i);
234     #endif
235 persson 2114 if (ev.buffer) { // jack2 1.9.5 has been seen sending NULL here
236     port->DispatchRaw(ev.buffer, ev.time);
237     }
238 persson 1651 }
239     }
240     }
241     }

Properties

Name Value
svn:keywords Revision

  ViewVC Help
Powered by ViewVC