/[svn]/linuxsampler/trunk/src/network/lscpserver.cpp
ViewVC logotype

Annotation of /linuxsampler/trunk/src/network/lscpserver.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2500 - (hide annotations) (download)
Fri Jan 10 12:20:05 2014 UTC (10 years, 3 months ago) by schoenebeck
File size: 158968 byte(s)
* Added support for multiple MIDI input ports per sampler channel (added
  various new C++ API methods for this new feature/design, old C++ API
  methods are now marked as deprecated but should still provide full
  behavior backward compatibility).
* LSCP Network interface: Added the following new LSCP commands for the new
  feature mentioned above: "ADD CHANNEL MIDI_INPUT",
  "REMOVE CHANNEL MIDI_INPUT" and "LIST CHANNEL MIDI_INPUTS". As with the
  C++ API changes, the old LSCP commands for MIDI input management are now
  marked as deprecated, but are still there and should provide full behavior
  backward compatibility.
* New LSCP specification document (LSCP v1.6).
* AbstractEngine::GSCheckSum(): don't allocate memory on the stack (was
  unsafe and caused compilation error with old clang 2.x).
* Bumped version (1.0.0.svn25).

1 schoenebeck 35 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5 schoenebeck 56 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 schoenebeck 2500 * Copyright (C) 2005 - 2014 Christian Schoenebeck *
7 schoenebeck 35 * *
8 schoenebeck 385 * This library is free software; you can redistribute it and/or modify *
9 schoenebeck 35 * it under the terms of the GNU General Public License as published by *
10     * the Free Software Foundation; either version 2 of the License, or *
11     * (at your option) any later version. *
12     * *
13 schoenebeck 385 * This library is distributed in the hope that it will be useful, *
14 schoenebeck 35 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16     * GNU General Public License for more details. *
17     * *
18     * You should have received a copy of the GNU General Public License *
19 schoenebeck 385 * along with this library; if not, write to the Free Software *
20 schoenebeck 35 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21     * MA 02111-1307 USA *
22     ***************************************************************************/
23    
24 persson 1713 #include <algorithm>
25 iliev 1771 #include <string>
26 persson 1713
27 iliev 1835 #include "../common/File.h"
28 schoenebeck 35 #include "lscpserver.h"
29 senkov 113 #include "lscpresultset.h"
30 senkov 170 #include "lscpevent.h"
31 schoenebeck 35
32 senoner 1481 #if defined(WIN32)
33 senoner 1537 #include <windows.h>
34 senoner 1481 #else
35 schoenebeck 411 #include <fcntl.h>
36 senoner 1481 #endif
37 schoenebeck 411
38 iliev 1161 #if ! HAVE_SQLITE3
39     #define DOESNT_HAVE_SQLITE3 "No database support. SQLITE3 was not installed when linuxsampler was built."
40 senkov 397 #endif
41    
42 schoenebeck 411 #include "../engines/EngineFactory.h"
43 schoenebeck 660 #include "../engines/EngineChannelFactory.h"
44 schoenebeck 203 #include "../drivers/audio/AudioOutputDeviceFactory.h"
45     #include "../drivers/midi/MidiInputDeviceFactory.h"
46 schoenebeck 2135 #include "../effects/EffectFactory.h"
47 schoenebeck 53
48 persson 1765 namespace LinuxSampler {
49 schoenebeck 1399
50 senkov 170 /**
51 schoenebeck 1399 * Returns a copy of the given string where all special characters are
52     * replaced by LSCP escape sequences ("\xHH"). This function shall be used
53     * to escape LSCP response fields in case the respective response field is
54     * actually defined as using escape sequences in the LSCP specs.
55     *
56     * @e Caution: DO NOT use this function for escaping path based responses,
57     * use the Path class (src/common/Path.h) for this instead!
58     */
59     static String _escapeLscpResponse(String txt) {
60     for (int i = 0; i < txt.length(); i++) {
61     const char c = txt.c_str()[i];
62     if (
63     !(c >= '0' && c <= '9') &&
64     !(c >= 'a' && c <= 'z') &&
65     !(c >= 'A' && c <= 'Z') &&
66     !(c == ' ') && !(c == '!') && !(c == '#') && !(c == '$') &&
67     !(c == '%') && !(c == '&') && !(c == '(') && !(c == ')') &&
68     !(c == '*') && !(c == '+') && !(c == ',') && !(c == '-') &&
69     !(c == '.') && !(c == '/') && !(c == ':') && !(c == ';') &&
70     !(c == '<') && !(c == '=') && !(c == '>') && !(c == '?') &&
71 iliev 1403 !(c == '@') && !(c == '[') && !(c == ']') &&
72 schoenebeck 1399 !(c == '^') && !(c == '_') && !(c == '`') && !(c == '{') &&
73     !(c == '|') && !(c == '}') && !(c == '~')
74     ) {
75     // convert the "special" character into a "\xHH" LSCP escape sequence
76     char buf[5];
77     snprintf(buf, sizeof(buf), "\\x%02x", static_cast<unsigned char>(c));
78     txt.replace(i, 1, buf);
79     i += 3;
80     }
81     }
82     return txt;
83     }
84    
85     /**
86 senkov 170 * Below are a few static members of the LSCPServer class.
87     * The big assumption here is that LSCPServer is going to remain a singleton.
88     * These members are used to support client connections.
89     * Class handles multiple connections at the same time using select() and non-blocking recv()
90     * Commands are processed by a single LSCPServer thread.
91     * Notifications are delivered either by the thread that originated them
92     * or (if the resultset is currently in progress) by the LSCPServer thread
93     * after the resultset was sent out.
94     * This makes sure that resultsets can not be interrupted by notifications.
95     * This also makes sure that the thread sending notification is not blocked
96     * by the LSCPServer thread.
97     */
98     fd_set LSCPServer::fdSet;
99     int LSCPServer::currentSocket = -1;
100 persson 2427 std::vector<yyparse_param_t> LSCPServer::Sessions;
101     std::vector<yyparse_param_t>::iterator itCurrentSession;
102     std::map<int,String> LSCPServer::bufferedNotifies;
103     std::map<int,String> LSCPServer::bufferedCommands;
104     std::map< LSCPEvent::event_t, std::list<int> > LSCPServer::eventSubscriptions;
105     Mutex LSCPServer::NotifyMutex;
106     Mutex LSCPServer::NotifyBufferMutex;
107     Mutex LSCPServer::SubscriptionMutex;
108     Mutex LSCPServer::RTNotifyMutex;
109 senkov 170
110 schoenebeck 1686 LSCPServer::LSCPServer(Sampler* pSampler, long int addr, short int port) : Thread(true, false, 0, -4), eventHandler(this) {
111 senkov 667 SocketAddress.sin_family = AF_INET;
112     SocketAddress.sin_addr.s_addr = addr;
113     SocketAddress.sin_port = port;
114 schoenebeck 53 this->pSampler = pSampler;
115 iliev 981 LSCPEvent::RegisterEvent(LSCPEvent::event_audio_device_count, "AUDIO_OUTPUT_DEVICE_COUNT");
116     LSCPEvent::RegisterEvent(LSCPEvent::event_audio_device_info, "AUDIO_OUTPUT_DEVICE_INFO");
117     LSCPEvent::RegisterEvent(LSCPEvent::event_midi_device_count, "MIDI_INPUT_DEVICE_COUNT");
118     LSCPEvent::RegisterEvent(LSCPEvent::event_midi_device_info, "MIDI_INPUT_DEVICE_INFO");
119 schoenebeck 556 LSCPEvent::RegisterEvent(LSCPEvent::event_channel_count, "CHANNEL_COUNT");
120 senkov 170 LSCPEvent::RegisterEvent(LSCPEvent::event_voice_count, "VOICE_COUNT");
121     LSCPEvent::RegisterEvent(LSCPEvent::event_stream_count, "STREAM_COUNT");
122     LSCPEvent::RegisterEvent(LSCPEvent::event_buffer_fill, "BUFFER_FILL");
123 schoenebeck 556 LSCPEvent::RegisterEvent(LSCPEvent::event_channel_info, "CHANNEL_INFO");
124 iliev 1108 LSCPEvent::RegisterEvent(LSCPEvent::event_fx_send_count, "FX_SEND_COUNT");
125     LSCPEvent::RegisterEvent(LSCPEvent::event_fx_send_info, "FX_SEND_INFO");
126 iliev 981 LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_map_count, "MIDI_INSTRUMENT_MAP_COUNT");
127     LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_map_info, "MIDI_INSTRUMENT_MAP_INFO");
128     LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_count, "MIDI_INSTRUMENT_COUNT");
129     LSCPEvent::RegisterEvent(LSCPEvent::event_midi_instr_info, "MIDI_INSTRUMENT_INFO");
130 iliev 1161 LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_dir_count, "DB_INSTRUMENT_DIRECTORY_COUNT");
131     LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_dir_info, "DB_INSTRUMENT_DIRECTORY_INFO");
132     LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_count, "DB_INSTRUMENT_COUNT");
133     LSCPEvent::RegisterEvent(LSCPEvent::event_db_instr_info, "DB_INSTRUMENT_INFO");
134 iliev 1200 LSCPEvent::RegisterEvent(LSCPEvent::event_db_instrs_job_info, "DB_INSTRUMENTS_JOB_INFO");
135 senkov 170 LSCPEvent::RegisterEvent(LSCPEvent::event_misc, "MISCELLANEOUS");
136 iliev 1541 LSCPEvent::RegisterEvent(LSCPEvent::event_total_stream_count, "TOTAL_STREAM_COUNT");
137 iliev 778 LSCPEvent::RegisterEvent(LSCPEvent::event_total_voice_count, "TOTAL_VOICE_COUNT");
138 iliev 1108 LSCPEvent::RegisterEvent(LSCPEvent::event_global_info, "GLOBAL_INFO");
139 schoenebeck 1686 LSCPEvent::RegisterEvent(LSCPEvent::event_channel_midi, "CHANNEL_MIDI");
140 schoenebeck 1695 LSCPEvent::RegisterEvent(LSCPEvent::event_device_midi, "DEVICE_MIDI");
141 iliev 2188 LSCPEvent::RegisterEvent(LSCPEvent::event_fx_instance_count, "EFFECT_INSTANCE_COUNT");
142     LSCPEvent::RegisterEvent(LSCPEvent::event_fx_instance_info, "EFFECT_INSTANCE_INFO");
143     LSCPEvent::RegisterEvent(LSCPEvent::event_send_fx_chain_count, "SEND_EFFECT_CHAIN_COUNT");
144     LSCPEvent::RegisterEvent(LSCPEvent::event_send_fx_chain_info, "SEND_EFFECT_CHAIN_INFO");
145 schoenebeck 475 hSocket = -1;
146 schoenebeck 35 }
147    
148 schoenebeck 475 LSCPServer::~LSCPServer() {
149 iliev 1848 CloseAllConnections();
150 persson 1850 InstrumentManager::StopBackgroundThread();
151 senoner 1481 #if defined(WIN32)
152     if (hSocket >= 0) closesocket(hSocket);
153     #else
154 schoenebeck 475 if (hSocket >= 0) close(hSocket);
155 senoner 1481 #endif
156 schoenebeck 475 }
157    
158 schoenebeck 1686 LSCPServer::EventHandler::EventHandler(LSCPServer* pParent) {
159     this->pParent = pParent;
160     }
161    
162     LSCPServer::EventHandler::~EventHandler() {
163     std::vector<midi_listener_entry> l = channelMidiListeners;
164     channelMidiListeners.clear();
165     for (int i = 0; i < l.size(); i++)
166     delete l[i].pMidiListener;
167     }
168    
169 iliev 1133 void LSCPServer::EventHandler::ChannelCountChanged(int NewCount) {
170 iliev 1130 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_count, NewCount));
171     }
172    
173 schoenebeck 1686 void LSCPServer::EventHandler::ChannelAdded(SamplerChannel* pChannel) {
174     pChannel->AddEngineChangeListener(this);
175     }
176    
177     void LSCPServer::EventHandler::ChannelToBeRemoved(SamplerChannel* pChannel) {
178     if (!pChannel->GetEngineChannel()) return;
179     EngineToBeChanged(pChannel->Index());
180     }
181    
182     void LSCPServer::EventHandler::EngineToBeChanged(int ChannelId) {
183     SamplerChannel* pSamplerChannel =
184     pParent->pSampler->GetSamplerChannel(ChannelId);
185     if (!pSamplerChannel) return;
186     EngineChannel* pEngineChannel =
187     pSamplerChannel->GetEngineChannel();
188     if (!pEngineChannel) return;
189     for (std::vector<midi_listener_entry>::iterator iter = channelMidiListeners.begin(); iter != channelMidiListeners.end(); ++iter) {
190     if ((*iter).pEngineChannel == pEngineChannel) {
191     VirtualMidiDevice* pMidiListener = (*iter).pMidiListener;
192     pEngineChannel->Disconnect(pMidiListener);
193     channelMidiListeners.erase(iter);
194     delete pMidiListener;
195     return;
196     }
197     }
198     }
199    
200     void LSCPServer::EventHandler::EngineChanged(int ChannelId) {
201     SamplerChannel* pSamplerChannel =
202     pParent->pSampler->GetSamplerChannel(ChannelId);
203     if (!pSamplerChannel) return;
204     EngineChannel* pEngineChannel =
205     pSamplerChannel->GetEngineChannel();
206     if (!pEngineChannel) return;
207     VirtualMidiDevice* pMidiListener = new VirtualMidiDevice;
208     pEngineChannel->Connect(pMidiListener);
209     midi_listener_entry entry = {
210     pSamplerChannel, pEngineChannel, pMidiListener
211     };
212     channelMidiListeners.push_back(entry);
213     }
214    
215 iliev 1133 void LSCPServer::EventHandler::AudioDeviceCountChanged(int NewCount) {
216 iliev 1130 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_count, NewCount));
217     }
218    
219 iliev 1133 void LSCPServer::EventHandler::MidiDeviceCountChanged(int NewCount) {
220 iliev 1130 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_count, NewCount));
221     }
222    
223 schoenebeck 1695 void LSCPServer::EventHandler::MidiDeviceToBeDestroyed(MidiInputDevice* pDevice) {
224     pDevice->RemoveMidiPortCountListener(this);
225     for (int i = 0; i < pDevice->PortCount(); ++i)
226     MidiPortToBeRemoved(pDevice->GetPort(i));
227     }
228    
229     void LSCPServer::EventHandler::MidiDeviceCreated(MidiInputDevice* pDevice) {
230     pDevice->AddMidiPortCountListener(this);
231     for (int i = 0; i < pDevice->PortCount(); ++i)
232     MidiPortAdded(pDevice->GetPort(i));
233     }
234    
235     void LSCPServer::EventHandler::MidiPortCountChanged(int NewCount) {
236     // yet unused
237     }
238    
239     void LSCPServer::EventHandler::MidiPortToBeRemoved(MidiInputPort* pPort) {
240     for (std::vector<device_midi_listener_entry>::iterator iter = deviceMidiListeners.begin(); iter != deviceMidiListeners.end(); ++iter) {
241     if ((*iter).pPort == pPort) {
242     VirtualMidiDevice* pMidiListener = (*iter).pMidiListener;
243     pPort->Disconnect(pMidiListener);
244     deviceMidiListeners.erase(iter);
245     delete pMidiListener;
246     return;
247     }
248     }
249     }
250    
251     void LSCPServer::EventHandler::MidiPortAdded(MidiInputPort* pPort) {
252     // find out the device ID
253     std::map<uint, MidiInputDevice*> devices =
254     pParent->pSampler->GetMidiInputDevices();
255     for (
256     std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
257     iter != devices.end(); ++iter
258     ) {
259     if (iter->second == pPort->GetDevice()) { // found
260     VirtualMidiDevice* pMidiListener = new VirtualMidiDevice;
261     pPort->Connect(pMidiListener);
262     device_midi_listener_entry entry = {
263     pPort, pMidiListener, iter->first
264     };
265     deviceMidiListeners.push_back(entry);
266     return;
267     }
268     }
269     }
270    
271 iliev 1133 void LSCPServer::EventHandler::MidiInstrumentCountChanged(int MapId, int NewCount) {
272 iliev 1130 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_count, MapId, NewCount));
273     }
274    
275 iliev 1133 void LSCPServer::EventHandler::MidiInstrumentInfoChanged(int MapId, int Bank, int Program) {
276 iliev 1130 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_info, MapId, Bank, Program));
277     }
278    
279 iliev 1133 void LSCPServer::EventHandler::MidiInstrumentMapCountChanged(int NewCount) {
280 iliev 1130 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_map_count, NewCount));
281     }
282    
283 iliev 1133 void LSCPServer::EventHandler::MidiInstrumentMapInfoChanged(int MapId) {
284 iliev 1130 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_instr_map_info, MapId));
285     }
286    
287 iliev 1133 void LSCPServer::EventHandler::FxSendCountChanged(int ChannelId, int NewCount) {
288 iliev 1130 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_count, ChannelId, NewCount));
289     }
290    
291 iliev 1133 void LSCPServer::EventHandler::VoiceCountChanged(int ChannelId, int NewCount) {
292 iliev 1130 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_voice_count, ChannelId, NewCount));
293     }
294    
295 iliev 1133 void LSCPServer::EventHandler::StreamCountChanged(int ChannelId, int NewCount) {
296 iliev 1130 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_stream_count, ChannelId, NewCount));
297     }
298    
299 iliev 1133 void LSCPServer::EventHandler::BufferFillChanged(int ChannelId, String FillData) {
300 iliev 1130 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_buffer_fill, ChannelId, FillData));
301     }
302    
303 iliev 1133 void LSCPServer::EventHandler::TotalVoiceCountChanged(int NewCount) {
304 iliev 1130 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_total_voice_count, NewCount));
305     }
306    
307 iliev 1541 void LSCPServer::EventHandler::TotalStreamCountChanged(int NewCount) {
308     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_total_stream_count, NewCount));
309     }
310    
311 iliev 1161 #if HAVE_SQLITE3
312     void LSCPServer::DbInstrumentsEventHandler::DirectoryCountChanged(String Dir) {
313 iliev 1345 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_dir_count, InstrumentsDb::toEscapedPath(Dir)));
314 iliev 1161 }
315 iliev 1130
316 iliev 1161 void LSCPServer::DbInstrumentsEventHandler::DirectoryInfoChanged(String Dir) {
317 iliev 1345 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_dir_info, InstrumentsDb::toEscapedPath(Dir)));
318 iliev 1161 }
319    
320     void LSCPServer::DbInstrumentsEventHandler::DirectoryNameChanged(String Dir, String NewName) {
321 iliev 1345 Dir = "'" + InstrumentsDb::toEscapedPath(Dir) + "'";
322 iliev 1350 NewName = "'" + InstrumentsDb::toEscapedPath(NewName) + "'";
323 iliev 1161 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_dir_info, "NAME", Dir, NewName));
324     }
325    
326     void LSCPServer::DbInstrumentsEventHandler::InstrumentCountChanged(String Dir) {
327 iliev 1345 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_count, InstrumentsDb::toEscapedPath(Dir)));
328 iliev 1161 }
329    
330     void LSCPServer::DbInstrumentsEventHandler::InstrumentInfoChanged(String Instr) {
331 iliev 1345 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_info, InstrumentsDb::toEscapedPath(Instr)));
332 iliev 1161 }
333 iliev 1200
334 iliev 1161 void LSCPServer::DbInstrumentsEventHandler::InstrumentNameChanged(String Instr, String NewName) {
335 iliev 1345 Instr = "'" + InstrumentsDb::toEscapedPath(Instr) + "'";
336 iliev 1350 NewName = "'" + InstrumentsDb::toEscapedPath(NewName) + "'";
337 iliev 1161 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instr_info, "NAME", Instr, NewName));
338     }
339 iliev 1200
340     void LSCPServer::DbInstrumentsEventHandler::JobStatusChanged(int JobId) {
341     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_db_instrs_job_info, JobId));
342     }
343 iliev 1161 #endif // HAVE_SQLITE3
344    
345 iliev 1835 void LSCPServer::RemoveListeners() {
346     pSampler->RemoveChannelCountListener(&eventHandler);
347     pSampler->RemoveAudioDeviceCountListener(&eventHandler);
348     pSampler->RemoveMidiDeviceCountListener(&eventHandler);
349     pSampler->RemoveVoiceCountListener(&eventHandler);
350     pSampler->RemoveStreamCountListener(&eventHandler);
351     pSampler->RemoveBufferFillListener(&eventHandler);
352     pSampler->RemoveTotalStreamCountListener(&eventHandler);
353     pSampler->RemoveTotalVoiceCountListener(&eventHandler);
354     pSampler->RemoveFxSendCountListener(&eventHandler);
355     MidiInstrumentMapper::RemoveMidiInstrumentCountListener(&eventHandler);
356     MidiInstrumentMapper::RemoveMidiInstrumentInfoListener(&eventHandler);
357     MidiInstrumentMapper::RemoveMidiInstrumentMapCountListener(&eventHandler);
358     MidiInstrumentMapper::RemoveMidiInstrumentMapInfoListener(&eventHandler);
359     #if HAVE_SQLITE3
360     InstrumentsDb::GetInstrumentsDb()->RemoveInstrumentsDbListener(&dbInstrumentsEventHandler);
361     #endif
362     }
363 iliev 1161
364 schoenebeck 211 /**
365     * Blocks the calling thread until the LSCP Server is initialized and
366     * accepting socket connections, if the server is already initialized then
367     * this method will return immediately.
368     * @param TimeoutSeconds - optional: max. wait time in seconds
369     * (default: 0s)
370     * @param TimeoutNanoSeconds - optional: max wait time in nano seconds
371     * (default: 0ns)
372     * @returns 0 on success, a value less than 0 if timeout exceeded
373     */
374     int LSCPServer::WaitUntilInitialized(long TimeoutSeconds, long TimeoutNanoSeconds) {
375     return Initialized.WaitAndUnlockIf(false, TimeoutSeconds, TimeoutNanoSeconds);
376     }
377    
378 schoenebeck 35 int LSCPServer::Main() {
379 senoner 1481 #if defined(WIN32)
380     WSADATA wsaData;
381     int iResult;
382     iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
383     if (iResult != 0) {
384     std::cerr << "LSCPServer: WSAStartup failed: " << iResult << "\n";
385     exit(EXIT_FAILURE);
386     }
387     #endif
388 schoenebeck 475 hSocket = socket(AF_INET, SOCK_STREAM, 0);
389 schoenebeck 35 if (hSocket < 0) {
390     std::cerr << "LSCPServer: Could not create server socket." << std::endl;
391 schoenebeck 53 //return -1;
392     exit(EXIT_FAILURE);
393 schoenebeck 35 }
394    
395     if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {
396 schoenebeck 227 std::cerr << "LSCPServer: Could not bind server socket, retrying for " << ToString(LSCP_SERVER_BIND_TIMEOUT) << " seconds...";
397     for (int trial = 0; true; trial++) { // retry for LSCP_SERVER_BIND_TIMEOUT seconds
398     if (bind(hSocket, (sockaddr*) &SocketAddress, sizeof(sockaddr_in)) < 0) {
399     if (trial > LSCP_SERVER_BIND_TIMEOUT) {
400     std::cerr << "gave up!" << std::endl;
401 senoner 1481 #if defined(WIN32)
402     closesocket(hSocket);
403     #else
404 schoenebeck 227 close(hSocket);
405 senoner 1481 #endif
406 schoenebeck 227 //return -1;
407     exit(EXIT_FAILURE);
408     }
409     else sleep(1); // sleep 1s
410     }
411     else break; // success
412     }
413 schoenebeck 35 }
414    
415     listen(hSocket, 1);
416 schoenebeck 211 Initialized.Set(true);
417 schoenebeck 1252
418 iliev 1130 // Registering event listeners
419 iliev 1133 pSampler->AddChannelCountListener(&eventHandler);
420     pSampler->AddAudioDeviceCountListener(&eventHandler);
421     pSampler->AddMidiDeviceCountListener(&eventHandler);
422     pSampler->AddVoiceCountListener(&eventHandler);
423     pSampler->AddStreamCountListener(&eventHandler);
424     pSampler->AddBufferFillListener(&eventHandler);
425 iliev 1541 pSampler->AddTotalStreamCountListener(&eventHandler);
426 iliev 1133 pSampler->AddTotalVoiceCountListener(&eventHandler);
427     pSampler->AddFxSendCountListener(&eventHandler);
428     MidiInstrumentMapper::AddMidiInstrumentCountListener(&eventHandler);
429     MidiInstrumentMapper::AddMidiInstrumentInfoListener(&eventHandler);
430     MidiInstrumentMapper::AddMidiInstrumentMapCountListener(&eventHandler);
431     MidiInstrumentMapper::AddMidiInstrumentMapInfoListener(&eventHandler);
432 iliev 1161 #if HAVE_SQLITE3
433     InstrumentsDb::GetInstrumentsDb()->AddInstrumentsDbListener(&dbInstrumentsEventHandler);
434     #endif
435 schoenebeck 35 // now wait for client connections and handle their requests
436     sockaddr_in client;
437     int length = sizeof(client);
438 senkov 170 FD_ZERO(&fdSet);
439     FD_SET(hSocket, &fdSet);
440     int maxSessions = hSocket;
441 schoenebeck 203
442 iliev 793 timeval timeout;
443    
444 schoenebeck 35 while (true) {
445 nagata 1649 #if CONFIG_PTHREAD_TESTCANCEL
446     TestCancel();
447     #endif
448 iliev 793 // check if some engine channel's parameter / status changed, if so notify the respective LSCP event subscribers
449     {
450 persson 2427 LockGuard lock(EngineChannelFactory::EngineChannelsMutex);
451 iliev 793 std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();
452     std::set<EngineChannel*>::iterator itEngineChannel = engineChannels.begin();
453     std::set<EngineChannel*>::iterator itEnd = engineChannels.end();
454     for (; itEngineChannel != itEnd; ++itEngineChannel) {
455     if ((*itEngineChannel)->StatusChanged()) {
456 iliev 1761 SendLSCPNotify(LSCPEvent(LSCPEvent::event_channel_info, (*itEngineChannel)->GetSamplerChannel()->Index()));
457 iliev 793 }
458 iliev 1108
459     for (int i = 0; i < (*itEngineChannel)->GetFxSendCount(); i++) {
460     FxSend* fxs = (*itEngineChannel)->GetFxSend(i);
461     if(fxs != NULL && fxs->IsInfoChanged()) {
462 iliev 1761 int chn = (*itEngineChannel)->GetSamplerChannel()->Index();
463 iliev 1108 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, chn, fxs->Id()));
464     fxs->SetInfoChanged(false);
465     }
466     }
467 iliev 793 }
468     }
469    
470 schoenebeck 1686 // check if MIDI data arrived on some engine channel
471     for (int i = 0; i < eventHandler.channelMidiListeners.size(); ++i) {
472     const EventHandler::midi_listener_entry entry =
473     eventHandler.channelMidiListeners[i];
474     VirtualMidiDevice* pMidiListener = entry.pMidiListener;
475     if (pMidiListener->NotesChanged()) {
476     for (int iNote = 0; iNote < 128; iNote++) {
477     if (pMidiListener->NoteChanged(iNote)) {
478     const bool bActive = pMidiListener->NoteIsActive(iNote);
479     LSCPServer::SendLSCPNotify(
480     LSCPEvent(
481     LSCPEvent::event_channel_midi,
482     entry.pSamplerChannel->Index(),
483     std::string(bActive ? "NOTE_ON" : "NOTE_OFF"),
484     iNote,
485     bActive ? pMidiListener->NoteOnVelocity(iNote)
486     : pMidiListener->NoteOffVelocity(iNote)
487     )
488     );
489     }
490     }
491     }
492     }
493    
494 schoenebeck 1695 // check if MIDI data arrived on some MIDI device
495     for (int i = 0; i < eventHandler.deviceMidiListeners.size(); ++i) {
496     const EventHandler::device_midi_listener_entry entry =
497     eventHandler.deviceMidiListeners[i];
498     VirtualMidiDevice* pMidiListener = entry.pMidiListener;
499     if (pMidiListener->NotesChanged()) {
500     for (int iNote = 0; iNote < 128; iNote++) {
501     if (pMidiListener->NoteChanged(iNote)) {
502     const bool bActive = pMidiListener->NoteIsActive(iNote);
503     LSCPServer::SendLSCPNotify(
504     LSCPEvent(
505     LSCPEvent::event_device_midi,
506     entry.uiDeviceID,
507     entry.pPort->GetPortNumber(),
508     std::string(bActive ? "NOTE_ON" : "NOTE_OFF"),
509     iNote,
510     bActive ? pMidiListener->NoteOnVelocity(iNote)
511     : pMidiListener->NoteOffVelocity(iNote)
512     )
513     );
514     }
515     }
516     }
517     }
518    
519 persson 2427 //Now let's deliver late notifies (if any)
520     {
521     LockGuard lock(NotifyBufferMutex);
522     for (std::map<int,String>::iterator iterNotify = bufferedNotifies.begin(); iterNotify != bufferedNotifies.end(); iterNotify++) {
523 wylder 814 #ifdef MSG_NOSIGNAL
524 persson 2427 send(iterNotify->first, iterNotify->second.c_str(), iterNotify->second.size(), MSG_NOSIGNAL);
525 wylder 814 #else
526 persson 2427 send(iterNotify->first, iterNotify->second.c_str(), iterNotify->second.size(), 0);
527 wylder 814 #endif
528 persson 2427 }
529     bufferedNotifies.clear();
530     }
531 iliev 793
532     fd_set selectSet = fdSet;
533     timeout.tv_sec = 0;
534     timeout.tv_usec = 100000;
535    
536     int retval = select(maxSessions+1, &selectSet, NULL, NULL, &timeout);
537    
538 persson 1808 if (retval == 0 || (retval == -1 && errno == EINTR))
539 senkov 198 continue; //Nothing try again
540 senkov 170 if (retval == -1) {
541     std::cerr << "LSCPServer: Socket select error." << std::endl;
542 senoner 1481 #if defined(WIN32)
543     closesocket(hSocket);
544     #else
545 senkov 170 close(hSocket);
546 senoner 1481 #endif
547 senkov 170 exit(EXIT_FAILURE);
548     }
549 schoenebeck 203
550 senkov 170 //Accept new connections now (if any)
551     if (FD_ISSET(hSocket, &selectSet)) {
552     int socket = accept(hSocket, (sockaddr*) &client, (socklen_t*) &length);
553     if (socket < 0) {
554     std::cerr << "LSCPServer: Client connection failed." << std::endl;
555     exit(EXIT_FAILURE);
556     }
557 schoenebeck 35
558 senoner 1481 #if defined(WIN32)
559     u_long nonblock_io = 1;
560     if( ioctlsocket(socket, FIONBIO, &nonblock_io) ) {
561     std::cerr << "LSCPServer: ioctlsocket: set FIONBIO failed. Error " << WSAGetLastError() << std::endl;
562     exit(EXIT_FAILURE);
563     }
564 schoenebeck 1536 #else
565 iliev 1882 struct linger linger;
566     linger.l_onoff = 1;
567     linger.l_linger = 0;
568     if(setsockopt(socket, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger))) {
569     std::cerr << "LSCPServer: Failed to set SO_LINGER\n";
570     }
571    
572 senkov 170 if (fcntl(socket, F_SETFL, O_NONBLOCK)) {
573     std::cerr << "LSCPServer: F_SETFL O_NONBLOCK failed." << std::endl;
574     exit(EXIT_FAILURE);
575     }
576 senoner 1481 #endif
577 schoenebeck 35
578 schoenebeck 210 // Parser initialization
579     yyparse_param_t yyparse_param;
580     yyparse_param.pServer = this;
581     yyparse_param.hSession = socket;
582    
583     Sessions.push_back(yyparse_param);
584 senkov 170 FD_SET(socket, &fdSet);
585     if (socket > maxSessions)
586     maxSessions = socket;
587     dmsg(1,("LSCPServer: Client connection established on socket:%d.\n", socket));
588     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Client connection established on socket", socket));
589     continue; //Maybe this was the only selected socket, better select again
590     }
591 schoenebeck 35
592 senkov 170 //Something was selected and it was not the hSocket, so it must be some command(s) coming.
593 schoenebeck 210 for (std::vector<yyparse_param_t>::iterator iter = Sessions.begin(); iter != Sessions.end(); iter++) {
594     if (FD_ISSET((*iter).hSession, &selectSet)) { //Was it this socket?
595 senkov 170 if (GetLSCPCommand(iter)) { //Have we read the entire command?
596     dmsg(3,("LSCPServer: Got command on socket %d, calling parser.\n", currentSocket));
597 schoenebeck 219 int dummy; // just a temporary hack to fulfill the restart() function prototype
598     restart(NULL, dummy); // restart the 'scanner'
599 schoenebeck 210 currentSocket = (*iter).hSession; //a hack
600 schoenebeck 1252 itCurrentSession = iter; // another hack
601 schoenebeck 475 dmsg(2,("LSCPServer: [%s]\n",bufferedCommands[currentSocket].c_str()));
602 schoenebeck 210 if ((*iter).bVerbose) { // if echo mode enabled
603     AnswerClient(bufferedCommands[currentSocket]);
604     }
605     int result = yyparse(&(*iter));
606 senkov 170 currentSocket = -1; //continuation of a hack
607 schoenebeck 1252 itCurrentSession = Sessions.end(); // hack as well
608 senkov 170 dmsg(3,("LSCPServer: Done parsing on socket %d.\n", currentSocket));
609     if (result == LSCP_QUIT) { //Was it a quit command by any chance?
610     CloseConnection(iter);
611     }
612     }
613     //socket may have been closed, iter may be invalid, get out of the loop for now.
614     //we'll be back if there is data.
615 schoenebeck 203 break;
616 senkov 170 }
617     }
618 schoenebeck 35 }
619     }
620    
621 schoenebeck 210 void LSCPServer::CloseConnection( std::vector<yyparse_param_t>::iterator iter ) {
622     int socket = (*iter).hSession;
623 senkov 170 dmsg(1,("LSCPServer: Client connection terminated on socket:%d.\n",socket));
624     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Client connection terminated on socket", socket));
625 schoenebeck 210 Sessions.erase(iter);
626 senkov 170 FD_CLR(socket, &fdSet);
627 persson 2427 {
628     LockGuard lock(SubscriptionMutex);
629     // Must unsubscribe this socket from all events (if any)
630     for (std::map< LSCPEvent::event_t, std::list<int> >::iterator iter = eventSubscriptions.begin(); iter != eventSubscriptions.end(); iter++) {
631     iter->second.remove(socket);
632     }
633     }
634     LockGuard lock(NotifyMutex);
635 senkov 170 bufferedCommands.erase(socket);
636     bufferedNotifies.erase(socket);
637 senoner 1481 #if defined(WIN32)
638     closesocket(socket);
639     #else
640 senkov 170 close(socket);
641 senoner 1481 #endif
642 senkov 170 }
643    
644 iliev 1848 void LSCPServer::CloseAllConnections() {
645     std::vector<yyparse_param_t>::iterator iter = Sessions.begin();
646     while(iter != Sessions.end()) {
647     CloseConnection(iter);
648     iter = Sessions.begin();
649     }
650     }
651    
652 senkov 360 int LSCPServer::EventSubscribers( std::list<LSCPEvent::event_t> events ) {
653     int subs = 0;
654 persson 2427 LockGuard lock(SubscriptionMutex);
655 senkov 360 for( std::list<LSCPEvent::event_t>::iterator iter = events.begin();
656     iter != events.end(); iter++)
657     {
658     subs += eventSubscriptions.count(*iter);
659     }
660     return subs;
661     }
662    
663 senkov 170 void LSCPServer::SendLSCPNotify( LSCPEvent event ) {
664 persson 2427 LockGuard lock(SubscriptionMutex);
665 senkov 170 if (eventSubscriptions.count(event.GetType()) == 0) {
666 persson 2427 // Nobody is subscribed to this event
667 senkov 170 return;
668     }
669     std::list<int>::iterator iter = eventSubscriptions[event.GetType()].begin();
670     std::list<int>::iterator end = eventSubscriptions[event.GetType()].end();
671     String notify = event.Produce();
672    
673     while (true) {
674     if (NotifyMutex.Trylock()) {
675     for(;iter != end; iter++)
676 wylder 814 #ifdef MSG_NOSIGNAL
677 iliev 707 send(*iter, notify.c_str(), notify.size(), MSG_NOSIGNAL);
678 wylder 814 #else
679     send(*iter, notify.c_str(), notify.size(), 0);
680     #endif
681 senkov 170 NotifyMutex.Unlock();
682     break;
683     } else {
684     if (NotifyBufferMutex.Trylock()) {
685     for(;iter != end; iter++)
686     bufferedNotifies[*iter] += notify;
687     NotifyBufferMutex.Unlock();
688     break;
689     }
690     }
691     }
692     }
693    
694     extern int GetLSCPCommand( void *buf, int max_size ) {
695     String command = LSCPServer::bufferedCommands[LSCPServer::currentSocket];
696     if (command.size() == 0) { //Parser wants input but we have nothing.
697     strcpy((char*) buf, "\n"); //So give it an empty command
698     return 1; //to keep it happy.
699     }
700    
701     if (max_size < command.size()) {
702     std::cerr << "getLSCPCommand: Flex buffer too small, ignoring the command." << std::endl;
703     return 0; //This will never happen
704     }
705    
706     strcpy((char*) buf, command.c_str());
707     LSCPServer::bufferedCommands.erase(LSCPServer::currentSocket);
708     return command.size();
709     }
710    
711 schoenebeck 1252 extern yyparse_param_t* GetCurrentYaccSession() {
712     return &(*itCurrentSession);
713     }
714    
715 schoenebeck 35 /**
716 senkov 170 * Will be called to try to read the command from the socket
717     * If command is read, it will return true. Otherwise false is returned.
718     * In any case the received portion (complete or incomplete) is saved into bufferedCommand map.
719     */
720 schoenebeck 210 bool LSCPServer::GetLSCPCommand( std::vector<yyparse_param_t>::iterator iter ) {
721     int socket = (*iter).hSession;
722 senkov 170 char c;
723     int i = 0;
724     while (true) {
725 senoner 1481 #if defined(WIN32)
726     int result = recv(socket, (char *)&c, 1, 0); //Read one character at a time for now
727     #else
728 senkov 170 int result = recv(socket, (void *)&c, 1, 0); //Read one character at a time for now
729 senoner 1481 #endif
730 senkov 170 if (result == 0) { //socket was selected, so 0 here means client has closed the connection
731     CloseConnection(iter);
732     break;
733     }
734     if (result == 1) {
735 schoenebeck 203 if (c == '\r')
736 senkov 170 continue; //Ignore CR
737     if (c == '\n') {
738 senkov 184 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_misc, "Received \'" + bufferedCommands[socket] + "\' on socket", socket));
739 iliev 907 bufferedCommands[socket] += "\r\n";
740 senkov 170 return true; //Complete command was read
741     }
742     bufferedCommands[socket] += c;
743     }
744 senoner 1481 #if defined(WIN32)
745     if (result == SOCKET_ERROR) {
746     int wsa_lasterror = WSAGetLastError();
747     if (wsa_lasterror == WSAEWOULDBLOCK) //Would block, try again later.
748     return false;
749 schoenebeck 1536 dmsg(2,("LSCPScanner: Socket error after recv() Error %d.\n", wsa_lasterror));
750 senoner 1481 CloseConnection(iter);
751     break;
752     }
753     #else
754 senkov 170 if (result == -1) {
755     if (errno == EAGAIN) //Would block, try again later.
756     return false;
757     switch(errno) {
758     case EBADF:
759     dmsg(2,("LSCPScanner: The argument s is an invalid descriptor.\n"));
760     break;
761     case ECONNREFUSED:
762     dmsg(2,("LSCPScanner: A remote host refused to allow the network connection (typically because it is not running the requested service).\n"));
763     break;
764     case ENOTCONN:
765     dmsg(2,("LSCPScanner: The socket is associated with a connection-oriented protocol and has not been connected (see connect(2) and accept(2)).\n"));
766     break;
767     case ENOTSOCK:
768     dmsg(2,("LSCPScanner: The argument s does not refer to a socket.\n"));
769     break;
770     case EAGAIN:
771     dmsg(2,("LSCPScanner: The socket is marked non-blocking and the receive operation would block, or a receive timeout had been set and the timeout expired before data was received.\n"));
772 schoenebeck 203 break;
773     case EINTR:
774 senkov 170 dmsg(2,("LSCPScanner: The receive was interrupted by delivery of a signal before any data were available.\n"));
775 schoenebeck 203 break;
776     case EFAULT:
777     dmsg(2,("LSCPScanner: The receive buffer pointer(s) point outside the process's address space.\n"));
778     break;
779     case EINVAL:
780     dmsg(2,("LSCPScanner: Invalid argument passed.\n"));
781     break;
782     case ENOMEM:
783     dmsg(2,("LSCPScanner: Could not allocate memory for recvmsg.\n"));
784     break;
785     default:
786     dmsg(2,("LSCPScanner: Unknown recv() error.\n"));
787     break;
788     }
789 senkov 170 CloseConnection(iter);
790     break;
791     }
792 senoner 1481 #endif
793 senkov 170 }
794     return false;
795     }
796    
797     /**
798 schoenebeck 35 * Will be called by the parser whenever it wants to send an answer to the
799     * client / frontend.
800     *
801     * @param ReturnMessage - message that will be send to the client
802     */
803     void LSCPServer::AnswerClient(String ReturnMessage) {
804     dmsg(2,("LSCPServer::AnswerClient(ReturnMessage=%s)", ReturnMessage.c_str()));
805 senkov 170 if (currentSocket != -1) {
806 persson 2427 LockGuard lock(NotifyMutex);
807 wylder 814 #ifdef MSG_NOSIGNAL
808 iliev 707 send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), MSG_NOSIGNAL);
809 wylder 814 #else
810     send(currentSocket, ReturnMessage.c_str(), ReturnMessage.size(), 0);
811     #endif
812 senkov 170 }
813 schoenebeck 35 }
814    
815 capela 143 /**
816     * Find a created audio output device index.
817     */
818     int LSCPServer::GetAudioOutputDeviceIndex ( AudioOutputDevice *pDevice )
819     {
820     // Search for the created device to get its index
821     std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
822     std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
823     for (; iter != devices.end(); iter++) {
824     if (iter->second == pDevice)
825     return iter->first;
826     }
827     // Not found.
828     return -1;
829     }
830    
831 senkov 155 /**
832     * Find a created midi input device index.
833     */
834     int LSCPServer::GetMidiInputDeviceIndex ( MidiInputDevice *pDevice )
835     {
836     // Search for the created device to get its index
837     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
838     std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
839     for (; iter != devices.end(); iter++) {
840     if (iter->second == pDevice)
841     return iter->first;
842     }
843     // Not found.
844     return -1;
845     }
846    
847 schoenebeck 123 String LSCPServer::CreateAudioOutputDevice(String Driver, std::map<String,String> Parameters) {
848     dmsg(2,("LSCPServer: CreateAudioOutputDevice(Driver=%s)\n", Driver.c_str()));
849     LSCPResultSet result;
850     try {
851     AudioOutputDevice* pDevice = pSampler->CreateAudioOutputDevice(Driver, Parameters);
852     // search for the created device to get its index
853 capela 143 int index = GetAudioOutputDeviceIndex(pDevice);
854 schoenebeck 880 if (index == -1) throw Exception("Internal error: could not find created audio output device.");
855 schoenebeck 123 result = index; // success
856     }
857 schoenebeck 880 catch (Exception e) {
858 schoenebeck 123 result.Error(e);
859     }
860     return result.Produce();
861     }
862    
863 senkov 155 String LSCPServer::CreateMidiInputDevice(String Driver, std::map<String,String> Parameters) {
864     dmsg(2,("LSCPServer: CreateMidiInputDevice(Driver=%s)\n", Driver.c_str()));
865     LSCPResultSet result;
866     try {
867     MidiInputDevice* pDevice = pSampler->CreateMidiInputDevice(Driver, Parameters);
868     // search for the created device to get its index
869     int index = GetMidiInputDeviceIndex(pDevice);
870 schoenebeck 880 if (index == -1) throw Exception("Internal error: could not find created midi input device.");
871 senkov 155 result = index; // success
872     }
873 schoenebeck 880 catch (Exception e) {
874 senkov 155 result.Error(e);
875     }
876     return result.Produce();
877     }
878    
879 schoenebeck 123 String LSCPServer::DestroyAudioOutputDevice(uint DeviceIndex) {
880     dmsg(2,("LSCPServer: DestroyAudioOutputDevice(DeviceIndex=%d)\n", DeviceIndex));
881     LSCPResultSet result;
882     try {
883     std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
884 schoenebeck 880 if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
885 schoenebeck 123 AudioOutputDevice* pDevice = devices[DeviceIndex];
886     pSampler->DestroyAudioOutputDevice(pDevice);
887     }
888 schoenebeck 880 catch (Exception e) {
889 schoenebeck 123 result.Error(e);
890     }
891     return result.Produce();
892     }
893    
894 senkov 155 String LSCPServer::DestroyMidiInputDevice(uint DeviceIndex) {
895     dmsg(2,("LSCPServer: DestroyMidiInputDevice(DeviceIndex=%d)\n", DeviceIndex));
896     LSCPResultSet result;
897     try {
898     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
899 schoenebeck 880 if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
900 senkov 155 MidiInputDevice* pDevice = devices[DeviceIndex];
901     pSampler->DestroyMidiInputDevice(pDevice);
902     }
903 schoenebeck 880 catch (Exception e) {
904 senkov 155 result.Error(e);
905     }
906     return result.Produce();
907     }
908    
909 iliev 1135 EngineChannel* LSCPServer::GetEngineChannel(uint uiSamplerChannel) {
910     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
911     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
912    
913     EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
914     if (!pEngineChannel) throw Exception("There is no engine deployed on this sampler channel yet");
915    
916 schoenebeck 1252 return pEngineChannel;
917 iliev 1135 }
918    
919 schoenebeck 35 /**
920     * Will be called by the parser to load an instrument.
921     */
922 capela 137 String LSCPServer::LoadInstrument(String Filename, uint uiInstrument, uint uiSamplerChannel, bool bBackground) {
923 schoenebeck 53 dmsg(2,("LSCPServer: LoadInstrument(Filename=%s,Instrument=%d,SamplerChannel=%d)\n", Filename.c_str(), uiInstrument, uiSamplerChannel));
924 senkov 120 LSCPResultSet result;
925 schoenebeck 53 try {
926     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
927 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
928 schoenebeck 411 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
929 schoenebeck 880 if (!pEngineChannel) throw Exception("No engine type assigned to sampler channel yet");
930 schoenebeck 223 if (!pSamplerChannel->GetAudioOutputDevice())
931 schoenebeck 880 throw Exception("No audio output device connected to sampler channel");
932 capela 137 if (bBackground) {
933 schoenebeck 947 InstrumentManager::instrument_id_t id;
934     id.FileName = Filename;
935     id.Index = uiInstrument;
936     InstrumentManager::LoadInstrumentInBackground(id, pEngineChannel);
937 capela 137 }
938 schoenebeck 392 else {
939 schoenebeck 411 // tell the engine channel which instrument to load
940     pEngineChannel->PrepareLoadInstrument(Filename.c_str(), uiInstrument);
941 schoenebeck 392 // actually start to load the instrument (blocks until completed)
942 schoenebeck 411 pEngineChannel->LoadInstrument();
943 schoenebeck 392 }
944 schoenebeck 53 }
945 schoenebeck 880 catch (Exception e) {
946 senkov 120 result.Error(e);
947 schoenebeck 53 }
948 senkov 120 return result.Produce();
949 schoenebeck 35 }
950    
951     /**
952 schoenebeck 411 * Will be called by the parser to assign a sampler engine type to a
953     * sampler channel.
954 schoenebeck 35 */
955 schoenebeck 411 String LSCPServer::SetEngineType(String EngineName, uint uiSamplerChannel) {
956 schoenebeck 705 dmsg(2,("LSCPServer: SetEngineType(EngineName=%s,uiSamplerChannel=%d)\n", EngineName.c_str(), uiSamplerChannel));
957 senkov 120 LSCPResultSet result;
958 schoenebeck 475 try {
959 schoenebeck 53 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
960 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
961 persson 2427 LockGuard lock(RTNotifyMutex);
962 schoenebeck 411 pSamplerChannel->SetEngineType(EngineName);
963 schoenebeck 705 if(HasSoloChannel()) pSamplerChannel->GetEngineChannel()->SetMute(-1);
964 schoenebeck 53 }
965 schoenebeck 880 catch (Exception e) {
966 senkov 120 result.Error(e);
967 schoenebeck 53 }
968 senkov 120 return result.Produce();
969 schoenebeck 35 }
970    
971     /**
972     * Will be called by the parser to get the amount of sampler channels.
973     */
974     String LSCPServer::GetChannels() {
975     dmsg(2,("LSCPServer: GetChannels()\n"));
976 senkov 120 LSCPResultSet result;
977     result.Add(pSampler->SamplerChannels());
978     return result.Produce();
979 schoenebeck 35 }
980    
981     /**
982 schoenebeck 209 * Will be called by the parser to get the list of sampler channels.
983     */
984     String LSCPServer::ListChannels() {
985     dmsg(2,("LSCPServer: ListChannels()\n"));
986     String list;
987     std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
988     std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
989     for (; iter != channels.end(); iter++) {
990     if (list != "") list += ",";
991     list += ToString(iter->first);
992     }
993     LSCPResultSet result;
994     result.Add(list);
995     return result.Produce();
996     }
997    
998     /**
999 schoenebeck 35 * Will be called by the parser to add a sampler channel.
1000     */
1001     String LSCPServer::AddChannel() {
1002     dmsg(2,("LSCPServer: AddChannel()\n"));
1003 persson 2427 SamplerChannel* pSamplerChannel;
1004     {
1005     LockGuard lock(RTNotifyMutex);
1006     pSamplerChannel = pSampler->AddSamplerChannel();
1007     }
1008 senkov 120 LSCPResultSet result(pSamplerChannel->Index());
1009     return result.Produce();
1010 schoenebeck 35 }
1011    
1012     /**
1013     * Will be called by the parser to remove a sampler channel.
1014     */
1015 schoenebeck 53 String LSCPServer::RemoveChannel(uint uiSamplerChannel) {
1016     dmsg(2,("LSCPServer: RemoveChannel(SamplerChannel=%d)\n", uiSamplerChannel));
1017 senkov 120 LSCPResultSet result;
1018 persson 2427 {
1019     LockGuard lock(RTNotifyMutex);
1020     pSampler->RemoveSamplerChannel(uiSamplerChannel);
1021     }
1022 senkov 120 return result.Produce();
1023 schoenebeck 35 }
1024    
1025     /**
1026 capela 527 * Will be called by the parser to get the amount of all available engines.
1027 schoenebeck 35 */
1028     String LSCPServer::GetAvailableEngines() {
1029     dmsg(2,("LSCPServer: GetAvailableEngines()\n"));
1030 schoenebeck 905 LSCPResultSet result;
1031     try {
1032     int n = EngineFactory::AvailableEngineTypes().size();
1033     result.Add(n);
1034     }
1035     catch (Exception e) {
1036     result.Error(e);
1037     }
1038 senkov 120 return result.Produce();
1039 schoenebeck 35 }
1040    
1041     /**
1042 capela 527 * Will be called by the parser to get a list of all available engines.
1043     */
1044     String LSCPServer::ListAvailableEngines() {
1045     dmsg(2,("LSCPServer: ListAvailableEngines()\n"));
1046 schoenebeck 905 LSCPResultSet result;
1047     try {
1048     String s = EngineFactory::AvailableEngineTypesAsString();
1049     result.Add(s);
1050     }
1051     catch (Exception e) {
1052     result.Error(e);
1053     }
1054 capela 527 return result.Produce();
1055     }
1056    
1057     /**
1058 schoenebeck 411 * Will be called by the parser to get descriptions for a particular
1059     * sampler engine.
1060 schoenebeck 35 */
1061     String LSCPServer::GetEngineInfo(String EngineName) {
1062     dmsg(2,("LSCPServer: GetEngineInfo(EngineName=%s)\n", EngineName.c_str()));
1063 senkov 120 LSCPResultSet result;
1064 persson 2427 {
1065     LockGuard lock(RTNotifyMutex);
1066     try {
1067     Engine* pEngine = EngineFactory::Create(EngineName);
1068     result.Add("DESCRIPTION", _escapeLscpResponse(pEngine->Description()));
1069     result.Add("VERSION", pEngine->Version());
1070     EngineFactory::Destroy(pEngine);
1071     }
1072     catch (Exception e) {
1073     result.Error(e);
1074     }
1075 schoenebeck 53 }
1076 senkov 120 return result.Produce();
1077 schoenebeck 35 }
1078    
1079     /**
1080     * Will be called by the parser to get informations about a particular
1081     * sampler channel.
1082     */
1083 schoenebeck 53 String LSCPServer::GetChannelInfo(uint uiSamplerChannel) {
1084     dmsg(2,("LSCPServer: GetChannelInfo(SamplerChannel=%d)\n", uiSamplerChannel));
1085 senkov 120 LSCPResultSet result;
1086 senkov 113 try {
1087     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1088 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1089 schoenebeck 411 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1090 schoenebeck 123
1091 senkov 117 //Defaults values
1092     String EngineName = "NONE";
1093 schoenebeck 225 float Volume = 0.0f;
1094 senkov 117 String InstrumentFileName = "NONE";
1095 senkov 376 String InstrumentName = "NONE";
1096 capela 133 int InstrumentIndex = -1;
1097     int InstrumentStatus = -1;
1098 schoenebeck 225 int AudioOutputChannels = 0;
1099     String AudioRouting;
1100 schoenebeck 705 int Mute = 0;
1101     bool Solo = false;
1102 iliev 1130 String MidiInstrumentMap = "NONE";
1103 schoenebeck 123
1104 schoenebeck 475 if (pEngineChannel) {
1105     EngineName = pEngineChannel->EngineName();
1106 schoenebeck 411 AudioOutputChannels = pEngineChannel->Channels();
1107     Volume = pEngineChannel->Volume();
1108     InstrumentStatus = pEngineChannel->InstrumentStatus();
1109     InstrumentIndex = pEngineChannel->InstrumentIndex();
1110     if (InstrumentIndex != -1) {
1111     InstrumentFileName = pEngineChannel->InstrumentFileName();
1112     InstrumentName = pEngineChannel->InstrumentName();
1113     }
1114     for (int chan = 0; chan < pEngineChannel->Channels(); chan++) {
1115 schoenebeck 225 if (AudioRouting != "") AudioRouting += ",";
1116 schoenebeck 411 AudioRouting += ToString(pEngineChannel->OutputChannel(chan));
1117 schoenebeck 225 }
1118 schoenebeck 705 Mute = pEngineChannel->GetMute();
1119     Solo = pEngineChannel->GetSolo();
1120 schoenebeck 973 if (pEngineChannel->UsesNoMidiInstrumentMap())
1121     MidiInstrumentMap = "NONE";
1122     else if (pEngineChannel->UsesDefaultMidiInstrumentMap())
1123     MidiInstrumentMap = "DEFAULT";
1124     else
1125     MidiInstrumentMap = ToString(pEngineChannel->GetMidiInstrumentMap());
1126 senkov 113 }
1127 senkov 117
1128     result.Add("ENGINE_NAME", EngineName);
1129     result.Add("VOLUME", Volume);
1130    
1131 capela 143 //Some not-so-hardcoded stuff to make GUI look good
1132     result.Add("AUDIO_OUTPUT_DEVICE", GetAudioOutputDeviceIndex(pSamplerChannel->GetAudioOutputDevice()));
1133 schoenebeck 225 result.Add("AUDIO_OUTPUT_CHANNELS", AudioOutputChannels);
1134     result.Add("AUDIO_OUTPUT_ROUTING", AudioRouting);
1135 senkov 113
1136 capela 159 result.Add("MIDI_INPUT_DEVICE", GetMidiInputDeviceIndex(pSamplerChannel->GetMidiInputDevice()));
1137     result.Add("MIDI_INPUT_PORT", pSamplerChannel->GetMidiInputPort());
1138 schoenebeck 675 if (pSamplerChannel->GetMidiInputChannel() == midi_chan_all) result.Add("MIDI_INPUT_CHANNEL", "ALL");
1139 schoenebeck 274 else result.Add("MIDI_INPUT_CHANNEL", pSamplerChannel->GetMidiInputChannel());
1140 capela 159
1141 schoenebeck 1471 // convert the filename into the correct encoding as defined for LSCP
1142     // (especially in terms of special characters -> escape sequences)
1143     if (InstrumentFileName != "NONE" && InstrumentFileName != "") {
1144     #if WIN32
1145     InstrumentFileName = Path::fromWindows(InstrumentFileName).toLscp();
1146     #else
1147     // assuming POSIX
1148     InstrumentFileName = Path::fromPosix(InstrumentFileName).toLscp();
1149     #endif
1150     }
1151    
1152     result.Add("INSTRUMENT_FILE", InstrumentFileName);
1153 senkov 117 result.Add("INSTRUMENT_NR", InstrumentIndex);
1154 schoenebeck 1399 result.Add("INSTRUMENT_NAME", _escapeLscpResponse(InstrumentName));
1155 capela 133 result.Add("INSTRUMENT_STATUS", InstrumentStatus);
1156 schoenebeck 705 result.Add("MUTE", Mute == -1 ? "MUTED_BY_SOLO" : (Mute ? "true" : "false"));
1157     result.Add("SOLO", Solo);
1158 schoenebeck 973 result.Add("MIDI_INSTRUMENT_MAP", MidiInstrumentMap);
1159 senkov 113 }
1160 schoenebeck 880 catch (Exception e) {
1161 senkov 120 result.Error(e);
1162 senkov 113 }
1163 senkov 120 return result.Produce();
1164 schoenebeck 35 }
1165    
1166     /**
1167     * Will be called by the parser to get the amount of active voices on a
1168     * particular sampler channel.
1169     */
1170 schoenebeck 53 String LSCPServer::GetVoiceCount(uint uiSamplerChannel) {
1171     dmsg(2,("LSCPServer: GetVoiceCount(SamplerChannel=%d)\n", uiSamplerChannel));
1172 senkov 120 LSCPResultSet result;
1173 schoenebeck 53 try {
1174 iliev 1771 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1175 schoenebeck 880 if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
1176 schoenebeck 411 result.Add(pEngineChannel->GetEngine()->VoiceCount());
1177 schoenebeck 53 }
1178 schoenebeck 880 catch (Exception e) {
1179 senkov 120 result.Error(e);
1180 schoenebeck 53 }
1181 senkov 120 return result.Produce();
1182 schoenebeck 35 }
1183    
1184     /**
1185     * Will be called by the parser to get the amount of active disk streams on a
1186     * particular sampler channel.
1187     */
1188 schoenebeck 53 String LSCPServer::GetStreamCount(uint uiSamplerChannel) {
1189     dmsg(2,("LSCPServer: GetStreamCount(SamplerChannel=%d)\n", uiSamplerChannel));
1190 senkov 120 LSCPResultSet result;
1191 schoenebeck 53 try {
1192 iliev 1771 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1193 schoenebeck 880 if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
1194 schoenebeck 411 result.Add(pEngineChannel->GetEngine()->DiskStreamCount());
1195 schoenebeck 53 }
1196 schoenebeck 880 catch (Exception e) {
1197 senkov 120 result.Error(e);
1198 schoenebeck 53 }
1199 senkov 120 return result.Produce();
1200 schoenebeck 35 }
1201    
1202     /**
1203     * Will be called by the parser to get the buffer fill states of all disk
1204     * streams on a particular sampler channel.
1205     */
1206 schoenebeck 53 String LSCPServer::GetBufferFill(fill_response_t ResponseType, uint uiSamplerChannel) {
1207     dmsg(2,("LSCPServer: GetBufferFill(ResponseType=%d, SamplerChannel=%d)\n", ResponseType, uiSamplerChannel));
1208 senkov 120 LSCPResultSet result;
1209 schoenebeck 53 try {
1210 iliev 1771 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1211 schoenebeck 880 if (!pEngineChannel->GetEngine()) throw Exception("No audio output device connected to sampler channel");
1212 schoenebeck 411 if (!pEngineChannel->GetEngine()->DiskStreamSupported()) result.Add("NA");
1213 senkov 129 else {
1214     switch (ResponseType) {
1215     case fill_response_bytes:
1216 schoenebeck 411 result.Add(pEngineChannel->GetEngine()->DiskStreamBufferFillBytes());
1217     break;
1218 senkov 129 case fill_response_percentage:
1219 schoenebeck 411 result.Add(pEngineChannel->GetEngine()->DiskStreamBufferFillPercentage());
1220     break;
1221 senkov 129 default:
1222 schoenebeck 880 throw Exception("Unknown fill response type");
1223 senkov 129 }
1224     }
1225 schoenebeck 53 }
1226 schoenebeck 880 catch (Exception e) {
1227 senkov 120 result.Error(e);
1228 schoenebeck 53 }
1229 senkov 120 return result.Produce();
1230 schoenebeck 35 }
1231    
1232 schoenebeck 123 String LSCPServer::GetAvailableAudioOutputDrivers() {
1233     dmsg(2,("LSCPServer: GetAvailableAudioOutputDrivers()\n"));
1234 senkov 120 LSCPResultSet result;
1235 schoenebeck 53 try {
1236 capela 527 int n = AudioOutputDeviceFactory::AvailableDrivers().size();
1237     result.Add(n);
1238     }
1239 schoenebeck 880 catch (Exception e) {
1240 capela 527 result.Error(e);
1241     }
1242     return result.Produce();
1243     }
1244    
1245     String LSCPServer::ListAvailableAudioOutputDrivers() {
1246     dmsg(2,("LSCPServer: ListAvailableAudioOutputDrivers()\n"));
1247     LSCPResultSet result;
1248     try {
1249 schoenebeck 123 String s = AudioOutputDeviceFactory::AvailableDriversAsString();
1250     result.Add(s);
1251 schoenebeck 53 }
1252 schoenebeck 880 catch (Exception e) {
1253 schoenebeck 123 result.Error(e);
1254 schoenebeck 53 }
1255 senkov 120 return result.Produce();
1256 schoenebeck 35 }
1257    
1258 senkov 155 String LSCPServer::GetAvailableMidiInputDrivers() {
1259     dmsg(2,("LSCPServer: GetAvailableMidiInputDrivers()\n"));
1260     LSCPResultSet result;
1261     try {
1262 capela 527 int n = MidiInputDeviceFactory::AvailableDrivers().size();
1263     result.Add(n);
1264     }
1265 schoenebeck 880 catch (Exception e) {
1266 capela 527 result.Error(e);
1267     }
1268     return result.Produce();
1269     }
1270    
1271     String LSCPServer::ListAvailableMidiInputDrivers() {
1272     dmsg(2,("LSCPServer: ListAvailableMidiInputDrivers()\n"));
1273     LSCPResultSet result;
1274     try {
1275 senkov 155 String s = MidiInputDeviceFactory::AvailableDriversAsString();
1276     result.Add(s);
1277     }
1278 schoenebeck 880 catch (Exception e) {
1279 senkov 155 result.Error(e);
1280     }
1281     return result.Produce();
1282     }
1283    
1284     String LSCPServer::GetMidiInputDriverInfo(String Driver) {
1285     dmsg(2,("LSCPServer: GetMidiInputDriverInfo(Driver=%s)\n",Driver.c_str()));
1286     LSCPResultSet result;
1287     try {
1288     result.Add("DESCRIPTION", MidiInputDeviceFactory::GetDriverDescription(Driver));
1289     result.Add("VERSION", MidiInputDeviceFactory::GetDriverVersion(Driver));
1290    
1291     std::map<String,DeviceCreationParameter*> parameters = MidiInputDeviceFactory::GetAvailableDriverParameters(Driver);
1292     if (parameters.size()) { // if there are parameters defined for this driver
1293     String s;
1294     std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1295     for (;iter != parameters.end(); iter++) {
1296     if (s != "") s += ",";
1297     s += iter->first;
1298 iliev 1835 delete iter->second;
1299 senkov 155 }
1300     result.Add("PARAMETERS", s);
1301     }
1302     }
1303 schoenebeck 880 catch (Exception e) {
1304 senkov 155 result.Error(e);
1305     }
1306     return result.Produce();
1307     }
1308    
1309 schoenebeck 123 String LSCPServer::GetAudioOutputDriverInfo(String Driver) {
1310     dmsg(2,("LSCPServer: GetAudioOutputDriverInfo(Driver=%s)\n",Driver.c_str()));
1311     LSCPResultSet result;
1312     try {
1313     result.Add("DESCRIPTION", AudioOutputDeviceFactory::GetDriverDescription(Driver));
1314     result.Add("VERSION", AudioOutputDeviceFactory::GetDriverVersion(Driver));
1315    
1316     std::map<String,DeviceCreationParameter*> parameters = AudioOutputDeviceFactory::GetAvailableDriverParameters(Driver);
1317     if (parameters.size()) { // if there are parameters defined for this driver
1318     String s;
1319     std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1320     for (;iter != parameters.end(); iter++) {
1321     if (s != "") s += ",";
1322     s += iter->first;
1323 iliev 1835 delete iter->second;
1324 schoenebeck 123 }
1325     result.Add("PARAMETERS", s);
1326     }
1327     }
1328 schoenebeck 880 catch (Exception e) {
1329 schoenebeck 123 result.Error(e);
1330     }
1331     return result.Produce();
1332     }
1333    
1334 senkov 155 String LSCPServer::GetMidiInputDriverParameterInfo(String Driver, String Parameter, std::map<String,String> DependencyList) {
1335 schoenebeck 226 dmsg(2,("LSCPServer: GetMidiInputDriverParameterInfo(Driver=%s,Parameter=%s,DependencyListSize=%d)\n",Driver.c_str(),Parameter.c_str(),DependencyList.size()));
1336 senkov 155 LSCPResultSet result;
1337     try {
1338     DeviceCreationParameter* pParameter = MidiInputDeviceFactory::GetDriverParameter(Driver, Parameter);
1339     result.Add("TYPE", pParameter->Type());
1340     result.Add("DESCRIPTION", pParameter->Description());
1341 schoenebeck 223 result.Add("MANDATORY", pParameter->Mandatory());
1342     result.Add("FIX", pParameter->Fix());
1343     result.Add("MULTIPLICITY", pParameter->Multiplicity());
1344 schoenebeck 226 optional<String> oDepends = pParameter->Depends();
1345     optional<String> oDefault = pParameter->Default(DependencyList);
1346     optional<String> oRangeMin = pParameter->RangeMin(DependencyList);
1347     optional<String> oRangeMax = pParameter->RangeMax(DependencyList);
1348     optional<String> oPossibilities = pParameter->Possibilities(DependencyList);
1349     if (oDepends) result.Add("DEPENDS", *oDepends);
1350     if (oDefault) result.Add("DEFAULT", *oDefault);
1351     if (oRangeMin) result.Add("RANGE_MIN", *oRangeMin);
1352     if (oRangeMax) result.Add("RANGE_MAX", *oRangeMax);
1353     if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);
1354 iliev 1835 delete pParameter;
1355 senkov 155 }
1356 schoenebeck 880 catch (Exception e) {
1357 senkov 155 result.Error(e);
1358     }
1359     return result.Produce();
1360     }
1361    
1362 schoenebeck 123 String LSCPServer::GetAudioOutputDriverParameterInfo(String Driver, String Parameter, std::map<String,String> DependencyList) {
1363 schoenebeck 226 dmsg(2,("LSCPServer: GetAudioOutputDriverParameterInfo(Driver=%s,Parameter=%s,DependencyListSize=%d)\n",Driver.c_str(),Parameter.c_str(),DependencyList.size()));
1364 schoenebeck 123 LSCPResultSet result;
1365     try {
1366     DeviceCreationParameter* pParameter = AudioOutputDeviceFactory::GetDriverParameter(Driver, Parameter);
1367     result.Add("TYPE", pParameter->Type());
1368     result.Add("DESCRIPTION", pParameter->Description());
1369 schoenebeck 223 result.Add("MANDATORY", pParameter->Mandatory());
1370     result.Add("FIX", pParameter->Fix());
1371     result.Add("MULTIPLICITY", pParameter->Multiplicity());
1372 schoenebeck 226 optional<String> oDepends = pParameter->Depends();
1373     optional<String> oDefault = pParameter->Default(DependencyList);
1374     optional<String> oRangeMin = pParameter->RangeMin(DependencyList);
1375     optional<String> oRangeMax = pParameter->RangeMax(DependencyList);
1376     optional<String> oPossibilities = pParameter->Possibilities(DependencyList);
1377     if (oDepends) result.Add("DEPENDS", *oDepends);
1378     if (oDefault) result.Add("DEFAULT", *oDefault);
1379     if (oRangeMin) result.Add("RANGE_MIN", *oRangeMin);
1380     if (oRangeMax) result.Add("RANGE_MAX", *oRangeMax);
1381     if (oPossibilities) result.Add("POSSIBILITIES", *oPossibilities);
1382 iliev 1835 delete pParameter;
1383 schoenebeck 123 }
1384 schoenebeck 880 catch (Exception e) {
1385 schoenebeck 123 result.Error(e);
1386     }
1387     return result.Produce();
1388     }
1389    
1390     String LSCPServer::GetAudioOutputDeviceCount() {
1391     dmsg(2,("LSCPServer: GetAudioOutputDeviceCount()\n"));
1392     LSCPResultSet result;
1393     try {
1394     uint count = pSampler->AudioOutputDevices();
1395 senkov 138 result.Add(count); // success
1396 schoenebeck 123 }
1397 schoenebeck 880 catch (Exception e) {
1398 schoenebeck 123 result.Error(e);
1399     }
1400     return result.Produce();
1401     }
1402    
1403 senkov 155 String LSCPServer::GetMidiInputDeviceCount() {
1404     dmsg(2,("LSCPServer: GetMidiInputDeviceCount()\n"));
1405     LSCPResultSet result;
1406     try {
1407     uint count = pSampler->MidiInputDevices();
1408     result.Add(count); // success
1409     }
1410 schoenebeck 880 catch (Exception e) {
1411 senkov 155 result.Error(e);
1412     }
1413     return result.Produce();
1414     }
1415    
1416 schoenebeck 123 String LSCPServer::GetAudioOutputDevices() {
1417     dmsg(2,("LSCPServer: GetAudioOutputDevices()\n"));
1418     LSCPResultSet result;
1419     try {
1420     String s;
1421     std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1422     std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
1423     for (; iter != devices.end(); iter++) {
1424     if (s != "") s += ",";
1425     s += ToString(iter->first);
1426     }
1427     result.Add(s);
1428     }
1429 schoenebeck 880 catch (Exception e) {
1430 schoenebeck 123 result.Error(e);
1431     }
1432     return result.Produce();
1433     }
1434    
1435 senkov 155 String LSCPServer::GetMidiInputDevices() {
1436     dmsg(2,("LSCPServer: GetMidiInputDevices()\n"));
1437     LSCPResultSet result;
1438     try {
1439     String s;
1440     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1441     std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
1442     for (; iter != devices.end(); iter++) {
1443     if (s != "") s += ",";
1444     s += ToString(iter->first);
1445     }
1446     result.Add(s);
1447     }
1448 schoenebeck 880 catch (Exception e) {
1449 senkov 155 result.Error(e);
1450     }
1451     return result.Produce();
1452     }
1453    
1454 schoenebeck 123 String LSCPServer::GetAudioOutputDeviceInfo(uint DeviceIndex) {
1455     dmsg(2,("LSCPServer: GetAudioOutputDeviceInfo(DeviceIndex=%d)\n",DeviceIndex));
1456     LSCPResultSet result;
1457     try {
1458     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1459 schoenebeck 880 if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
1460 schoenebeck 123 AudioOutputDevice* pDevice = devices[DeviceIndex];
1461 schoenebeck 221 result.Add("DRIVER", pDevice->Driver());
1462 schoenebeck 123 std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1463     std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1464     for (; iter != parameters.end(); iter++) {
1465     result.Add(iter->first, iter->second->Value());
1466     }
1467     }
1468 schoenebeck 880 catch (Exception e) {
1469 schoenebeck 123 result.Error(e);
1470     }
1471     return result.Produce();
1472     }
1473    
1474 senkov 155 String LSCPServer::GetMidiInputDeviceInfo(uint DeviceIndex) {
1475     dmsg(2,("LSCPServer: GetMidiInputDeviceInfo(DeviceIndex=%d)\n",DeviceIndex));
1476     LSCPResultSet result;
1477     try {
1478     std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1479 schoenebeck 880 if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1480 senkov 155 MidiInputDevice* pDevice = devices[DeviceIndex];
1481 schoenebeck 221 result.Add("DRIVER", pDevice->Driver());
1482 senkov 155 std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1483     std::map<String,DeviceCreationParameter*>::iterator iter = parameters.begin();
1484     for (; iter != parameters.end(); iter++) {
1485     result.Add(iter->first, iter->second->Value());
1486     }
1487     }
1488 schoenebeck 880 catch (Exception e) {
1489 senkov 155 result.Error(e);
1490     }
1491     return result.Produce();
1492     }
1493     String LSCPServer::GetMidiInputPortInfo(uint DeviceIndex, uint PortIndex) {
1494     dmsg(2,("LSCPServer: GetMidiInputPortInfo(DeviceIndex=%d, PortIndex=%d)\n",DeviceIndex, PortIndex));
1495     LSCPResultSet result;
1496     try {
1497 schoenebeck 223 // get MIDI input device
1498 senkov 155 std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1499 schoenebeck 880 if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1500 senkov 155 MidiInputDevice* pDevice = devices[DeviceIndex];
1501 schoenebeck 223
1502     // get MIDI port
1503 schoenebeck 221 MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);
1504 schoenebeck 880 if (!pMidiInputPort) throw Exception("There is no MIDI input port with index " + ToString(PortIndex) + ".");
1505 schoenebeck 223
1506     // return the values of all MIDI port parameters
1507 schoenebeck 221 std::map<String,DeviceRuntimeParameter*> parameters = pMidiInputPort->PortParameters();
1508     std::map<String,DeviceRuntimeParameter*>::iterator iter = parameters.begin();
1509 senkov 155 for (; iter != parameters.end(); iter++) {
1510     result.Add(iter->first, iter->second->Value());
1511     }
1512     }
1513 schoenebeck 880 catch (Exception e) {
1514 senkov 155 result.Error(e);
1515     }
1516     return result.Produce();
1517     }
1518    
1519 schoenebeck 123 String LSCPServer::GetAudioOutputChannelInfo(uint DeviceId, uint ChannelId) {
1520     dmsg(2,("LSCPServer: GetAudioOutputChannelInfo(DeviceId=%d,ChannelId)\n",DeviceId,ChannelId));
1521     LSCPResultSet result;
1522     try {
1523     // get audio output device
1524     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1525 schoenebeck 880 if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1526 schoenebeck 123 AudioOutputDevice* pDevice = devices[DeviceId];
1527    
1528     // get audio channel
1529     AudioChannel* pChannel = pDevice->Channel(ChannelId);
1530 schoenebeck 880 if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1531 schoenebeck 123
1532     // return the values of all audio channel parameters
1533     std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1534     std::map<String,DeviceRuntimeParameter*>::iterator iter = parameters.begin();
1535     for (; iter != parameters.end(); iter++) {
1536     result.Add(iter->first, iter->second->Value());
1537     }
1538     }
1539 schoenebeck 880 catch (Exception e) {
1540 schoenebeck 123 result.Error(e);
1541     }
1542     return result.Produce();
1543     }
1544    
1545 senkov 185 String LSCPServer::GetMidiInputPortParameterInfo(uint DeviceId, uint PortId, String ParameterName) {
1546     dmsg(2,("LSCPServer: GetMidiInputPortParameterInfo(DeviceId=%d,PortId=%d,ParameterName=%s)\n",DeviceId,PortId,ParameterName.c_str()));
1547     LSCPResultSet result;
1548     try {
1549 schoenebeck 223 // get MIDI input device
1550     std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1551 schoenebeck 880 if (!devices.count(DeviceId)) throw Exception("There is no midi input device with index " + ToString(DeviceId) + ".");
1552 schoenebeck 223 MidiInputDevice* pDevice = devices[DeviceId];
1553 senkov 185
1554 schoenebeck 221 // get midi port
1555     MidiInputPort* pPort = pDevice->GetPort(PortId);
1556 schoenebeck 880 if (!pPort) throw Exception("Midi input device does not have port " + ToString(PortId) + ".");
1557 senkov 185
1558 schoenebeck 223 // get desired port parameter
1559     std::map<String,DeviceRuntimeParameter*> parameters = pPort->PortParameters();
1560 schoenebeck 880 if (!parameters.count(ParameterName)) throw Exception("Midi port does not provide a parameter '" + ParameterName + "'.");
1561 schoenebeck 223 DeviceRuntimeParameter* pParameter = parameters[ParameterName];
1562 schoenebeck 203
1563 senkov 185 // return all fields of this audio channel parameter
1564     result.Add("TYPE", pParameter->Type());
1565     result.Add("DESCRIPTION", pParameter->Description());
1566     result.Add("FIX", pParameter->Fix());
1567     result.Add("MULTIPLICITY", pParameter->Multiplicity());
1568 schoenebeck 223 if (pParameter->RangeMin()) result.Add("RANGE_MIN", *pParameter->RangeMin());
1569     if (pParameter->RangeMax()) result.Add("RANGE_MAX", *pParameter->RangeMax());
1570     if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());
1571 senkov 185 }
1572 schoenebeck 880 catch (Exception e) {
1573 senkov 185 result.Error(e);
1574     }
1575     return result.Produce();
1576     }
1577    
1578 schoenebeck 123 String LSCPServer::GetAudioOutputChannelParameterInfo(uint DeviceId, uint ChannelId, String ParameterName) {
1579     dmsg(2,("LSCPServer: GetAudioOutputChannelParameterInfo(DeviceId=%d,ChannelId=%d,ParameterName=%s)\n",DeviceId,ChannelId,ParameterName.c_str()));
1580     LSCPResultSet result;
1581     try {
1582     // get audio output device
1583     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1584 schoenebeck 880 if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1585 schoenebeck 123 AudioOutputDevice* pDevice = devices[DeviceId];
1586    
1587     // get audio channel
1588     AudioChannel* pChannel = pDevice->Channel(ChannelId);
1589 schoenebeck 880 if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1590 schoenebeck 123
1591     // get desired audio channel parameter
1592     std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1593 schoenebeck 880 if (!parameters.count(ParameterName)) throw Exception("Audio channel does not provide a parameter '" + ParameterName + "'.");
1594 schoenebeck 123 DeviceRuntimeParameter* pParameter = parameters[ParameterName];
1595    
1596     // return all fields of this audio channel parameter
1597     result.Add("TYPE", pParameter->Type());
1598     result.Add("DESCRIPTION", pParameter->Description());
1599     result.Add("FIX", pParameter->Fix());
1600     result.Add("MULTIPLICITY", pParameter->Multiplicity());
1601 schoenebeck 223 if (pParameter->RangeMin()) result.Add("RANGE_MIN", *pParameter->RangeMin());
1602     if (pParameter->RangeMax()) result.Add("RANGE_MAX", *pParameter->RangeMax());
1603     if (pParameter->Possibilities()) result.Add("POSSIBILITIES", *pParameter->Possibilities());
1604 schoenebeck 123 }
1605 schoenebeck 880 catch (Exception e) {
1606 schoenebeck 123 result.Error(e);
1607     }
1608     return result.Produce();
1609     }
1610    
1611     String LSCPServer::SetAudioOutputChannelParameter(uint DeviceId, uint ChannelId, String ParamKey, String ParamVal) {
1612     dmsg(2,("LSCPServer: SetAudioOutputChannelParameter(DeviceId=%d,ChannelId=%d,ParamKey=%s,ParamVal=%s)\n",DeviceId,ChannelId,ParamKey.c_str(),ParamVal.c_str()));
1613     LSCPResultSet result;
1614     try {
1615     // get audio output device
1616     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1617 schoenebeck 880 if (!devices.count(DeviceId)) throw Exception("There is no audio output device with index " + ToString(DeviceId) + ".");
1618 schoenebeck 123 AudioOutputDevice* pDevice = devices[DeviceId];
1619    
1620     // get audio channel
1621     AudioChannel* pChannel = pDevice->Channel(ChannelId);
1622 schoenebeck 880 if (!pChannel) throw Exception("Audio output device does not have audio channel " + ToString(ChannelId) + ".");
1623 schoenebeck 123
1624     // get desired audio channel parameter
1625     std::map<String,DeviceRuntimeParameter*> parameters = pChannel->ChannelParameters();
1626 schoenebeck 880 if (!parameters.count(ParamKey)) throw Exception("Audio channel does not provide a parameter '" + ParamKey + "'.");
1627 schoenebeck 123 DeviceRuntimeParameter* pParameter = parameters[ParamKey];
1628    
1629     // set new channel parameter value
1630     pParameter->SetValue(ParamVal);
1631 iliev 981 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_info, DeviceId));
1632 schoenebeck 123 }
1633 schoenebeck 880 catch (Exception e) {
1634 schoenebeck 123 result.Error(e);
1635     }
1636     return result.Produce();
1637     }
1638    
1639     String LSCPServer::SetAudioOutputDeviceParameter(uint DeviceIndex, String ParamKey, String ParamVal) {
1640     dmsg(2,("LSCPServer: SetAudioOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1641     LSCPResultSet result;
1642     try {
1643     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1644 schoenebeck 880 if (!devices.count(DeviceIndex)) throw Exception("There is no audio output device with index " + ToString(DeviceIndex) + ".");
1645 schoenebeck 123 AudioOutputDevice* pDevice = devices[DeviceIndex];
1646     std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1647 schoenebeck 880 if (!parameters.count(ParamKey)) throw Exception("Audio output device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'");
1648 schoenebeck 123 parameters[ParamKey]->SetValue(ParamVal);
1649 iliev 981 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_audio_device_info, DeviceIndex));
1650 schoenebeck 123 }
1651 schoenebeck 880 catch (Exception e) {
1652 schoenebeck 123 result.Error(e);
1653     }
1654     return result.Produce();
1655     }
1656    
1657 senkov 155 String LSCPServer::SetMidiInputDeviceParameter(uint DeviceIndex, String ParamKey, String ParamVal) {
1658     dmsg(2,("LSCPServer: SetMidiOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1659     LSCPResultSet result;
1660     try {
1661     std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1662 schoenebeck 880 if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1663 senkov 155 MidiInputDevice* pDevice = devices[DeviceIndex];
1664     std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1665 schoenebeck 880 if (!parameters.count(ParamKey)) throw Exception("MIDI input device " + ToString(DeviceIndex) + " does not have a device parameter '" + ParamKey + "'");
1666 senkov 155 parameters[ParamKey]->SetValue(ParamVal);
1667 iliev 981 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_info, DeviceIndex));
1668 senkov 155 }
1669 schoenebeck 880 catch (Exception e) {
1670 senkov 155 result.Error(e);
1671     }
1672     return result.Produce();
1673     }
1674    
1675     String LSCPServer::SetMidiInputPortParameter(uint DeviceIndex, uint PortIndex, String ParamKey, String ParamVal) {
1676     dmsg(2,("LSCPServer: SetMidiOutputDeviceParameter(DeviceIndex=%d,ParamKey=%s,ParamVal=%s)\n",DeviceIndex,ParamKey.c_str(),ParamVal.c_str()));
1677     LSCPResultSet result;
1678     try {
1679 schoenebeck 223 // get MIDI input device
1680 senkov 155 std::map<uint,MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1681 schoenebeck 880 if (!devices.count(DeviceIndex)) throw Exception("There is no MIDI input device with index " + ToString(DeviceIndex) + ".");
1682 senkov 155 MidiInputDevice* pDevice = devices[DeviceIndex];
1683 schoenebeck 223
1684     // get MIDI port
1685 schoenebeck 221 MidiInputPort* pMidiInputPort = pDevice->GetPort(PortIndex);
1686 schoenebeck 880 if (!pMidiInputPort) throw Exception("There is no MIDI input port with index " + ToString(PortIndex) + ".");
1687 schoenebeck 223
1688     // set port parameter value
1689 schoenebeck 221 std::map<String,DeviceRuntimeParameter*> parameters = pMidiInputPort->PortParameters();
1690 schoenebeck 880 if (!parameters.count(ParamKey)) throw Exception("MIDI input device " + ToString(PortIndex) + " does not have a parameter '" + ParamKey + "'");
1691 senkov 155 parameters[ParamKey]->SetValue(ParamVal);
1692 iliev 981 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_midi_device_info, DeviceIndex));
1693 senkov 155 }
1694 schoenebeck 880 catch (Exception e) {
1695 senkov 155 result.Error(e);
1696     }
1697     return result.Produce();
1698     }
1699    
1700 schoenebeck 35 /**
1701     * Will be called by the parser to change the audio output channel for
1702     * playback on a particular sampler channel.
1703     */
1704 schoenebeck 123 String LSCPServer::SetAudioOutputChannel(uint ChannelAudioOutputChannel, uint AudioOutputDeviceInputChannel, uint uiSamplerChannel) {
1705     dmsg(2,("LSCPServer: SetAudioOutputChannel(ChannelAudioOutputChannel=%d, AudioOutputDeviceInputChannel=%d, SamplerChannel=%d)\n",ChannelAudioOutputChannel,AudioOutputDeviceInputChannel,uiSamplerChannel));
1706 schoenebeck 225 LSCPResultSet result;
1707     try {
1708     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1709 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1710 schoenebeck 411 EngineChannel* pEngineChannel = pSamplerChannel->GetEngineChannel();
1711 schoenebeck 880 if (!pEngineChannel) throw Exception("No engine type yet assigned to sampler channel " + ToString(uiSamplerChannel));
1712     if (!pSamplerChannel->GetAudioOutputDevice()) throw Exception("No audio output device connected to sampler channel " + ToString(uiSamplerChannel));
1713 schoenebeck 411 pEngineChannel->SetOutputChannel(ChannelAudioOutputChannel, AudioOutputDeviceInputChannel);
1714 schoenebeck 225 }
1715 schoenebeck 880 catch (Exception e) {
1716 schoenebeck 225 result.Error(e);
1717     }
1718     return result.Produce();
1719 schoenebeck 35 }
1720    
1721 capela 159 String LSCPServer::SetAudioOutputDevice(uint AudioDeviceId, uint uiSamplerChannel) {
1722     dmsg(2,("LSCPServer: SetAudiotOutputDevice(AudioDeviceId=%d, SamplerChannel=%d)\n",AudioDeviceId,uiSamplerChannel));
1723     LSCPResultSet result;
1724 persson 2427 {
1725     LockGuard lock(RTNotifyMutex);
1726     try {
1727     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1728     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1729     std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1730     if (!devices.count(AudioDeviceId)) throw Exception("There is no audio output device with index " + ToString(AudioDeviceId));
1731     AudioOutputDevice* pDevice = devices[AudioDeviceId];
1732     pSamplerChannel->SetAudioOutputDevice(pDevice);
1733     }
1734     catch (Exception e) {
1735     result.Error(e);
1736     }
1737 capela 159 }
1738     return result.Produce();
1739     }
1740    
1741 capela 143 String LSCPServer::SetAudioOutputType(String AudioOutputDriver, uint uiSamplerChannel) {
1742     dmsg(2,("LSCPServer: SetAudioOutputType(String AudioOutputDriver=%s, SamplerChannel=%d)\n",AudioOutputDriver.c_str(),uiSamplerChannel));
1743     LSCPResultSet result;
1744 persson 2427 {
1745     LockGuard lock(RTNotifyMutex);
1746     try {
1747     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1748     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1749     // Driver type name aliasing...
1750     if (AudioOutputDriver == "Alsa") AudioOutputDriver = "ALSA";
1751     if (AudioOutputDriver == "Jack") AudioOutputDriver = "JACK";
1752     // Check if there's one audio output device already created
1753     // for the intended audio driver type (AudioOutputDriver)...
1754     AudioOutputDevice *pDevice = NULL;
1755     std::map<uint, AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
1756     std::map<uint, AudioOutputDevice*>::iterator iter = devices.begin();
1757     for (; iter != devices.end(); iter++) {
1758     if ((iter->second)->Driver() == AudioOutputDriver) {
1759     pDevice = iter->second;
1760     break;
1761     }
1762 capela 143 }
1763 persson 2427 // If it doesn't exist, create a new one with default parameters...
1764     if (pDevice == NULL) {
1765     std::map<String,String> params;
1766     pDevice = pSampler->CreateAudioOutputDevice(AudioOutputDriver, params);
1767     }
1768     // Must have a device...
1769     if (pDevice == NULL)
1770     throw Exception("Internal error: could not create audio output device.");
1771     // Set it as the current channel device...
1772     pSamplerChannel->SetAudioOutputDevice(pDevice);
1773 capela 143 }
1774 persson 2427 catch (Exception e) {
1775     result.Error(e);
1776 capela 143 }
1777     }
1778     return result.Produce();
1779     }
1780    
1781 schoenebeck 2500 String LSCPServer::AddChannelMidiInput(uint uiSamplerChannel, uint MIDIDeviceId, uint MIDIPort) {
1782     dmsg(2,("LSCPServer: AddChannelMidiInput(uiSamplerChannel=%d, MIDIDeviceId=%d, MIDIPort=%d)\n",uiSamplerChannel,MIDIDeviceId,MIDIPort));
1783     LSCPResultSet result;
1784     try {
1785     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1786     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1787    
1788     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1789     if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1790     MidiInputDevice* pDevice = devices[MIDIDeviceId];
1791    
1792     MidiInputPort* pPort = pDevice->GetPort(MIDIPort);
1793     if (!pPort) throw Exception("There is no MIDI input port with index " + ToString(MIDIPort) + " on MIDI input device with index " + ToString(MIDIDeviceId));
1794    
1795     pSamplerChannel->Connect(pPort);
1796     } catch (Exception e) {
1797     result.Error(e);
1798     }
1799     return result.Produce();
1800     }
1801    
1802     String LSCPServer::RemoveChannelMidiInput(uint uiSamplerChannel) {
1803     dmsg(2,("LSCPServer: RemoveChannelMidiInput(uiSamplerChannel=%d)\n",uiSamplerChannel));
1804     LSCPResultSet result;
1805     try {
1806     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1807     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1808     pSamplerChannel->DisconnectAllMidiInputPorts();
1809     } catch (Exception e) {
1810     result.Error(e);
1811     }
1812     return result.Produce();
1813     }
1814    
1815     String LSCPServer::RemoveChannelMidiInput(uint uiSamplerChannel, uint MIDIDeviceId) {
1816     dmsg(2,("LSCPServer: RemoveChannelMidiInput(uiSamplerChannel=%d, MIDIDeviceId=%d)\n",uiSamplerChannel,MIDIDeviceId));
1817     LSCPResultSet result;
1818     try {
1819     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1820     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1821    
1822     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1823     if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1824     MidiInputDevice* pDevice = devices[MIDIDeviceId];
1825    
1826     std::vector<MidiInputPort*> vPorts = pSamplerChannel->GetMidiInputPorts();
1827     for (int i = 0; i < vPorts.size(); ++i)
1828     if (vPorts[i]->GetDevice() == pDevice)
1829     pSamplerChannel->Disconnect(vPorts[i]);
1830    
1831     } catch (Exception e) {
1832     result.Error(e);
1833     }
1834     return result.Produce();
1835     }
1836    
1837     String LSCPServer::RemoveChannelMidiInput(uint uiSamplerChannel, uint MIDIDeviceId, uint MIDIPort) {
1838     dmsg(2,("LSCPServer: RemoveChannelMidiInput(uiSamplerChannel=%d, MIDIDeviceId=%d, MIDIPort=%d)\n",uiSamplerChannel,MIDIDeviceId,MIDIPort));
1839     LSCPResultSet result;
1840     try {
1841     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1842     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1843    
1844     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1845     if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1846     MidiInputDevice* pDevice = devices[MIDIDeviceId];
1847    
1848     MidiInputPort* pPort = pDevice->GetPort(MIDIPort);
1849     if (!pPort) throw Exception("There is no MIDI input port with index " + ToString(MIDIPort) + " on MIDI input device with index " + ToString(MIDIDeviceId));
1850    
1851     pSamplerChannel->Disconnect(pPort);
1852     } catch (Exception e) {
1853     result.Error(e);
1854     }
1855     return result.Produce();
1856     }
1857    
1858     String LSCPServer::ListChannelMidiInputs(uint uiSamplerChannel) {
1859     dmsg(2,("LSCPServer: ListChannelMidiInputs(uiSamplerChannel=%d)\n",uiSamplerChannel));
1860     LSCPResultSet result;
1861     try {
1862     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1863     if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1864     std::vector<MidiInputPort*> vPorts = pSamplerChannel->GetMidiInputPorts();
1865    
1866     String s;
1867     for (int i = 0; i < vPorts.size(); ++i) {
1868     const int iDeviceID = vPorts[i]->GetDevice()->MidiInputDeviceID();
1869     const int iPortNr = vPorts[i]->GetPortNumber();
1870     if (s.size()) s += ",";
1871     s += "{" + ToString(iDeviceID) + ","
1872     + ToString(iPortNr) + "}";
1873     }
1874     result.Add(s);
1875     } catch (Exception e) {
1876     result.Error(e);
1877     }
1878     return result.Produce();
1879     }
1880    
1881 capela 159 String LSCPServer::SetMIDIInputPort(uint MIDIPort, uint uiSamplerChannel) {
1882     dmsg(2,("LSCPServer: SetMIDIInputPort(MIDIPort=%d, SamplerChannel=%d)\n",MIDIPort,uiSamplerChannel));
1883 senkov 120 LSCPResultSet result;
1884 schoenebeck 53 try {
1885     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1886 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1887 capela 159 pSamplerChannel->SetMidiInputPort(MIDIPort);
1888 schoenebeck 53 }
1889 schoenebeck 880 catch (Exception e) {
1890 senkov 120 result.Error(e);
1891 schoenebeck 53 }
1892 senkov 120 return result.Produce();
1893 schoenebeck 53 }
1894    
1895 capela 159 String LSCPServer::SetMIDIInputChannel(uint MIDIChannel, uint uiSamplerChannel) {
1896     dmsg(2,("LSCPServer: SetMIDIInputChannel(MIDIChannel=%d, SamplerChannel=%d)\n",MIDIChannel,uiSamplerChannel));
1897 senkov 120 LSCPResultSet result;
1898 senkov 68 try {
1899     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1900 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1901 schoenebeck 675 pSamplerChannel->SetMidiInputChannel((midi_chan_t) MIDIChannel);
1902 senkov 68 }
1903 schoenebeck 880 catch (Exception e) {
1904 senkov 120 result.Error(e);
1905 senkov 68 }
1906 senkov 120 return result.Produce();
1907 schoenebeck 35 }
1908    
1909 capela 159 String LSCPServer::SetMIDIInputDevice(uint MIDIDeviceId, uint uiSamplerChannel) {
1910     dmsg(2,("LSCPServer: SetMIDIInputDevice(MIDIDeviceId=%d, SamplerChannel=%d)\n",MIDIDeviceId,uiSamplerChannel));
1911 schoenebeck 123 LSCPResultSet result;
1912     try {
1913 capela 159 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1914 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1915 capela 159 std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1916 schoenebeck 880 if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1917 capela 159 MidiInputDevice* pDevice = devices[MIDIDeviceId];
1918     pSamplerChannel->SetMidiInputDevice(pDevice);
1919 schoenebeck 123 }
1920 schoenebeck 880 catch (Exception e) {
1921 schoenebeck 123 result.Error(e);
1922     }
1923     return result.Produce();
1924     }
1925    
1926 capela 159 String LSCPServer::SetMIDIInputType(String MidiInputDriver, uint uiSamplerChannel) {
1927     dmsg(2,("LSCPServer: SetMIDIInputType(String MidiInputDriver=%s, SamplerChannel=%d)\n",MidiInputDriver.c_str(),uiSamplerChannel));
1928     LSCPResultSet result;
1929     try {
1930     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1931 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1932 capela 159 // Driver type name aliasing...
1933 schoenebeck 226 if (MidiInputDriver == "Alsa") MidiInputDriver = "ALSA";
1934 capela 159 // Check if there's one MIDI input device already created
1935     // for the intended MIDI driver type (MidiInputDriver)...
1936     MidiInputDevice *pDevice = NULL;
1937     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1938     std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
1939     for (; iter != devices.end(); iter++) {
1940     if ((iter->second)->Driver() == MidiInputDriver) {
1941     pDevice = iter->second;
1942     break;
1943     }
1944     }
1945     // If it doesn't exist, create a new one with default parameters...
1946     if (pDevice == NULL) {
1947     std::map<String,String> params;
1948     pDevice = pSampler->CreateMidiInputDevice(MidiInputDriver, params);
1949     // Make it with at least one initial port.
1950     std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1951     }
1952     // Must have a device...
1953     if (pDevice == NULL)
1954 schoenebeck 880 throw Exception("Internal error: could not create MIDI input device.");
1955 capela 159 // Set it as the current channel device...
1956     pSamplerChannel->SetMidiInputDevice(pDevice);
1957     }
1958 schoenebeck 880 catch (Exception e) {
1959 capela 159 result.Error(e);
1960     }
1961     return result.Produce();
1962     }
1963    
1964 schoenebeck 35 /**
1965 capela 159 * Will be called by the parser to change the MIDI input device, port and channel on which
1966     * engine of a particular sampler channel should listen to.
1967     */
1968     String LSCPServer::SetMIDIInput(uint MIDIDeviceId, uint MIDIPort, uint MIDIChannel, uint uiSamplerChannel) {
1969     dmsg(2,("LSCPServer: SetMIDIInput(MIDIDeviceId=%d, MIDIPort=%d, MIDIChannel=%d, SamplerChannel=%d)\n", MIDIDeviceId, MIDIPort, MIDIChannel, uiSamplerChannel));
1970     LSCPResultSet result;
1971     try {
1972     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1973 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1974 capela 159 std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1975 schoenebeck 880 if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1976 capela 159 MidiInputDevice* pDevice = devices[MIDIDeviceId];
1977 schoenebeck 675 pSamplerChannel->SetMidiInput(pDevice, MIDIPort, (midi_chan_t) MIDIChannel);
1978 capela 159 }
1979 schoenebeck 880 catch (Exception e) {
1980 capela 159 result.Error(e);
1981     }
1982     return result.Produce();
1983     }
1984    
1985     /**
1986 schoenebeck 35 * Will be called by the parser to change the global volume factor on a
1987     * particular sampler channel.
1988     */
1989 schoenebeck 225 String LSCPServer::SetVolume(double dVolume, uint uiSamplerChannel) {
1990     dmsg(2,("LSCPServer: SetVolume(Volume=%f, SamplerChannel=%d)\n", dVolume, uiSamplerChannel));
1991 senkov 120 LSCPResultSet result;
1992 schoenebeck 53 try {
1993 iliev 1771 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1994 schoenebeck 411 pEngineChannel->Volume(dVolume);
1995 schoenebeck 53 }
1996 schoenebeck 880 catch (Exception e) {
1997 senkov 120 result.Error(e);
1998 schoenebeck 53 }
1999 senkov 120 return result.Produce();
2000 schoenebeck 35 }
2001    
2002     /**
2003 schoenebeck 705 * Will be called by the parser to mute/unmute particular sampler channel.
2004     */
2005     String LSCPServer::SetChannelMute(bool bMute, uint uiSamplerChannel) {
2006     dmsg(2,("LSCPServer: SetChannelMute(bMute=%d,uiSamplerChannel=%d)\n",bMute,uiSamplerChannel));
2007     LSCPResultSet result;
2008     try {
2009 iliev 1771 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2010 schoenebeck 705
2011     if(!bMute) pEngineChannel->SetMute((HasSoloChannel() && !pEngineChannel->GetSolo()) ? -1 : 0);
2012     else pEngineChannel->SetMute(1);
2013 schoenebeck 880 } catch (Exception e) {
2014 schoenebeck 705 result.Error(e);
2015     }
2016     return result.Produce();
2017     }
2018    
2019     /**
2020     * Will be called by the parser to solo particular sampler channel.
2021     */
2022     String LSCPServer::SetChannelSolo(bool bSolo, uint uiSamplerChannel) {
2023     dmsg(2,("LSCPServer: SetChannelSolo(bSolo=%d,uiSamplerChannel=%d)\n",bSolo,uiSamplerChannel));
2024     LSCPResultSet result;
2025     try {
2026 iliev 1771 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2027 schoenebeck 705
2028     bool oldSolo = pEngineChannel->GetSolo();
2029     bool hadSoloChannel = HasSoloChannel();
2030 schoenebeck 1009
2031 schoenebeck 705 pEngineChannel->SetSolo(bSolo);
2032 schoenebeck 1009
2033 schoenebeck 705 if(!oldSolo && bSolo) {
2034     if(pEngineChannel->GetMute() == -1) pEngineChannel->SetMute(0);
2035     if(!hadSoloChannel) MuteNonSoloChannels();
2036     }
2037 schoenebeck 1009
2038 schoenebeck 705 if(oldSolo && !bSolo) {
2039     if(!HasSoloChannel()) UnmuteChannels();
2040     else if(!pEngineChannel->GetMute()) pEngineChannel->SetMute(-1);
2041     }
2042 schoenebeck 880 } catch (Exception e) {
2043 schoenebeck 705 result.Error(e);
2044     }
2045     return result.Produce();
2046     }
2047    
2048     /**
2049     * Determines whether there is at least one solo channel in the channel list.
2050     *
2051     * @returns true if there is at least one solo channel in the channel list,
2052     * false otherwise.
2053     */
2054     bool LSCPServer::HasSoloChannel() {
2055     std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
2056     std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
2057     for (; iter != channels.end(); iter++) {
2058     EngineChannel* c = iter->second->GetEngineChannel();
2059     if(c && c->GetSolo()) return true;
2060     }
2061    
2062     return false;
2063     }
2064    
2065     /**
2066     * Mutes all unmuted non-solo channels. Notice that the channels are muted
2067     * with -1 which indicates that they are muted because of the presence
2068     * of a solo channel(s). Channels muted with -1 will be automatically unmuted
2069     * when there are no solo channels left.
2070     */
2071     void LSCPServer::MuteNonSoloChannels() {
2072     dmsg(2,("LSCPServer: MuteNonSoloChannels()\n"));
2073     std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
2074     std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
2075     for (; iter != channels.end(); iter++) {
2076     EngineChannel* c = iter->second->GetEngineChannel();
2077     if(c && !c->GetSolo() && !c->GetMute()) c->SetMute(-1);
2078     }
2079     }
2080    
2081     /**
2082     * Unmutes all channels that are muted because of the presence
2083     * of a solo channel(s).
2084     */
2085     void LSCPServer::UnmuteChannels() {
2086     dmsg(2,("LSCPServer: UnmuteChannels()\n"));
2087     std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
2088     std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
2089     for (; iter != channels.end(); iter++) {
2090     EngineChannel* c = iter->second->GetEngineChannel();
2091     if(c && c->GetMute() == -1) c->SetMute(0);
2092     }
2093     }
2094    
2095 schoenebeck 1047 String LSCPServer::AddOrReplaceMIDIInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg, String EngineType, String InstrumentFile, uint InstrumentIndex, float Volume, MidiInstrumentMapper::mode_t LoadMode, String Name, bool bModal) {
2096 schoenebeck 947 dmsg(2,("LSCPServer: AddOrReplaceMIDIInstrumentMapping()\n"));
2097    
2098     midi_prog_index_t idx;
2099 schoenebeck 973 idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
2100     idx.midi_bank_lsb = MidiBank & 0x7f;
2101 schoenebeck 947 idx.midi_prog = MidiProg;
2102    
2103     MidiInstrumentMapper::entry_t entry;
2104     entry.EngineName = EngineType;
2105     entry.InstrumentFile = InstrumentFile;
2106     entry.InstrumentIndex = InstrumentIndex;
2107     entry.LoadMode = LoadMode;
2108     entry.Volume = Volume;
2109     entry.Name = Name;
2110    
2111     LSCPResultSet result;
2112     try {
2113 schoenebeck 1047 // PERSISTENT mapping commands might block for a long time, so in
2114     // that case we add/replace the mapping in another thread in case
2115     // the NON_MODAL argument was supplied, non persistent mappings
2116     // should return immediately, so we don't need to do that for them
2117     bool bInBackground = (entry.LoadMode == MidiInstrumentMapper::PERSISTENT && !bModal);
2118 schoenebeck 973 MidiInstrumentMapper::AddOrReplaceEntry(MidiMapID, idx, entry, bInBackground);
2119 schoenebeck 947 } catch (Exception e) {
2120     result.Error(e);
2121     }
2122     return result.Produce();
2123     }
2124    
2125 schoenebeck 973 String LSCPServer::RemoveMIDIInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg) {
2126 schoenebeck 947 dmsg(2,("LSCPServer: RemoveMIDIInstrumentMapping()\n"));
2127    
2128     midi_prog_index_t idx;
2129 schoenebeck 973 idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
2130     idx.midi_bank_lsb = MidiBank & 0x7f;
2131 schoenebeck 947 idx.midi_prog = MidiProg;
2132    
2133     LSCPResultSet result;
2134     try {
2135 schoenebeck 973 MidiInstrumentMapper::RemoveEntry(MidiMapID, idx);
2136 schoenebeck 947 } catch (Exception e) {
2137     result.Error(e);
2138     }
2139     return result.Produce();
2140     }
2141    
2142 schoenebeck 973 String LSCPServer::GetMidiInstrumentMappings(uint MidiMapID) {
2143     dmsg(2,("LSCPServer: GetMidiInstrumentMappings()\n"));
2144 schoenebeck 947 LSCPResultSet result;
2145 schoenebeck 973 try {
2146 iliev 1763 result.Add(MidiInstrumentMapper::GetInstrumentCount(MidiMapID));
2147 schoenebeck 973 } catch (Exception e) {
2148     result.Error(e);
2149     }
2150 schoenebeck 947 return result.Produce();
2151     }
2152    
2153 schoenebeck 973
2154     String LSCPServer::GetAllMidiInstrumentMappings() {
2155     dmsg(2,("LSCPServer: GetAllMidiInstrumentMappings()\n"));
2156     LSCPResultSet result;
2157 iliev 1763 try {
2158     result.Add(MidiInstrumentMapper::GetInstrumentCount());
2159     } catch (Exception e) {
2160     result.Error(e);
2161 schoenebeck 973 }
2162     return result.Produce();
2163     }
2164    
2165     String LSCPServer::GetMidiInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg) {
2166 schoenebeck 947 dmsg(2,("LSCPServer: GetMidiIstrumentMapping()\n"));
2167     LSCPResultSet result;
2168     try {
2169 iliev 1763 MidiInstrumentMapper::entry_t entry = MidiInstrumentMapper::GetEntry(MidiMapID, MidiBank, MidiProg);
2170     // convert the filename into the correct encoding as defined for LSCP
2171     // (especially in terms of special characters -> escape sequences)
2172 schoenebeck 1471 #if WIN32
2173 iliev 1763 const String instrumentFileName = Path::fromWindows(entry.InstrumentFile).toLscp();
2174 schoenebeck 1471 #else
2175 iliev 1763 // assuming POSIX
2176     const String instrumentFileName = Path::fromPosix(entry.InstrumentFile).toLscp();
2177 schoenebeck 1471 #endif
2178    
2179 iliev 1763 result.Add("NAME", _escapeLscpResponse(entry.Name));
2180     result.Add("ENGINE_NAME", entry.EngineName);
2181     result.Add("INSTRUMENT_FILE", instrumentFileName);
2182     result.Add("INSTRUMENT_NR", (int) entry.InstrumentIndex);
2183     String instrumentName;
2184     Engine* pEngine = EngineFactory::Create(entry.EngineName);
2185     if (pEngine) {
2186     if (pEngine->GetInstrumentManager()) {
2187     InstrumentManager::instrument_id_t instrID;
2188     instrID.FileName = entry.InstrumentFile;
2189     instrID.Index = entry.InstrumentIndex;
2190     instrumentName = pEngine->GetInstrumentManager()->GetInstrumentName(instrID);
2191 schoenebeck 947 }
2192 iliev 1763 EngineFactory::Destroy(pEngine);
2193 schoenebeck 947 }
2194 iliev 1763 result.Add("INSTRUMENT_NAME", _escapeLscpResponse(instrumentName));
2195     switch (entry.LoadMode) {
2196     case MidiInstrumentMapper::ON_DEMAND:
2197     result.Add("LOAD_MODE", "ON_DEMAND");
2198     break;
2199     case MidiInstrumentMapper::ON_DEMAND_HOLD:
2200     result.Add("LOAD_MODE", "ON_DEMAND_HOLD");
2201     break;
2202     case MidiInstrumentMapper::PERSISTENT:
2203     result.Add("LOAD_MODE", "PERSISTENT");
2204     break;
2205     default:
2206     throw Exception("entry reflects invalid LOAD_MODE, consider this as a bug!");
2207     }
2208     result.Add("VOLUME", entry.Volume);
2209 schoenebeck 947 } catch (Exception e) {
2210     result.Error(e);
2211     }
2212     return result.Produce();
2213     }
2214    
2215 schoenebeck 973 String LSCPServer::ListMidiInstrumentMappings(uint MidiMapID) {
2216     dmsg(2,("LSCPServer: ListMidiInstrumentMappings()\n"));
2217 schoenebeck 947 LSCPResultSet result;
2218     try {
2219     String s;
2220 schoenebeck 973 std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(MidiMapID);
2221 schoenebeck 947 std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin();
2222     for (; iter != mappings.end(); iter++) {
2223     if (s.size()) s += ",";
2224 schoenebeck 973 s += "{" + ToString(MidiMapID) + ","
2225 schoenebeck 1007 + ToString((int(iter->first.midi_bank_msb) << 7) | int(iter->first.midi_bank_lsb)) + ","
2226 schoenebeck 973 + ToString(int(iter->first.midi_prog)) + "}";
2227 schoenebeck 947 }
2228     result.Add(s);
2229     } catch (Exception e) {
2230     result.Error(e);
2231     }
2232     return result.Produce();
2233     }
2234    
2235 schoenebeck 973 String LSCPServer::ListAllMidiInstrumentMappings() {
2236     dmsg(2,("LSCPServer: ListAllMidiInstrumentMappings()\n"));
2237     LSCPResultSet result;
2238     try {
2239     std::vector<int> maps = MidiInstrumentMapper::Maps();
2240     String s;
2241     for (int i = 0; i < maps.size(); i++) {
2242     std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(maps[i]);
2243     std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin();
2244     for (; iter != mappings.end(); iter++) {
2245     if (s.size()) s += ",";
2246     s += "{" + ToString(maps[i]) + ","
2247 schoenebeck 1009 + ToString((int(iter->first.midi_bank_msb) << 7) | int(iter->first.midi_bank_lsb)) + ","
2248 schoenebeck 973 + ToString(int(iter->first.midi_prog)) + "}";
2249     }
2250     }
2251     result.Add(s);
2252     } catch (Exception e) {
2253     result.Error(e);
2254     }
2255     return result.Produce();
2256     }
2257    
2258     String LSCPServer::ClearMidiInstrumentMappings(uint MidiMapID) {
2259 schoenebeck 947 dmsg(2,("LSCPServer: ClearMidiInstrumentMappings()\n"));
2260     LSCPResultSet result;
2261     try {
2262 schoenebeck 973 MidiInstrumentMapper::RemoveAllEntries(MidiMapID);
2263 schoenebeck 947 } catch (Exception e) {
2264     result.Error(e);
2265     }
2266     return result.Produce();
2267     }
2268    
2269 schoenebeck 973 String LSCPServer::ClearAllMidiInstrumentMappings() {
2270     dmsg(2,("LSCPServer: ClearAllMidiInstrumentMappings()\n"));
2271     LSCPResultSet result;
2272     try {
2273     std::vector<int> maps = MidiInstrumentMapper::Maps();
2274     for (int i = 0; i < maps.size(); i++)
2275     MidiInstrumentMapper::RemoveAllEntries(maps[i]);
2276     } catch (Exception e) {
2277     result.Error(e);
2278     }
2279     return result.Produce();
2280     }
2281    
2282     String LSCPServer::AddMidiInstrumentMap(String MapName) {
2283     dmsg(2,("LSCPServer: AddMidiInstrumentMap()\n"));
2284     LSCPResultSet result;
2285     try {
2286     int MapID = MidiInstrumentMapper::AddMap(MapName);
2287     result = LSCPResultSet(MapID);
2288     } catch (Exception e) {
2289     result.Error(e);
2290     }
2291     return result.Produce();
2292     }
2293    
2294     String LSCPServer::RemoveMidiInstrumentMap(uint MidiMapID) {
2295     dmsg(2,("LSCPServer: RemoveMidiInstrumentMap()\n"));
2296     LSCPResultSet result;
2297     try {
2298     MidiInstrumentMapper::RemoveMap(MidiMapID);
2299     } catch (Exception e) {
2300     result.Error(e);
2301     }
2302     return result.Produce();
2303     }
2304    
2305     String LSCPServer::RemoveAllMidiInstrumentMaps() {
2306     dmsg(2,("LSCPServer: RemoveAllMidiInstrumentMaps()\n"));
2307     LSCPResultSet result;
2308     try {
2309     MidiInstrumentMapper::RemoveAllMaps();
2310     } catch (Exception e) {
2311     result.Error(e);
2312     }
2313     return result.Produce();
2314     }
2315    
2316     String LSCPServer::GetMidiInstrumentMaps() {
2317     dmsg(2,("LSCPServer: GetMidiInstrumentMaps()\n"));
2318     LSCPResultSet result;
2319     try {
2320     result.Add(MidiInstrumentMapper::Maps().size());
2321     } catch (Exception e) {
2322     result.Error(e);
2323     }
2324     return result.Produce();
2325     }
2326    
2327     String LSCPServer::ListMidiInstrumentMaps() {
2328     dmsg(2,("LSCPServer: ListMidiInstrumentMaps()\n"));
2329     LSCPResultSet result;
2330     try {
2331     std::vector<int> maps = MidiInstrumentMapper::Maps();
2332     String sList;
2333     for (int i = 0; i < maps.size(); i++) {
2334     if (sList != "") sList += ",";
2335     sList += ToString(maps[i]);
2336     }
2337     result.Add(sList);
2338     } catch (Exception e) {
2339     result.Error(e);
2340     }
2341     return result.Produce();
2342     }
2343    
2344     String LSCPServer::GetMidiInstrumentMap(uint MidiMapID) {
2345     dmsg(2,("LSCPServer: GetMidiInstrumentMap()\n"));
2346     LSCPResultSet result;
2347     try {
2348 schoenebeck 1399 result.Add("NAME", _escapeLscpResponse(MidiInstrumentMapper::MapName(MidiMapID)));
2349 iliev 1135 result.Add("DEFAULT", MidiInstrumentMapper::GetDefaultMap() == MidiMapID);
2350 schoenebeck 973 } catch (Exception e) {
2351     result.Error(e);
2352     }
2353     return result.Produce();
2354     }
2355    
2356     String LSCPServer::SetMidiInstrumentMapName(uint MidiMapID, String NewName) {
2357     dmsg(2,("LSCPServer: SetMidiInstrumentMapName()\n"));
2358     LSCPResultSet result;
2359     try {
2360     MidiInstrumentMapper::RenameMap(MidiMapID, NewName);
2361     } catch (Exception e) {
2362     result.Error(e);
2363     }
2364     return result.Produce();
2365     }
2366    
2367 schoenebeck 705 /**
2368 schoenebeck 973 * Set the MIDI instrument map the given sampler channel shall use for
2369     * handling MIDI program change messages. There are the following two
2370     * special (negative) values:
2371     *
2372     * - (-1) : set to NONE (ignore program changes)
2373     * - (-2) : set to DEFAULT map
2374     */
2375     String LSCPServer::SetChannelMap(uint uiSamplerChannel, int MidiMapID) {
2376     dmsg(2,("LSCPServer: SetChannelMap()\n"));
2377     LSCPResultSet result;
2378     try {
2379 iliev 1771 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2380 schoenebeck 973
2381     if (MidiMapID == -1) pEngineChannel->SetMidiInstrumentMapToNone();
2382     else if (MidiMapID == -2) pEngineChannel->SetMidiInstrumentMapToDefault();
2383     else pEngineChannel->SetMidiInstrumentMap(MidiMapID);
2384     } catch (Exception e) {
2385     result.Error(e);
2386     }
2387     return result.Produce();
2388     }
2389    
2390 schoenebeck 1001 String LSCPServer::CreateFxSend(uint uiSamplerChannel, uint MidiCtrl, String Name) {
2391     dmsg(2,("LSCPServer: CreateFxSend()\n"));
2392     LSCPResultSet result;
2393     try {
2394 iliev 1135 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2395 schoenebeck 1252
2396 schoenebeck 1001 FxSend* pFxSend = pEngineChannel->AddFxSend(MidiCtrl, Name);
2397     if (!pFxSend) throw Exception("Could not add FxSend, don't ask, I don't know why (probably a bug)");
2398    
2399     result = LSCPResultSet(pFxSend->Id()); // success
2400     } catch (Exception e) {
2401     result.Error(e);
2402     }
2403     return result.Produce();
2404     }
2405    
2406     String LSCPServer::DestroyFxSend(uint uiSamplerChannel, uint FxSendID) {
2407     dmsg(2,("LSCPServer: DestroyFxSend()\n"));
2408     LSCPResultSet result;
2409     try {
2410 iliev 1135 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2411 schoenebeck 1001
2412     FxSend* pFxSend = NULL;
2413     for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2414     if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
2415     pFxSend = pEngineChannel->GetFxSend(i);
2416     break;
2417     }
2418     }
2419     if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
2420     pEngineChannel->RemoveFxSend(pFxSend);
2421     } catch (Exception e) {
2422     result.Error(e);
2423     }
2424     return result.Produce();
2425     }
2426    
2427     String LSCPServer::GetFxSends(uint uiSamplerChannel) {
2428     dmsg(2,("LSCPServer: GetFxSends()\n"));
2429     LSCPResultSet result;
2430     try {
2431 iliev 1135 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2432 schoenebeck 1001
2433     result.Add(pEngineChannel->GetFxSendCount());
2434     } catch (Exception e) {
2435     result.Error(e);
2436     }
2437     return result.Produce();
2438     }
2439    
2440     String LSCPServer::ListFxSends(uint uiSamplerChannel) {
2441     dmsg(2,("LSCPServer: ListFxSends()\n"));
2442     LSCPResultSet result;
2443     String list;
2444     try {
2445 iliev 1135 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2446 schoenebeck 1001
2447     for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2448     FxSend* pFxSend = pEngineChannel->GetFxSend(i);
2449     if (list != "") list += ",";
2450     list += ToString(pFxSend->Id());
2451     }
2452     result.Add(list);
2453     } catch (Exception e) {
2454     result.Error(e);
2455     }
2456     return result.Produce();
2457     }
2458    
2459 iliev 1135 FxSend* LSCPServer::GetFxSend(uint uiSamplerChannel, uint FxSendID) {
2460     EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2461    
2462     FxSend* pFxSend = NULL;
2463     for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2464     if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
2465     pFxSend = pEngineChannel->GetFxSend(i);
2466     break;
2467     }
2468     }
2469     if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
2470     return pFxSend;
2471     }
2472    
2473 schoenebeck 1001 String LSCPServer::GetFxSendInfo(uint uiSamplerChannel, uint FxSendID) {
2474     dmsg(2,("LSCPServer: GetFxSendInfo()\n"));
2475     LSCPResultSet result;
2476     try {
2477 iliev 1135 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2478     FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2479 schoenebeck 1252
2480 schoenebeck 1001 // gather audio routing informations
2481     String AudioRouting;
2482     for (int chan = 0; chan < pEngineChannel->Channels(); chan++) {
2483     if (AudioRouting != "") AudioRouting += ",";
2484     AudioRouting += ToString(pFxSend->DestinationChannel(chan));
2485     }
2486    
2487 schoenebeck 2137 const String sEffectRouting =
2488     (pFxSend->DestinationEffectChain() >= 0 && pFxSend->DestinationEffectChainPosition() >= 0)
2489     ? ToString(pFxSend->DestinationEffectChain()) + "," + ToString(pFxSend->DestinationEffectChainPosition())
2490     : "NONE";
2491    
2492 schoenebeck 1001 // success
2493 schoenebeck 1399 result.Add("NAME", _escapeLscpResponse(pFxSend->Name()));
2494 schoenebeck 1026 result.Add("MIDI_CONTROLLER", pFxSend->MidiController());
2495     result.Add("LEVEL", ToString(pFxSend->Level()));
2496 schoenebeck 1001 result.Add("AUDIO_OUTPUT_ROUTING", AudioRouting);
2497 schoenebeck 2140 result.Add("EFFECT", sEffectRouting);
2498 schoenebeck 1001 } catch (Exception e) {
2499     result.Error(e);
2500     }
2501     return result.Produce();
2502     }
2503    
2504 iliev 1135 String LSCPServer::SetFxSendName(uint uiSamplerChannel, uint FxSendID, String Name) {
2505     dmsg(2,("LSCPServer: SetFxSendName()\n"));
2506     LSCPResultSet result;
2507     try {
2508     FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2509    
2510     pFxSend->SetName(Name);
2511     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2512     } catch (Exception e) {
2513     result.Error(e);
2514     }
2515     return result.Produce();
2516     }
2517    
2518 schoenebeck 1001 String LSCPServer::SetFxSendAudioOutputChannel(uint uiSamplerChannel, uint FxSendID, uint FxSendChannel, uint DeviceChannel) {
2519     dmsg(2,("LSCPServer: SetFxSendAudioOutputChannel()\n"));
2520     LSCPResultSet result;
2521     try {
2522 iliev 1135 FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2523 schoenebeck 1001
2524     pFxSend->SetDestinationChannel(FxSendChannel, DeviceChannel);
2525 iliev 1108 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2526 schoenebeck 1001 } catch (Exception e) {
2527     result.Error(e);
2528     }
2529     return result.Produce();
2530     }
2531    
2532 schoenebeck 1026 String LSCPServer::SetFxSendMidiController(uint uiSamplerChannel, uint FxSendID, uint MidiController) {
2533     dmsg(2,("LSCPServer: SetFxSendMidiController()\n"));
2534     LSCPResultSet result;
2535     try {
2536 iliev 1135 FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2537 schoenebeck 1026
2538     pFxSend->SetMidiController(MidiController);
2539 iliev 1108 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2540 schoenebeck 1026 } catch (Exception e) {
2541     result.Error(e);
2542     }
2543     return result.Produce();
2544     }
2545    
2546     String LSCPServer::SetFxSendLevel(uint uiSamplerChannel, uint FxSendID, double dLevel) {
2547     dmsg(2,("LSCPServer: SetFxSendLevel()\n"));
2548     LSCPResultSet result;
2549     try {
2550 iliev 1135 FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2551 schoenebeck 1026
2552     pFxSend->SetLevel((float)dLevel);
2553 iliev 1108 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2554 schoenebeck 1026 } catch (Exception e) {
2555     result.Error(e);
2556     }
2557     return result.Produce();
2558     }
2559    
2560 schoenebeck 2137 String LSCPServer::SetFxSendEffect(uint uiSamplerChannel, uint FxSendID, int iSendEffectChain, int iEffectChainPosition) {
2561     dmsg(2,("LSCPServer: SetFxSendEffect(%d,%d)\n", iSendEffectChain, iEffectChainPosition));
2562     LSCPResultSet result;
2563     try {
2564     FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2565    
2566     pFxSend->SetDestinationEffect(iSendEffectChain, iEffectChainPosition);
2567     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2568     } catch (Exception e) {
2569     result.Error(e);
2570     }
2571     return result.Produce();
2572     }
2573    
2574 schoenebeck 2135 String LSCPServer::GetAvailableEffects() {
2575     dmsg(2,("LSCPServer: GetAvailableEffects()\n"));
2576     LSCPResultSet result;
2577     try {
2578     int n = EffectFactory::AvailableEffectsCount();
2579     result.Add(n);
2580     }
2581     catch (Exception e) {
2582     result.Error(e);
2583     }
2584     return result.Produce();
2585     }
2586    
2587     String LSCPServer::ListAvailableEffects() {
2588     dmsg(2,("LSCPServer: ListAvailableEffects()\n"));
2589     LSCPResultSet result;
2590     String list;
2591     try {
2592     //FIXME: for now we simply enumerate from 0 .. EffectFactory::AvailableEffectsCount() here, in future we should use unique IDs for effects during the whole sampler session. This issue comes into game when the user forces a reload of available effect plugins
2593     int n = EffectFactory::AvailableEffectsCount();
2594     for (int i = 0; i < n; i++) {
2595     if (i) list += ",";
2596     list += ToString(i);
2597     }
2598     }
2599     catch (Exception e) {
2600     result.Error(e);
2601     }
2602     result.Add(list);
2603     return result.Produce();
2604     }
2605    
2606     String LSCPServer::GetEffectInfo(int iEffectIndex) {
2607     dmsg(2,("LSCPServer: GetEffectInfo(%d)\n", iEffectIndex));
2608     LSCPResultSet result;
2609     try {
2610     EffectInfo* pEffectInfo = EffectFactory::GetEffectInfo(iEffectIndex);
2611     if (!pEffectInfo)
2612     throw Exception("There is no effect with index " + ToString(iEffectIndex));
2613    
2614     // convert the filename into the correct encoding as defined for LSCP
2615     // (especially in terms of special characters -> escape sequences)
2616     #if WIN32
2617     const String dllFileName = Path::fromWindows(pEffectInfo->Module()).toLscp();
2618     #else
2619     // assuming POSIX
2620     const String dllFileName = Path::fromPosix(pEffectInfo->Module()).toLscp();
2621     #endif
2622    
2623     result.Add("SYSTEM", pEffectInfo->EffectSystem());
2624     result.Add("MODULE", dllFileName);
2625     result.Add("NAME", _escapeLscpResponse(pEffectInfo->Name()));
2626     result.Add("DESCRIPTION", _escapeLscpResponse(pEffectInfo->Description()));
2627     }
2628     catch (Exception e) {
2629     result.Error(e);
2630     }
2631     return result.Produce();
2632     }
2633    
2634 schoenebeck 2137 String LSCPServer::GetEffectInstanceInfo(int iEffectInstance) {
2635     dmsg(2,("LSCPServer: GetEffectInstanceInfo(%d)\n", iEffectInstance));
2636 schoenebeck 2135 LSCPResultSet result;
2637     try {
2638 schoenebeck 2137 Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2639 schoenebeck 2135 if (!pEffect)
2640 schoenebeck 2137 throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2641 schoenebeck 2135
2642     EffectInfo* pEffectInfo = pEffect->GetEffectInfo();
2643    
2644     // convert the filename into the correct encoding as defined for LSCP
2645     // (especially in terms of special characters -> escape sequences)
2646     #if WIN32
2647     const String dllFileName = Path::fromWindows(pEffectInfo->Module()).toLscp();
2648     #else
2649     // assuming POSIX
2650     const String dllFileName = Path::fromPosix(pEffectInfo->Module()).toLscp();
2651     #endif
2652    
2653     result.Add("SYSTEM", pEffectInfo->EffectSystem());
2654     result.Add("MODULE", dllFileName);
2655     result.Add("NAME", _escapeLscpResponse(pEffectInfo->Name()));
2656     result.Add("DESCRIPTION", _escapeLscpResponse(pEffectInfo->Description()));
2657     result.Add("INPUT_CONTROLS", ToString(pEffect->InputControlCount()));
2658     }
2659     catch (Exception e) {
2660     result.Error(e);
2661     }
2662     return result.Produce();
2663     }
2664    
2665 schoenebeck 2137 String LSCPServer::GetEffectInstanceInputControlInfo(int iEffectInstance, int iInputControlIndex) {
2666     dmsg(2,("LSCPServer: GetEffectInstanceInputControlInfo(%d,%d)\n", iEffectInstance, iInputControlIndex));
2667 schoenebeck 2135 LSCPResultSet result;
2668     try {
2669 schoenebeck 2137 Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2670 schoenebeck 2135 if (!pEffect)
2671 schoenebeck 2137 throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2672 schoenebeck 2135
2673     EffectControl* pEffectControl = pEffect->InputControl(iInputControlIndex);
2674     if (!pEffectControl)
2675     throw Exception(
2676 schoenebeck 2137 "Effect instance " + ToString(iEffectInstance) +
2677 schoenebeck 2135 " does not have an input control with index " +
2678     ToString(iInputControlIndex)
2679     );
2680    
2681     result.Add("DESCRIPTION", _escapeLscpResponse(pEffectControl->Description()));
2682     result.Add("VALUE", pEffectControl->Value());
2683     if (pEffectControl->MinValue())
2684     result.Add("RANGE_MIN", *pEffectControl->MinValue());
2685     if (pEffectControl->MaxValue())
2686     result.Add("RANGE_MAX", *pEffectControl->MaxValue());
2687     if (!pEffectControl->Possibilities().empty())
2688     result.Add("POSSIBILITIES", pEffectControl->Possibilities());
2689     if (pEffectControl->DefaultValue())
2690     result.Add("DEFAULT", *pEffectControl->DefaultValue());
2691     } catch (Exception e) {
2692     result.Error(e);
2693     }
2694     return result.Produce();
2695     }
2696    
2697 schoenebeck 2137 String LSCPServer::SetEffectInstanceInputControlValue(int iEffectInstance, int iInputControlIndex, double dValue) {
2698     dmsg(2,("LSCPServer: SetEffectInstanceInputControlValue(%d,%d,%f)\n", iEffectInstance, iInputControlIndex, dValue));
2699 schoenebeck 2135 LSCPResultSet result;
2700     try {
2701 schoenebeck 2137 Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2702 schoenebeck 2135 if (!pEffect)
2703 schoenebeck 2137 throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2704 schoenebeck 2135
2705     EffectControl* pEffectControl = pEffect->InputControl(iInputControlIndex);
2706     if (!pEffectControl)
2707     throw Exception(
2708 schoenebeck 2137 "Effect instance " + ToString(iEffectInstance) +
2709 schoenebeck 2135 " does not have an input control with index " +
2710     ToString(iInputControlIndex)
2711     );
2712    
2713     pEffectControl->SetValue(dValue);
2714 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_info, iEffectInstance));
2715 schoenebeck 2135 } catch (Exception e) {
2716     result.Error(e);
2717     }
2718     return result.Produce();
2719     }
2720    
2721 schoenebeck 2137 String LSCPServer::CreateEffectInstance(int iEffectIndex) {
2722     dmsg(2,("LSCPServer: CreateEffectInstance(%d)\n", iEffectIndex));
2723 schoenebeck 2135 LSCPResultSet result;
2724     try {
2725 schoenebeck 2137 EffectInfo* pEffectInfo = EffectFactory::GetEffectInfo(iEffectIndex);
2726 schoenebeck 2135 if (!pEffectInfo)
2727 schoenebeck 2137 throw Exception("There is no effect with index " + ToString(iEffectIndex));
2728 schoenebeck 2135 Effect* pEffect = EffectFactory::Create(pEffectInfo);
2729 schoenebeck 2138 result = pEffect->ID(); // success
2730 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_count, EffectFactory::EffectInstancesCount()));
2731 schoenebeck 2135 } catch (Exception e) {
2732     result.Error(e);
2733     }
2734     return result.Produce();
2735     }
2736    
2737     String LSCPServer::CreateEffectInstance(String effectSystem, String module, String effectName) {
2738 schoenebeck 2137 dmsg(2,("LSCPServer: CreateEffectInstance('%s','%s','%s')\n", effectSystem.c_str(), module.c_str(), effectName.c_str()));
2739 schoenebeck 2135 LSCPResultSet result;
2740     try {
2741     // to allow loading the same LSCP session file on different systems
2742     // successfully, probably with different effect plugin DLL paths or even
2743     // running completely different operating systems, we do the following
2744     // for finding the right effect:
2745     //
2746     // first try to search for an exact match of the effect plugin DLL
2747     // (a.k.a 'module'), to avoid picking the wrong DLL with the same
2748     // effect name ...
2749     EffectInfo* pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_MATCH_EXACTLY);
2750     // ... if no effect with exactly matchin DLL filename was found, then
2751     // try to lower the restrictions of matching the effect plugin DLL
2752     // filename and try again and again ...
2753     if (!pEffectInfo) {
2754     dmsg(2,("no exact module match, trying MODULE_IGNORE_PATH\n"));
2755     pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_PATH);
2756     }
2757     if (!pEffectInfo) {
2758     dmsg(2,("no module match, trying MODULE_IGNORE_PATH | MODULE_IGNORE_CASE\n"));
2759     pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_PATH | EffectFactory::MODULE_IGNORE_CASE);
2760     }
2761     if (!pEffectInfo) {
2762     dmsg(2,("no module match, trying MODULE_IGNORE_PATH | MODULE_IGNORE_CASE | MODULE_IGNORE_EXTENSION\n"));
2763     pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_PATH | EffectFactory::MODULE_IGNORE_CASE | EffectFactory::MODULE_IGNORE_EXTENSION);
2764     }
2765     // ... if there was still no effect found, then completely ignore the
2766     // DLL plugin filename argument and just search for the matching effect
2767     // system type and effect name
2768     if (!pEffectInfo) {
2769     dmsg(2,("no module match, trying MODULE_IGNORE_ALL\n"));
2770     pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_ALL);
2771     }
2772     if (!pEffectInfo)
2773     throw Exception("There is no such effect '" + effectSystem + "' '" + module + "' '" + effectName + "'");
2774    
2775     Effect* pEffect = EffectFactory::Create(pEffectInfo);
2776     result = LSCPResultSet(pEffect->ID());
2777 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_count, EffectFactory::EffectInstancesCount()));
2778 schoenebeck 2135 } catch (Exception e) {
2779     result.Error(e);
2780     }
2781     return result.Produce();
2782     }
2783    
2784 schoenebeck 2137 String LSCPServer::DestroyEffectInstance(int iEffectInstance) {
2785     dmsg(2,("LSCPServer: DestroyEffectInstance(%d)\n", iEffectInstance));
2786 schoenebeck 2135 LSCPResultSet result;
2787     try {
2788 schoenebeck 2137 Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2789 schoenebeck 2135 if (!pEffect)
2790 schoenebeck 2137 throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2791 schoenebeck 2135 EffectFactory::Destroy(pEffect);
2792 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_count, EffectFactory::EffectInstancesCount()));
2793 schoenebeck 2135 } catch (Exception e) {
2794     result.Error(e);
2795     }
2796     return result.Produce();
2797     }
2798    
2799     String LSCPServer::GetEffectInstances() {
2800     dmsg(2,("LSCPServer: GetEffectInstances()\n"));
2801     LSCPResultSet result;
2802     try {
2803     int n = EffectFactory::EffectInstancesCount();
2804     result.Add(n);
2805     } catch (Exception e) {
2806     result.Error(e);
2807     }
2808     return result.Produce();
2809     }
2810    
2811     String LSCPServer::ListEffectInstances() {
2812     dmsg(2,("LSCPServer: ListEffectInstances()\n"));
2813     LSCPResultSet result;
2814     String list;
2815     try {
2816     int n = EffectFactory::EffectInstancesCount();
2817     for (int i = 0; i < n; i++) {
2818     Effect* pEffect = EffectFactory::GetEffectInstance(i);
2819     if (i) list += ",";
2820     list += ToString(pEffect->ID());
2821     }
2822     } catch (Exception e) {
2823     result.Error(e);
2824     }
2825     result.Add(list);
2826     return result.Produce();
2827     }
2828    
2829 schoenebeck 2137 String LSCPServer::GetSendEffectChains(int iAudioOutputDevice) {
2830     dmsg(2,("LSCPServer: GetSendEffectChains(%d)\n", iAudioOutputDevice));
2831 schoenebeck 2135 LSCPResultSet result;
2832     try {
2833     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2834     if (!devices.count(iAudioOutputDevice))
2835     throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2836     AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2837 schoenebeck 2137 int n = pDevice->SendEffectChainCount();
2838 schoenebeck 2135 result.Add(n);
2839     } catch (Exception e) {
2840     result.Error(e);
2841     }
2842     return result.Produce();
2843     }
2844    
2845 schoenebeck 2137 String LSCPServer::ListSendEffectChains(int iAudioOutputDevice) {
2846     dmsg(2,("LSCPServer: ListSendEffectChains(%d)\n", iAudioOutputDevice));
2847 schoenebeck 2135 LSCPResultSet result;
2848     String list;
2849     try {
2850     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2851     if (!devices.count(iAudioOutputDevice))
2852     throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2853     AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2854 schoenebeck 2137 int n = pDevice->SendEffectChainCount();
2855 schoenebeck 2135 for (int i = 0; i < n; i++) {
2856 schoenebeck 2137 EffectChain* pEffectChain = pDevice->SendEffectChain(i);
2857 schoenebeck 2135 if (i) list += ",";
2858     list += ToString(pEffectChain->ID());
2859     }
2860     } catch (Exception e) {
2861     result.Error(e);
2862     }
2863     result.Add(list);
2864     return result.Produce();
2865     }
2866    
2867 schoenebeck 2137 String LSCPServer::AddSendEffectChain(int iAudioOutputDevice) {
2868     dmsg(2,("LSCPServer: AddSendEffectChain(%d)\n", iAudioOutputDevice));
2869 schoenebeck 2135 LSCPResultSet result;
2870     try {
2871     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2872     if (!devices.count(iAudioOutputDevice))
2873     throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2874     AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2875 schoenebeck 2137 EffectChain* pEffectChain = pDevice->AddSendEffectChain();
2876 schoenebeck 2138 result = pEffectChain->ID();
2877 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_count, iAudioOutputDevice, pDevice->SendEffectChainCount()));
2878 schoenebeck 2135 } catch (Exception e) {
2879     result.Error(e);
2880     }
2881     return result.Produce();
2882     }
2883    
2884 schoenebeck 2137 String LSCPServer::RemoveSendEffectChain(int iAudioOutputDevice, int iSendEffectChain) {
2885     dmsg(2,("LSCPServer: RemoveSendEffectChain(%d,%d)\n", iAudioOutputDevice, iSendEffectChain));
2886 schoenebeck 2135 LSCPResultSet result;
2887     try {
2888     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2889     if (!devices.count(iAudioOutputDevice))
2890     throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2891 iliev 2198
2892     std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();
2893     std::set<EngineChannel*>::iterator itEngineChannel = engineChannels.begin();
2894     std::set<EngineChannel*>::iterator itEnd = engineChannels.end();
2895     for (; itEngineChannel != itEnd; ++itEngineChannel) {
2896     AudioOutputDevice* pDev = (*itEngineChannel)->GetAudioOutputDevice();
2897     if (pDev != NULL && pDev->deviceId() == iAudioOutputDevice) {
2898     for (int i = 0; i < (*itEngineChannel)->GetFxSendCount(); i++) {
2899     FxSend* fxs = (*itEngineChannel)->GetFxSend(i);
2900     if(fxs != NULL && fxs->DestinationEffectChain() == iSendEffectChain) {
2901     throw Exception("The effect chain is still in use by channel " + ToString((*itEngineChannel)->GetSamplerChannel()->Index()));
2902     }
2903     }
2904     }
2905     }
2906    
2907 schoenebeck 2135 AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2908 schoenebeck 2137 for (int i = 0; i < pDevice->SendEffectChainCount(); i++) {
2909     EffectChain* pEffectChain = pDevice->SendEffectChain(i);
2910     if (pEffectChain->ID() == iSendEffectChain) {
2911     pDevice->RemoveSendEffectChain(i);
2912 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_count, iAudioOutputDevice, pDevice->SendEffectChainCount()));
2913 schoenebeck 2135 return result.Produce();
2914     }
2915     }
2916     throw Exception(
2917 schoenebeck 2137 "There is no send effect chain with ID " +
2918     ToString(iSendEffectChain) + " for audio output device " +
2919 schoenebeck 2135 ToString(iAudioOutputDevice) + "."
2920     );
2921     } catch (Exception e) {
2922     result.Error(e);
2923     }
2924     return result.Produce();
2925     }
2926    
2927 schoenebeck 2137 static EffectChain* _getSendEffectChain(Sampler* pSampler, int iAudioOutputDevice, int iSendEffectChain) throw (Exception) {
2928 schoenebeck 2135 std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2929     if (!devices.count(iAudioOutputDevice))
2930     throw Exception(
2931     "There is no audio output device with index " +
2932     ToString(iAudioOutputDevice) + "."
2933     );
2934     AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2935 iliev 2198 EffectChain* pEffectChain = pDevice->SendEffectChainByID(iSendEffectChain);
2936     if(pEffectChain != NULL) return pEffectChain;
2937 schoenebeck 2135 throw Exception(
2938 schoenebeck 2137 "There is no send effect chain with ID " +
2939     ToString(iSendEffectChain) + " for audio output device " +
2940 schoenebeck 2135 ToString(iAudioOutputDevice) + "."
2941     );
2942     }
2943    
2944 schoenebeck 2137 String LSCPServer::GetSendEffectChainInfo(int iAudioOutputDevice, int iSendEffectChain) {
2945     dmsg(2,("LSCPServer: GetSendEffectChainInfo(%d,%d)\n", iAudioOutputDevice, iSendEffectChain));
2946 schoenebeck 2135 LSCPResultSet result;
2947     try {
2948     EffectChain* pEffectChain =
2949 schoenebeck 2137 _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
2950 schoenebeck 2135 String sEffectSequence;
2951     for (int i = 0; i < pEffectChain->EffectCount(); i++) {
2952     if (i) sEffectSequence += ",";
2953     sEffectSequence += ToString(pEffectChain->GetEffect(i)->ID());
2954     }
2955     result.Add("EFFECT_COUNT", pEffectChain->EffectCount());
2956     result.Add("EFFECT_SEQUENCE", sEffectSequence);
2957     } catch (Exception e) {
2958     result.Error(e);
2959     }
2960     return result.Produce();
2961     }
2962    
2963 schoenebeck 2137 String LSCPServer::AppendSendEffectChainEffect(int iAudioOutputDevice, int iSendEffectChain, int iEffectInstance) {
2964     dmsg(2,("LSCPServer: AppendSendEffectChainEffect(%d,%d,%d)\n", iAudioOutputDevice, iSendEffectChain, iEffectInstance));
2965 schoenebeck 2135 LSCPResultSet result;
2966     try {
2967     EffectChain* pEffectChain =
2968 schoenebeck 2137 _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
2969 schoenebeck 2135 Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2970     if (!pEffect)
2971 schoenebeck 2137 throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2972 schoenebeck 2135 pEffectChain->AppendEffect(pEffect);
2973 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_info, iAudioOutputDevice, iSendEffectChain, pEffectChain->EffectCount()));
2974 schoenebeck 2135 } catch (Exception e) {
2975     result.Error(e);
2976     }
2977     return result.Produce();
2978     }
2979    
2980 schoenebeck 2137 String LSCPServer::InsertSendEffectChainEffect(int iAudioOutputDevice, int iSendEffectChain, int iEffectChainPosition, int iEffectInstance) {
2981     dmsg(2,("LSCPServer: InsertSendEffectChainEffect(%d,%d,%d,%d)\n", iAudioOutputDevice, iSendEffectChain, iEffectChainPosition, iEffectInstance));
2982 schoenebeck 2135 LSCPResultSet result;
2983     try {
2984     EffectChain* pEffectChain =
2985 schoenebeck 2137 _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
2986 schoenebeck 2135 Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2987     if (!pEffect)
2988     throw Exception("There is no effect instance with index " + ToString(iEffectInstance));
2989     pEffectChain->InsertEffect(pEffect, iEffectChainPosition);
2990 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_info, iAudioOutputDevice, iSendEffectChain, pEffectChain->EffectCount()));
2991 schoenebeck 2135 } catch (Exception e) {
2992     result.Error(e);
2993     }
2994     return result.Produce();
2995     }
2996    
2997 schoenebeck 2137 String LSCPServer::RemoveSendEffectChainEffect(int iAudioOutputDevice, int iSendEffectChain, int iEffectChainPosition) {
2998     dmsg(2,("LSCPServer: RemoveSendEffectChainEffect(%d,%d,%d)\n", iAudioOutputDevice, iSendEffectChain, iEffectChainPosition));
2999 schoenebeck 2135 LSCPResultSet result;
3000     try {
3001     EffectChain* pEffectChain =
3002 schoenebeck 2137 _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
3003 iliev 2198
3004     std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();
3005     std::set<EngineChannel*>::iterator itEngineChannel = engineChannels.begin();
3006     std::set<EngineChannel*>::iterator itEnd = engineChannels.end();
3007     for (; itEngineChannel != itEnd; ++itEngineChannel) {
3008     AudioOutputDevice* pDev = (*itEngineChannel)->GetAudioOutputDevice();
3009     if (pDev != NULL && pDev->deviceId() == iAudioOutputDevice) {
3010     for (int i = 0; i < (*itEngineChannel)->GetFxSendCount(); i++) {
3011     FxSend* fxs = (*itEngineChannel)->GetFxSend(i);
3012     if(fxs != NULL && fxs->DestinationEffectChain() == iSendEffectChain && fxs->DestinationEffectChainPosition() == iEffectChainPosition) {
3013     throw Exception("The effect instance is still in use by channel " + ToString((*itEngineChannel)->GetSamplerChannel()->Index()));
3014     }
3015     }
3016     }
3017     }
3018    
3019 schoenebeck 2137 pEffectChain->RemoveEffect(iEffectChainPosition);
3020 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_info, iAudioOutputDevice, iSendEffectChain, pEffectChain->EffectCount()));
3021 schoenebeck 2135 } catch (Exception e) {
3022     result.Error(e);
3023     }
3024     return result.Produce();
3025     }
3026    
3027 schoenebeck 1212 String LSCPServer::EditSamplerChannelInstrument(uint uiSamplerChannel) {
3028     dmsg(2,("LSCPServer: EditSamplerChannelInstrument(SamplerChannel=%d)\n", uiSamplerChannel));
3029     LSCPResultSet result;
3030     try {
3031 iliev 1771 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
3032 iliev 1337 if (pEngineChannel->InstrumentStatus() < 0) throw Exception("No instrument loaded to sampler channel");
3033 schoenebeck 1212 Engine* pEngine = pEngineChannel->GetEngine();
3034     InstrumentManager* pInstrumentManager = pEngine->GetInstrumentManager();
3035     if (!pInstrumentManager) throw Exception("Engine does not provide an instrument manager");
3036     InstrumentManager::instrument_id_t instrumentID;
3037     instrumentID.FileName = pEngineChannel->InstrumentFileName();
3038     instrumentID.Index = pEngineChannel->InstrumentIndex();
3039     pInstrumentManager->LaunchInstrumentEditor(instrumentID);
3040     } catch (Exception e) {
3041     result.Error(e);
3042     }
3043     return result.Produce();
3044     }
3045    
3046 iliev 1771 String LSCPServer::SendChannelMidiData(String MidiMsg, uint uiSamplerChannel, uint Arg1, uint Arg2) {
3047     dmsg(2,("LSCPServer: SendChannelMidiData(MidiMsg=%s,uiSamplerChannel=%d,Arg1=%d,Arg2=%d)\n", MidiMsg.c_str(), uiSamplerChannel, Arg1, Arg2));
3048     LSCPResultSet result;
3049     try {
3050     EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
3051    
3052     if (Arg1 > 127 || Arg2 > 127) {
3053     throw Exception("Invalid MIDI message");
3054     }
3055    
3056     VirtualMidiDevice* pMidiDevice = NULL;
3057     std::vector<EventHandler::midi_listener_entry>::iterator iter = eventHandler.channelMidiListeners.begin();
3058     for (; iter != eventHandler.channelMidiListeners.end(); ++iter) {
3059     if ((*iter).pEngineChannel == pEngineChannel) {
3060     pMidiDevice = (*iter).pMidiListener;
3061     break;
3062     }
3063     }
3064    
3065     if(pMidiDevice == NULL) throw Exception("Couldn't find virtual MIDI device");
3066    
3067     if (MidiMsg == "NOTE_ON") {
3068 iliev 1774 pMidiDevice->SendNoteOnToDevice(Arg1, Arg2);
3069 iliev 1771 bool b = pMidiDevice->SendNoteOnToSampler(Arg1, Arg2);
3070     if (!b) throw Exception("MIDI event failed: " + MidiMsg + " " + ToString(Arg1) + " " + ToString(Arg2));
3071     } else if (MidiMsg == "NOTE_OFF") {
3072 iliev 1774 pMidiDevice->SendNoteOffToDevice(Arg1, Arg2);
3073 iliev 1771 bool b = pMidiDevice->SendNoteOffToSampler(Arg1, Arg2);
3074     if (!b) throw Exception("MIDI event failed: " + MidiMsg + " " + ToString(Arg1) + " " + ToString(Arg2));
3075 schoenebeck 2025 } else if (MidiMsg == "CC") {
3076     pMidiDevice->SendCCToDevice(Arg1, Arg2);
3077     bool b = pMidiDevice->SendCCToSampler(Arg1, Arg2);
3078     if (!b) throw Exception("MIDI event failed: " + MidiMsg + " " + ToString(Arg1) + " " + ToString(Arg2));
3079 iliev 1771 } else {
3080     throw Exception("Unknown MIDI message type: " + MidiMsg);
3081     }
3082     } catch (Exception e) {
3083     result.Error(e);
3084     }
3085     return result.Produce();
3086     }
3087    
3088 schoenebeck 973 /**
3089 schoenebeck 35 * Will be called by the parser to reset a particular sampler channel.
3090     */
3091 schoenebeck 53 String LSCPServer::ResetChannel(uint uiSamplerChannel) {
3092     dmsg(2,("LSCPServer: ResetChannel(SamplerChannel=%d)\n", uiSamplerChannel));
3093 senkov 120 LSCPResultSet result;
3094 schoenebeck 53 try {
3095 iliev 1771 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
3096 schoenebeck 670 pEngineChannel->Reset();
3097 schoenebeck 53 }
3098 schoenebeck 880 catch (Exception e) {
3099 senkov 120 result.Error(e);
3100 schoenebeck 53 }
3101 senkov 120 return result.Produce();
3102 schoenebeck 35 }
3103    
3104     /**
3105 schoenebeck 212 * Will be called by the parser to reset the whole sampler.
3106     */
3107     String LSCPServer::ResetSampler() {
3108     dmsg(2,("LSCPServer: ResetSampler()\n"));
3109     pSampler->Reset();
3110     LSCPResultSet result;
3111     return result.Produce();
3112     }
3113    
3114     /**
3115 schoenebeck 563 * Will be called by the parser to return general informations about this
3116     * sampler.
3117     */
3118     String LSCPServer::GetServerInfo() {
3119     dmsg(2,("LSCPServer: GetServerInfo()\n"));
3120 schoenebeck 1399 const std::string description =
3121     _escapeLscpResponse("LinuxSampler - modular, streaming capable sampler");
3122 schoenebeck 563 LSCPResultSet result;
3123 schoenebeck 1399 result.Add("DESCRIPTION", description);
3124 schoenebeck 570 result.Add("VERSION", VERSION);
3125 schoenebeck 947 result.Add("PROTOCOL_VERSION", ToString(LSCP_RELEASE_MAJOR) + "." + ToString(LSCP_RELEASE_MINOR));
3126 iliev 1161 #if HAVE_SQLITE3
3127     result.Add("INSTRUMENTS_DB_SUPPORT", "yes");
3128     #else
3129     result.Add("INSTRUMENTS_DB_SUPPORT", "no");
3130     #endif
3131 schoenebeck 1252
3132 schoenebeck 563 return result.Produce();
3133     }
3134    
3135     /**
3136 iliev 1541 * Will be called by the parser to return the current number of all active streams.
3137     */
3138     String LSCPServer::GetTotalStreamCount() {
3139     dmsg(2,("LSCPServer: GetTotalStreamCount()\n"));
3140     LSCPResultSet result;
3141     result.Add(pSampler->GetDiskStreamCount());
3142     return result.Produce();
3143     }
3144    
3145     /**
3146 iliev 778 * Will be called by the parser to return the current number of all active voices.
3147     */
3148     String LSCPServer::GetTotalVoiceCount() {
3149     dmsg(2,("LSCPServer: GetTotalVoiceCount()\n"));
3150     LSCPResultSet result;
3151     result.Add(pSampler->GetVoiceCount());
3152     return result.Produce();
3153     }
3154    
3155     /**
3156     * Will be called by the parser to return the maximum number of voices.
3157     */
3158     String LSCPServer::GetTotalVoiceCountMax() {
3159     dmsg(2,("LSCPServer: GetTotalVoiceCountMax()\n"));
3160     LSCPResultSet result;
3161 schoenebeck 2375 result.Add(EngineFactory::EngineInstances().size() * pSampler->GetGlobalMaxVoices());
3162 iliev 778 return result.Produce();
3163     }
3164    
3165 schoenebeck 1800 /**
3166     * Will be called by the parser to return the sampler global maximum
3167     * allowed number of voices.
3168     */
3169     String LSCPServer::GetGlobalMaxVoices() {
3170     dmsg(2,("LSCPServer: GetGlobalMaxVoices()\n"));
3171     LSCPResultSet result;
3172 schoenebeck 2375 result.Add(pSampler->GetGlobalMaxVoices());
3173 schoenebeck 1800 return result.Produce();
3174     }
3175    
3176     /**
3177     * Will be called by the parser to set the sampler global maximum number of
3178     * voices.
3179     */
3180     String LSCPServer::SetGlobalMaxVoices(int iVoices) {
3181     dmsg(2,("LSCPServer: SetGlobalMaxVoices(%d)\n", iVoices));
3182     LSCPResultSet result;
3183     try {
3184 schoenebeck 2375 pSampler->SetGlobalMaxVoices(iVoices);
3185     LSCPServer::SendLSCPNotify(
3186     LSCPEvent(LSCPEvent::event_global_info, "VOICES", pSampler->GetGlobalMaxVoices())
3187     );
3188 schoenebeck 1800 } catch (Exception e) {
3189     result.Error(e);
3190     }
3191     return result.Produce();
3192     }
3193    
3194     /**
3195     * Will be called by the parser to return the sampler global maximum
3196     * allowed number of disk streams.
3197     */
3198     String LSCPServer::GetGlobalMaxStreams() {
3199     dmsg(2,("LSCPServer: GetGlobalMaxStreams()\n"));
3200     LSCPResultSet result;
3201 schoenebeck 2375 result.Add(pSampler->GetGlobalMaxStreams());
3202 schoenebeck 1800 return result.Produce();
3203     }
3204    
3205     /**
3206     * Will be called by the parser to set the sampler global maximum number of
3207     * disk streams.
3208     */
3209     String LSCPServer::SetGlobalMaxStreams(int iStreams) {
3210     dmsg(2,("LSCPServer: SetGlobalMaxStreams(%d)\n", iStreams));
3211     LSCPResultSet result;
3212     try {
3213 schoenebeck 2375 pSampler->SetGlobalMaxStreams(iStreams);
3214     LSCPServer::SendLSCPNotify(
3215     LSCPEvent(LSCPEvent::event_global_info, "STREAMS", pSampler->GetGlobalMaxStreams())
3216     );
3217 schoenebeck 1800 } catch (Exception e) {
3218     result.Error(e);
3219     }
3220     return result.Produce();
3221     }
3222    
3223 schoenebeck 1005 String LSCPServer::GetGlobalVolume() {
3224     LSCPResultSet result;
3225     result.Add(ToString(GLOBAL_VOLUME)); // see common/global.cpp
3226     return result.Produce();
3227     }
3228    
3229     String LSCPServer::SetGlobalVolume(double dVolume) {
3230     LSCPResultSet result;
3231     try {
3232     if (dVolume < 0) throw Exception("Volume may not be negative");
3233 schoenebeck 1724 GLOBAL_VOLUME = dVolume; // see common/global_private.cpp
3234 iliev 1108 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_global_info, "VOLUME", GLOBAL_VOLUME));
3235 schoenebeck 1005 } catch (Exception e) {
3236     result.Error(e);
3237     }
3238     return result.Produce();
3239     }
3240    
3241 schoenebeck 1525 String LSCPServer::GetFileInstruments(String Filename) {
3242 iliev 1535 dmsg(2,("LSCPServer: GetFileInstruments(String Filename=%s)\n",Filename.c_str()));
3243 schoenebeck 1525 LSCPResultSet result;
3244 iliev 1535 try {
3245     VerifyFile(Filename);
3246     } catch (Exception e) {
3247     result.Error(e);
3248     return result.Produce();
3249     }
3250 schoenebeck 1525 // try to find a sampler engine that can handle the file
3251     bool bFound = false;
3252     std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
3253     for (int i = 0; !bFound && i < engineTypes.size(); i++) {
3254     Engine* pEngine = NULL;
3255     try {
3256     pEngine = EngineFactory::Create(engineTypes[i]);
3257     if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
3258     InstrumentManager* pManager = pEngine->GetInstrumentManager();
3259     if (pManager) {
3260     std::vector<InstrumentManager::instrument_id_t> IDs =
3261     pManager->GetInstrumentFileContent(Filename);
3262     // return the amount of instruments in the file
3263     result.Add(IDs.size());
3264     // no more need to ask other engine types
3265     bFound = true;
3266     } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
3267     } catch (Exception e) {
3268     // NOOP, as exception is thrown if engine doesn't support file
3269     }
3270     if (pEngine) EngineFactory::Destroy(pEngine);
3271     }
3272 iliev 1535
3273     if (!bFound) result.Error("Unknown file format");
3274 schoenebeck 1525 return result.Produce();
3275     }
3276    
3277     String LSCPServer::ListFileInstruments(String Filename) {
3278 iliev 1535 dmsg(2,("LSCPServer: ListFileInstruments(String Filename=%s)\n",Filename.c_str()));
3279 schoenebeck 1525 LSCPResultSet result;
3280 iliev 1535 try {
3281     VerifyFile(Filename);
3282     } catch (Exception e) {
3283     result.Error(e);
3284     return result.Produce();
3285     }
3286 schoenebeck 1525 // try to find a sampler engine that can handle the file
3287     bool bFound = false;
3288     std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
3289     for (int i = 0; !bFound && i < engineTypes.size(); i++) {
3290     Engine* pEngine = NULL;
3291     try {
3292     pEngine = EngineFactory::Create(engineTypes[i]);
3293     if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
3294     InstrumentManager* pManager = pEngine->GetInstrumentManager();
3295     if (pManager) {
3296     std::vector<InstrumentManager::instrument_id_t> IDs =
3297     pManager->GetInstrumentFileContent(Filename);
3298     // return a list of IDs of the instruments in the file
3299     String s;
3300     for (int j = 0; j < IDs.size(); j++) {
3301     if (s.size()) s += ",";
3302     s += ToString(IDs[j].Index);
3303     }
3304     result.Add(s);
3305     // no more need to ask other engine types
3306     bFound = true;
3307     } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
3308     } catch (Exception e) {
3309     // NOOP, as exception is thrown if engine doesn't support file
3310     }
3311     if (pEngine) EngineFactory::Destroy(pEngine);
3312     }
3313 iliev 1535
3314     if (!bFound) result.Error("Unknown file format");
3315 schoenebeck 1525 return result.Produce();
3316     }
3317    
3318     String LSCPServer::GetFileInstrumentInfo(String Filename, uint InstrumentID) {
3319 iliev 1535 dmsg(2,("LSCPServer: GetFileInstrumentInfo(String Filename=%s, InstrumentID=%d)\n",Filename.c_str(),InstrumentID));
3320 schoenebeck 1525 LSCPResultSet result;
3321 iliev 1535 try {
3322     VerifyFile(Filename);
3323     } catch (Exception e) {
3324     result.Error(e);
3325     return result.Produce();
3326     }
3327 schoenebeck 1525 InstrumentManager::instrument_id_t id;
3328     id.FileName = Filename;
3329     id.Index = InstrumentID;
3330     // try to find a sampler engine that can handle the file
3331     bool bFound = false;
3332 schoenebeck 1536 bool bFatalErr = false;
3333 schoenebeck 1525 std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
3334 schoenebeck 1536 for (int i = 0; !bFound && !bFatalErr && i < engineTypes.size(); i++) {
3335 schoenebeck 1525 Engine* pEngine = NULL;
3336     try {
3337     pEngine = EngineFactory::Create(engineTypes[i]);
3338     if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
3339     InstrumentManager* pManager = pEngine->GetInstrumentManager();
3340     if (pManager) {
3341 schoenebeck 1536 // check if the instrument index is valid
3342     // FIXME: this won't work if an engine only supports parts of the instrument file
3343     std::vector<InstrumentManager::instrument_id_t> IDs =
3344     pManager->GetInstrumentFileContent(Filename);
3345     if (std::find(IDs.begin(), IDs.end(), id) == IDs.end()) {
3346     std::stringstream ss;
3347     ss << "Invalid instrument index " << InstrumentID << " for instrument file '" << Filename << "'";
3348     bFatalErr = true;
3349     throw Exception(ss.str());
3350     }
3351     // get the info of the requested instrument
3352 schoenebeck 1525 InstrumentManager::instrument_info_t info =
3353     pManager->GetInstrumentInfo(id);
3354     // return detailed informations about the file
3355     result.Add("NAME", info.InstrumentName);
3356 iliev 1535 result.Add("FORMAT_FAMILY", engineTypes[i]);
3357 schoenebeck 1525 result.Add("FORMAT_VERSION", info.FormatVersion);
3358     result.Add("PRODUCT", info.Product);
3359     result.Add("ARTISTS", info.Artists);
3360 iliev 1771
3361     std::stringstream ss;
3362     bool b = false;
3363     for (int i = 0; i < 128; i++) {
3364     if (info.KeyBindings[i]) {
3365     if (b) ss << ',';
3366     ss << i; b = true;
3367     }
3368     }
3369     result.Add("KEY_BINDINGS", ss.str());
3370    
3371 iliev 1774 b = false;
3372 iliev 1771 std::stringstream ss2;
3373     for (int i = 0; i < 128; i++) {
3374     if (info.KeySwitchBindings[i]) {
3375     if (b) ss2 << ',';
3376     ss2 << i; b = true;
3377     }
3378     }
3379     result.Add("KEYSWITCH_BINDINGS", ss2.str());
3380 schoenebeck 1525 // no more need to ask other engine types
3381     bFound = true;
3382     } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
3383     } catch (Exception e) {
3384 schoenebeck 1536 // usually NOOP, as exception is thrown if engine doesn't support file
3385     if (bFatalErr) result.Error(e);
3386 schoenebeck 1525 }
3387     if (pEngine) EngineFactory::Destroy(pEngine);
3388     }
3389 iliev 1535
3390 schoenebeck 1536 if (!bFound && !bFatalErr) result.Error("Unknown file format");
3391 schoenebeck 1525 return result.Produce();
3392     }
3393    
3394 iliev 1535 void LSCPServer::VerifyFile(String Filename) {
3395 senoner 1537 #if WIN32
3396     WIN32_FIND_DATA win32FileAttributeData;
3397     BOOL res = GetFileAttributesEx( Filename.c_str(), GetFileExInfoStandard, &win32FileAttributeData );
3398     if (!res) {
3399     std::stringstream ss;
3400     ss << "File does not exist, GetFileAttributesEx failed `" << Filename << "`: Error " << GetLastError();
3401     throw Exception(ss.str());
3402     }
3403     if ( win32FileAttributeData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
3404     throw Exception("Directory is specified");
3405     }
3406 schoenebeck 1551 #else
3407 iliev 1835 File f(Filename);
3408     if(!f.Exist()) throw Exception(f.GetErrorMsg());
3409     if (f.IsDirectory()) throw Exception("Directory is specified");
3410 senoner 1537 #endif
3411 iliev 1535 }
3412    
3413 iliev 778 /**
3414 schoenebeck 35 * Will be called by the parser to subscribe a client (frontend) on the
3415     * server for receiving event messages.
3416     */
3417 senkov 170 String LSCPServer::SubscribeNotification(LSCPEvent::event_t type) {
3418     dmsg(2,("LSCPServer: SubscribeNotification(Event=%s)\n", LSCPEvent::Name(type).c_str()));
3419     LSCPResultSet result;
3420 persson 2427 {
3421     LockGuard lock(SubscriptionMutex);
3422     eventSubscriptions[type].push_back(currentSocket);
3423     }
3424 senkov 170 return result.Produce();
3425 schoenebeck 35 }
3426    
3427     /**
3428     * Will be called by the parser to unsubscribe a client on the server
3429     * for not receiving further event messages.
3430     */
3431 senkov 170 String LSCPServer::UnsubscribeNotification(LSCPEvent::event_t type) {
3432     dmsg(2,("LSCPServer: UnsubscribeNotification(Event=%s)\n", LSCPEvent::Name(type).c_str()));
3433     LSCPResultSet result;
3434 persson 2427 {
3435     LockGuard lock(SubscriptionMutex);
3436     eventSubscriptions[type].remove(currentSocket);
3437     }
3438 senkov 170 return result.Produce();
3439 schoenebeck 35 }
3440 capela 133
3441 iliev 1161 String LSCPServer::AddDbInstrumentDirectory(String Dir) {
3442     dmsg(2,("LSCPServer: AddDbInstrumentDirectory(Dir=%s)\n", Dir.c_str()));
3443     LSCPResultSet result;
3444     #if HAVE_SQLITE3
3445     try {
3446     InstrumentsDb::GetInstrumentsDb()->AddDirectory(Dir);
3447     } catch (Exception e) {
3448     result.Error(e);
3449     }
3450     #else
3451     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3452     #endif
3453     return result.Produce();
3454 senkov 397 }
3455    
3456 iliev 1161 String LSCPServer::RemoveDbInstrumentDirectory(String Dir, bool Force) {
3457     dmsg(2,("LSCPServer: RemoveDbInstrumentDirectory(Dir=%s,Force=%d)\n", Dir.c_str(), Force));
3458 senkov 397 LSCPResultSet result;
3459 schoenebeck 401 #if HAVE_SQLITE3
3460 iliev 1161 try {
3461     InstrumentsDb::GetInstrumentsDb()->RemoveDirectory(Dir, Force);
3462     } catch (Exception e) {
3463     result.Error(e);
3464     }
3465     #else
3466     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3467     #endif
3468     return result.Produce();
3469     }
3470 senkov 397
3471 iliev 1187 String LSCPServer::GetDbInstrumentDirectoryCount(String Dir, bool Recursive) {
3472     dmsg(2,("LSCPServer: GetDbInstrumentDirectoryCount(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3473 iliev 1161 LSCPResultSet result;
3474     #if HAVE_SQLITE3
3475     try {
3476 iliev 1187 result.Add(InstrumentsDb::GetInstrumentsDb()->GetDirectoryCount(Dir, Recursive));
3477 iliev 1161 } catch (Exception e) {
3478     result.Error(e);
3479 senkov 397 }
3480 iliev 1161 #else
3481     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3482     #endif
3483     return result.Produce();
3484     }
3485    
3486 iliev 1187 String LSCPServer::GetDbInstrumentDirectories(String Dir, bool Recursive) {
3487     dmsg(2,("LSCPServer: GetDbInstrumentDirectories(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3488 iliev 1161 LSCPResultSet result;
3489     #if HAVE_SQLITE3
3490     try {
3491     String list;
3492 iliev 1187 StringListPtr dirs = InstrumentsDb::GetInstrumentsDb()->GetDirectories(Dir, Recursive);
3493 iliev 1161
3494     for (int i = 0; i < dirs->size(); i++) {
3495     if (list != "") list += ",";
3496 iliev 1350 list += "'" + InstrumentsDb::toEscapedPath(dirs->at(i)) + "'";
3497 iliev 1161 }
3498    
3499     result.Add(list);
3500     } catch (Exception e) {
3501     result.Error(e);
3502 senkov 397 }
3503     #else
3504 iliev 1161 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3505 senkov 397 #endif
3506     return result.Produce();
3507     }
3508    
3509 iliev 1161 String LSCPServer::GetDbInstrumentDirectoryInfo(String Dir) {
3510     dmsg(2,("LSCPServer: GetDbInstrumentDirectoryInfo(Dir=%s)\n", Dir.c_str()));
3511     LSCPResultSet result;
3512     #if HAVE_SQLITE3
3513     try {
3514     DbDirectory info = InstrumentsDb::GetInstrumentsDb()->GetDirectoryInfo(Dir);
3515    
3516 iliev 1403 result.Add("DESCRIPTION", _escapeLscpResponse(info.Description));
3517 iliev 1161 result.Add("CREATED", info.Created);
3518     result.Add("MODIFIED", info.Modified);
3519     } catch (Exception e) {
3520     result.Error(e);
3521     }
3522     #else
3523     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3524     #endif
3525     return result.Produce();
3526     }
3527    
3528     String LSCPServer::SetDbInstrumentDirectoryName(String Dir, String Name) {
3529     dmsg(2,("LSCPServer: SetDbInstrumentDirectoryName(Dir=%s,Name=%s)\n", Dir.c_str(), Name.c_str()));
3530     LSCPResultSet result;
3531     #if HAVE_SQLITE3
3532     try {
3533     InstrumentsDb::GetInstrumentsDb()->RenameDirectory(Dir, Name);
3534     } catch (Exception e) {
3535     result.Error(e);
3536     }
3537     #else
3538     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3539     #endif
3540     return result.Produce();
3541     }
3542    
3543     String LSCPServer::MoveDbInstrumentDirectory(String Dir, String Dst) {
3544     dmsg(2,("LSCPServer: MoveDbInstrumentDirectory(Dir=%s,Dst=%s)\n", Dir.c_str(), Dst.c_str()));
3545     LSCPResultSet result;
3546     #if HAVE_SQLITE3
3547     try {
3548     InstrumentsDb::GetInstrumentsDb()->MoveDirectory(Dir, Dst);
3549     } catch (Exception e) {
3550     result.Error(e);
3551     }
3552     #else
3553     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3554     #endif
3555     return result.Produce();
3556     }
3557    
3558 iliev 1187 String LSCPServer::CopyDbInstrumentDirectory(String Dir, String Dst) {
3559     dmsg(2,("LSCPServer: CopyDbInstrumentDirectory(Dir=%s,Dst=%s)\n", Dir.c_str(), Dst.c_str()));
3560     LSCPResultSet result;
3561     #if HAVE_SQLITE3
3562     try {
3563     InstrumentsDb::GetInstrumentsDb()->CopyDirectory(Dir, Dst);
3564     } catch (Exception e) {
3565     result.Error(e);
3566     }
3567     #else
3568     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3569     #endif
3570     return result.Produce();
3571     }
3572    
3573 iliev 1161 String LSCPServer::SetDbInstrumentDirectoryDescription(String Dir, String Desc) {
3574     dmsg(2,("LSCPServer: SetDbInstrumentDirectoryDescription(Dir=%s,Desc=%s)\n", Dir.c_str(), Desc.c_str()));
3575     LSCPResultSet result;
3576     #if HAVE_SQLITE3
3577     try {
3578     InstrumentsDb::GetInstrumentsDb()->SetDirectoryDescription(Dir, Desc);
3579     } catch (Exception e) {
3580     result.Error(e);
3581     }
3582     #else
3583     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3584     #endif
3585     return result.Produce();
3586     }
3587    
3588 iliev 1200 String LSCPServer::AddDbInstruments(String DbDir, String FilePath, int Index, bool bBackground) {
3589     dmsg(2,("LSCPServer: AddDbInstruments(DbDir=%s,FilePath=%s,Index=%d,bBackground=%d)\n", DbDir.c_str(), FilePath.c_str(), Index, bBackground));
3590 iliev 1161 LSCPResultSet result;
3591     #if HAVE_SQLITE3
3592     try {
3593 iliev 1200 int id;
3594     InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
3595     id = db->AddInstruments(DbDir, FilePath, Index, bBackground);
3596     if (bBackground) result = id;
3597 iliev 1161 } catch (Exception e) {
3598     result.Error(e);
3599     }
3600     #else
3601     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3602     #endif
3603     return result.Produce();
3604     }
3605    
3606 iliev 1781 String LSCPServer::AddDbInstruments(String ScanMode, String DbDir, String FsDir, bool bBackground, bool insDir) {
3607     dmsg(2,("LSCPServer: AddDbInstruments(ScanMode=%s,DbDir=%s,FsDir=%s,bBackground=%d,insDir=%d)\n", ScanMode.c_str(), DbDir.c_str(), FsDir.c_str(), bBackground, insDir));
3608 iliev 1161 LSCPResultSet result;
3609     #if HAVE_SQLITE3
3610     try {
3611 iliev 1200 int id;
3612     InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
3613     if (ScanMode.compare("RECURSIVE") == 0) {
3614 iliev 1781 id = db->AddInstruments(RECURSIVE, DbDir, FsDir, bBackground, insDir);
3615 iliev 1200 } else if (ScanMode.compare("NON_RECURSIVE") == 0) {
3616 iliev 1781 id = db->AddInstruments(NON_RECURSIVE, DbDir, FsDir, bBackground, insDir);
3617 iliev 1200 } else if (ScanMode.compare("FLAT") == 0) {
3618 iliev 1781 id = db->AddInstruments(FLAT, DbDir, FsDir, bBackground, insDir);
3619 iliev 1200 } else {
3620     throw Exception("Unknown scan mode: " + ScanMode);
3621     }
3622 schoenebeck 1252
3623 iliev 1200 if (bBackground) result = id;
3624 iliev 1161 } catch (Exception e) {
3625     result.Error(e);
3626     }
3627     #else
3628     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3629     #endif
3630     return result.Produce();
3631     }
3632    
3633     String LSCPServer::RemoveDbInstrument(String Instr) {
3634     dmsg(2,("LSCPServer: RemoveDbInstrument(Instr=%s)\n", Instr.c_str()));
3635     LSCPResultSet result;
3636     #if HAVE_SQLITE3
3637     try {
3638     InstrumentsDb::GetInstrumentsDb()->RemoveInstrument(Instr);
3639     } catch (Exception e) {
3640     result.Error(e);
3641     }
3642     #else
3643     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3644     #endif
3645     return result.Produce();
3646     }
3647    
3648 iliev 1187 String LSCPServer::GetDbInstrumentCount(String Dir, bool Recursive) {
3649     dmsg(2,("LSCPServer: GetDbInstrumentCount(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3650 iliev 1161 LSCPResultSet result;
3651     #if HAVE_SQLITE3
3652     try {
3653 iliev 1187 result.Add(InstrumentsDb::GetInstrumentsDb()->GetInstrumentCount(Dir, Recursive));
3654 iliev 1161 } catch (Exception e) {
3655     result.Error(e);
3656     }
3657     #else
3658     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3659     #endif
3660     return result.Produce();
3661     }
3662    
3663 iliev 1187 String LSCPServer::GetDbInstruments(String Dir, bool Recursive) {
3664     dmsg(2,("LSCPServer: GetDbInstruments(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3665 iliev 1161 LSCPResultSet result;
3666     #if HAVE_SQLITE3
3667     try {
3668     String list;
3669 iliev 1187 StringListPtr instrs = InstrumentsDb::GetInstrumentsDb()->GetInstruments(Dir, Recursive);
3670 iliev 1161
3671     for (int i = 0; i < instrs->size(); i++) {
3672     if (list != "") list += ",";
3673 iliev 1350 list += "'" + InstrumentsDb::toEscapedPath(instrs->at(i)) + "'";
3674 iliev 1161 }
3675    
3676     result.Add(list);
3677     } catch (Exception e) {
3678     result.Error(e);
3679     }
3680     #else
3681     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3682     #endif
3683     return result.Produce();
3684     }
3685    
3686     String LSCPServer::GetDbInstrumentInfo(String Instr) {
3687     dmsg(2,("LSCPServer: GetDbInstrumentInfo(Instr=%s)\n", Instr.c_str()));
3688     LSCPResultSet result;
3689     #if HAVE_SQLITE3
3690     try {
3691     DbInstrument info = InstrumentsDb::GetInstrumentsDb()->GetInstrumentInfo(Instr);
3692    
3693     result.Add("INSTRUMENT_FILE", info.InstrFile);
3694     result.Add("INSTRUMENT_NR", info.InstrNr);
3695     result.Add("FORMAT_FAMILY", info.FormatFamily);
3696     result.Add("FORMAT_VERSION", info.FormatVersion);
3697     result.Add("SIZE", (int)info.Size);
3698     result.Add("CREATED", info.Created);
3699     result.Add("MODIFIED", info.Modified);
3700 iliev 1403 result.Add("DESCRIPTION", _escapeLscpResponse(info.Description));
3701 iliev 1161 result.Add("IS_DRUM", info.IsDrum);
3702 iliev 1403 result.Add("PRODUCT", _escapeLscpResponse(info.Product));
3703     result.Add("ARTISTS", _escapeLscpResponse(info.Artists));
3704     result.Add("KEYWORDS", _escapeLscpResponse(info.Keywords));
3705 iliev 1161 } catch (Exception e) {
3706     result.Error(e);
3707     }
3708     #else
3709     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3710     #endif
3711     return result.Produce();
3712     }
3713    
3714 iliev 1200 String LSCPServer::GetDbInstrumentsJobInfo(int JobId) {
3715     dmsg(2,("LSCPServer: GetDbInstrumentsJobInfo(JobId=%d)\n", JobId));
3716     LSCPResultSet result;
3717     #if HAVE_SQLITE3
3718     try {
3719     ScanJob job = InstrumentsDb::GetInstrumentsDb()->Jobs.GetJobById(JobId);
3720    
3721     result.Add("FILES_TOTAL", job.FilesTotal);
3722     result.Add("FILES_SCANNED", job.FilesScanned);
3723     result.Add("SCANNING", job.Scanning);
3724     result.Add("STATUS", job.Status);
3725     } catch (Exception e) {
3726     result.Error(e);
3727     }
3728     #else
3729     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3730     #endif
3731     return result.Produce();
3732     }
3733    
3734 iliev 1161 String LSCPServer::SetDbInstrumentName(String Instr, String Name) {
3735     dmsg(2,("LSCPServer: SetDbInstrumentName(Instr=%s,Name=%s)\n", Instr.c_str(), Name.c_str()));
3736     LSCPResultSet result;
3737     #if HAVE_SQLITE3
3738     try {
3739     InstrumentsDb::GetInstrumentsDb()->RenameInstrument(Instr, Name);
3740     } catch (Exception e) {
3741     result.Error(e);
3742     }
3743     #else
3744     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3745     #endif
3746     return result.Produce();
3747     }
3748    
3749     String LSCPServer::MoveDbInstrument(String Instr, String Dst) {
3750     dmsg(2,("LSCPServer: MoveDbInstrument(Instr=%s,Dst=%s)\n", Instr.c_str(), Dst.c_str()));
3751     LSCPResultSet result;
3752     #if HAVE_SQLITE3
3753     try {
3754     InstrumentsDb::GetInstrumentsDb()->MoveInstrument(Instr, Dst);
3755     } catch (Exception e) {
3756     result.Error(e);
3757     }
3758     #else
3759     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3760     #endif
3761     return result.Produce();
3762     }
3763    
3764 iliev 1187 String LSCPServer::CopyDbInstrument(String Instr, String Dst) {
3765     dmsg(2,("LSCPServer: CopyDbInstrument(Instr=%s,Dst=%s)\n", Instr.c_str(), Dst.c_str()));
3766     LSCPResultSet result;
3767     #if HAVE_SQLITE3
3768     try {
3769     InstrumentsDb::GetInstrumentsDb()->CopyInstrument(Instr, Dst);
3770     } catch (Exception e) {
3771     result.Error(e);
3772     }
3773     #else
3774     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3775     #endif
3776     return result.Produce();
3777     }
3778    
3779 iliev 1161 String LSCPServer::SetDbInstrumentDescription(String Instr, String Desc) {
3780     dmsg(2,("LSCPServer: SetDbInstrumentDescription(Instr=%s,Desc=%s)\n", Instr.c_str(), Desc.c_str()));
3781     LSCPResultSet result;
3782     #if HAVE_SQLITE3
3783     try {
3784     InstrumentsDb::GetInstrumentsDb()->SetInstrumentDescription(Instr, Desc);
3785     } catch (Exception e) {
3786     result.Error(e);
3787     }
3788     #else
3789     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3790     #endif
3791     return result.Produce();
3792     }
3793    
3794 iliev 1727 String LSCPServer::SetDbInstrumentFilePath(String OldPath, String NewPath) {
3795     dmsg(2,("LSCPServer: SetDbInstrumentFilePath(OldPath=%s,NewPath=%s)\n", OldPath.c_str(), NewPath.c_str()));
3796     LSCPResultSet result;
3797     #if HAVE_SQLITE3
3798     try {
3799     InstrumentsDb::GetInstrumentsDb()->SetInstrumentFilePath(OldPath, NewPath);
3800     } catch (Exception e) {
3801     result.Error(e);
3802     }
3803     #else
3804     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3805     #endif
3806     return result.Produce();
3807     }
3808    
3809     String LSCPServer::FindLostDbInstrumentFiles() {
3810     dmsg(2,("LSCPServer: FindLostDbInstrumentFiles()\n"));
3811     LSCPResultSet result;
3812     #if HAVE_SQLITE3
3813     try {
3814     String list;
3815     StringListPtr pLostFiles = InstrumentsDb::GetInstrumentsDb()->FindLostInstrumentFiles();
3816    
3817     for (int i = 0; i < pLostFiles->size(); i++) {
3818     if (list != "") list += ",";
3819     list += "'" + pLostFiles->at(i) + "'";
3820     }
3821    
3822     result.Add(list);
3823     } catch (Exception e) {
3824     result.Error(e);
3825     }
3826     #else
3827     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3828     #endif
3829     return result.Produce();
3830     }
3831    
3832 iliev 1187 String LSCPServer::FindDbInstrumentDirectories(String Dir, std::map<String,String> Parameters, bool Recursive) {
3833     dmsg(2,("LSCPServer: FindDbInstrumentDirectories(Dir=%s)\n", Dir.c_str()));
3834     LSCPResultSet result;
3835     #if HAVE_SQLITE3
3836     try {
3837     SearchQuery Query;
3838     std::map<String,String>::iterator iter;
3839     for (iter = Parameters.begin(); iter != Parameters.end(); iter++) {
3840     if (iter->first.compare("NAME") == 0) {
3841     Query.Name = iter->second;
3842     } else if (iter->first.compare("CREATED") == 0) {
3843     Query.SetCreated(iter->second);
3844     } else if (iter->first.compare("MODIFIED") == 0) {
3845     Query.SetModified(iter->second);
3846     } else if (iter->first.compare("DESCRIPTION") == 0) {
3847     Query.Description = iter->second;
3848     } else {
3849     throw Exception("Unknown search criteria: " + iter->first);
3850     }
3851     }
3852 iliev 1161
3853 iliev 1187 String list;
3854     StringListPtr pDirectories =
3855     InstrumentsDb::GetInstrumentsDb()->FindDirectories(Dir, &Query, Recursive);
3856    
3857     for (int i = 0; i < pDirectories->size(); i++) {
3858     if (list != "") list += ",";
3859 iliev 1345 list += "'" + InstrumentsDb::toEscapedPath(pDirectories->at(i)) + "'";
3860 iliev 1187 }
3861    
3862     result.Add(list);
3863     } catch (Exception e) {
3864     result.Error(e);
3865     }
3866     #else
3867     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3868     #endif
3869     return result.Produce();
3870     }
3871    
3872     String LSCPServer::FindDbInstruments(String Dir, std::map<String,String> Parameters, bool Recursive) {
3873     dmsg(2,("LSCPServer: FindDbInstruments(Dir=%s)\n", Dir.c_str()));
3874     LSCPResultSet result;
3875     #if HAVE_SQLITE3
3876     try {
3877     SearchQuery Query;
3878     std::map<String,String>::iterator iter;
3879     for (iter = Parameters.begin(); iter != Parameters.end(); iter++) {
3880     if (iter->first.compare("NAME") == 0) {
3881     Query.Name = iter->second;
3882     } else if (iter->first.compare("FORMAT_FAMILIES") == 0) {
3883     Query.SetFormatFamilies(iter->second);
3884     } else if (iter->first.compare("SIZE") == 0) {
3885     Query.SetSize(iter->second);
3886     } else if (iter->first.compare("CREATED") == 0) {
3887     Query.SetCreated(iter->second);
3888     } else if (iter->first.compare("MODIFIED") == 0) {
3889     Query.SetModified(iter->second);
3890     } else if (iter->first.compare("DESCRIPTION") == 0) {
3891     Query.Description = iter->second;
3892     } else if (iter->first.compare("IS_DRUM") == 0) {
3893     if (!strcasecmp(iter->second.c_str(), "true")) {
3894     Query.InstrType = SearchQuery::DRUM;
3895     } else {
3896     Query.InstrType = SearchQuery::CHROMATIC;
3897     }
3898     } else if (iter->first.compare("PRODUCT") == 0) {
3899     Query.Product = iter->second;
3900     } else if (iter->first.compare("ARTISTS") == 0) {
3901     Query.Artists = iter->second;
3902     } else if (iter->first.compare("KEYWORDS") == 0) {
3903     Query.Keywords = iter->second;
3904     } else {
3905     throw Exception("Unknown search criteria: " + iter->first);
3906     }
3907     }
3908    
3909     String list;
3910     StringListPtr pInstruments =
3911     InstrumentsDb::GetInstrumentsDb()->FindInstruments(Dir, &Query, Recursive);
3912    
3913     for (int i = 0; i < pInstruments->size(); i++) {
3914     if (list != "") list += ",";
3915 iliev 1345 list += "'" + InstrumentsDb::toEscapedPath(pInstruments->at(i)) + "'";
3916 iliev 1187 }
3917    
3918     result.Add(list);
3919     } catch (Exception e) {
3920     result.Error(e);
3921     }
3922     #else
3923     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3924     #endif
3925     return result.Produce();
3926     }
3927    
3928 iliev 1353 String LSCPServer::FormatInstrumentsDb() {
3929     dmsg(2,("LSCPServer: FormatInstrumentsDb()\n"));
3930     LSCPResultSet result;
3931     #if HAVE_SQLITE3
3932     try {
3933     InstrumentsDb::GetInstrumentsDb()->Format();
3934     } catch (Exception e) {
3935     result.Error(e);
3936     }
3937     #else
3938     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3939     #endif
3940     return result.Produce();
3941     }
3942 iliev 1187
3943 iliev 1353
3944 schoenebeck 210 /**
3945     * Will be called by the parser to enable or disable echo mode; if echo
3946     * mode is enabled, all commands from the client will (immediately) be
3947     * echoed back to the client.
3948     */
3949     String LSCPServer::SetEcho(yyparse_param_t* pSession, double boolean_value) {
3950     dmsg(2,("LSCPServer: SetEcho(val=%f)\n", boolean_value));
3951     LSCPResultSet result;
3952     try {
3953     if (boolean_value == 0) pSession->bVerbose = false;
3954     else if (boolean_value == 1) pSession->bVerbose = true;
3955 schoenebeck 880 else throw Exception("Not a boolean value, must either be 0 or 1");
3956 schoenebeck 210 }
3957 schoenebeck 880 catch (Exception e) {
3958 schoenebeck 210 result.Error(e);
3959     }
3960     return result.Produce();
3961     }
3962 persson 1765
3963     }

  ViewVC Help
Powered by ViewVC