/[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 2427 - (hide annotations) (download)
Sat Mar 2 07:03:04 2013 UTC (11 years, 1 month ago) by persson
File size: 154211 byte(s)
* code refactoring: added a lock guard class for exception safe mutex
  handling and used it everywhere appropriate

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 persson 2427 * Copyright (C) 2005 - 2013 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 capela 159 String LSCPServer::SetMIDIInputPort(uint MIDIPort, uint uiSamplerChannel) {
1782     dmsg(2,("LSCPServer: SetMIDIInputPort(MIDIPort=%d, SamplerChannel=%d)\n",MIDIPort,uiSamplerChannel));
1783 senkov 120 LSCPResultSet result;
1784 schoenebeck 53 try {
1785     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1786 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1787 capela 159 pSamplerChannel->SetMidiInputPort(MIDIPort);
1788 schoenebeck 53 }
1789 schoenebeck 880 catch (Exception e) {
1790 senkov 120 result.Error(e);
1791 schoenebeck 53 }
1792 senkov 120 return result.Produce();
1793 schoenebeck 53 }
1794    
1795 capela 159 String LSCPServer::SetMIDIInputChannel(uint MIDIChannel, uint uiSamplerChannel) {
1796     dmsg(2,("LSCPServer: SetMIDIInputChannel(MIDIChannel=%d, SamplerChannel=%d)\n",MIDIChannel,uiSamplerChannel));
1797 senkov 120 LSCPResultSet result;
1798 senkov 68 try {
1799     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1800 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1801 schoenebeck 675 pSamplerChannel->SetMidiInputChannel((midi_chan_t) MIDIChannel);
1802 senkov 68 }
1803 schoenebeck 880 catch (Exception e) {
1804 senkov 120 result.Error(e);
1805 senkov 68 }
1806 senkov 120 return result.Produce();
1807 schoenebeck 35 }
1808    
1809 capela 159 String LSCPServer::SetMIDIInputDevice(uint MIDIDeviceId, uint uiSamplerChannel) {
1810     dmsg(2,("LSCPServer: SetMIDIInputDevice(MIDIDeviceId=%d, SamplerChannel=%d)\n",MIDIDeviceId,uiSamplerChannel));
1811 schoenebeck 123 LSCPResultSet result;
1812     try {
1813 capela 159 SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1814 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1815 capela 159 std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1816 schoenebeck 880 if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1817 capela 159 MidiInputDevice* pDevice = devices[MIDIDeviceId];
1818     pSamplerChannel->SetMidiInputDevice(pDevice);
1819 schoenebeck 123 }
1820 schoenebeck 880 catch (Exception e) {
1821 schoenebeck 123 result.Error(e);
1822     }
1823     return result.Produce();
1824     }
1825    
1826 capela 159 String LSCPServer::SetMIDIInputType(String MidiInputDriver, uint uiSamplerChannel) {
1827     dmsg(2,("LSCPServer: SetMIDIInputType(String MidiInputDriver=%s, SamplerChannel=%d)\n",MidiInputDriver.c_str(),uiSamplerChannel));
1828     LSCPResultSet result;
1829     try {
1830     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1831 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1832 capela 159 // Driver type name aliasing...
1833 schoenebeck 226 if (MidiInputDriver == "Alsa") MidiInputDriver = "ALSA";
1834 capela 159 // Check if there's one MIDI input device already created
1835     // for the intended MIDI driver type (MidiInputDriver)...
1836     MidiInputDevice *pDevice = NULL;
1837     std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1838     std::map<uint, MidiInputDevice*>::iterator iter = devices.begin();
1839     for (; iter != devices.end(); iter++) {
1840     if ((iter->second)->Driver() == MidiInputDriver) {
1841     pDevice = iter->second;
1842     break;
1843     }
1844     }
1845     // If it doesn't exist, create a new one with default parameters...
1846     if (pDevice == NULL) {
1847     std::map<String,String> params;
1848     pDevice = pSampler->CreateMidiInputDevice(MidiInputDriver, params);
1849     // Make it with at least one initial port.
1850     std::map<String,DeviceCreationParameter*> parameters = pDevice->DeviceParameters();
1851     }
1852     // Must have a device...
1853     if (pDevice == NULL)
1854 schoenebeck 880 throw Exception("Internal error: could not create MIDI input device.");
1855 capela 159 // Set it as the current channel device...
1856     pSamplerChannel->SetMidiInputDevice(pDevice);
1857     }
1858 schoenebeck 880 catch (Exception e) {
1859 capela 159 result.Error(e);
1860     }
1861     return result.Produce();
1862     }
1863    
1864 schoenebeck 35 /**
1865 capela 159 * Will be called by the parser to change the MIDI input device, port and channel on which
1866     * engine of a particular sampler channel should listen to.
1867     */
1868     String LSCPServer::SetMIDIInput(uint MIDIDeviceId, uint MIDIPort, uint MIDIChannel, uint uiSamplerChannel) {
1869     dmsg(2,("LSCPServer: SetMIDIInput(MIDIDeviceId=%d, MIDIPort=%d, MIDIChannel=%d, SamplerChannel=%d)\n", MIDIDeviceId, MIDIPort, MIDIChannel, uiSamplerChannel));
1870     LSCPResultSet result;
1871     try {
1872     SamplerChannel* pSamplerChannel = pSampler->GetSamplerChannel(uiSamplerChannel);
1873 schoenebeck 880 if (!pSamplerChannel) throw Exception("Invalid sampler channel number " + ToString(uiSamplerChannel));
1874 capela 159 std::map<uint, MidiInputDevice*> devices = pSampler->GetMidiInputDevices();
1875 schoenebeck 880 if (!devices.count(MIDIDeviceId)) throw Exception("There is no MIDI input device with index " + ToString(MIDIDeviceId));
1876 capela 159 MidiInputDevice* pDevice = devices[MIDIDeviceId];
1877 schoenebeck 675 pSamplerChannel->SetMidiInput(pDevice, MIDIPort, (midi_chan_t) MIDIChannel);
1878 capela 159 }
1879 schoenebeck 880 catch (Exception e) {
1880 capela 159 result.Error(e);
1881     }
1882     return result.Produce();
1883     }
1884    
1885     /**
1886 schoenebeck 35 * Will be called by the parser to change the global volume factor on a
1887     * particular sampler channel.
1888     */
1889 schoenebeck 225 String LSCPServer::SetVolume(double dVolume, uint uiSamplerChannel) {
1890     dmsg(2,("LSCPServer: SetVolume(Volume=%f, SamplerChannel=%d)\n", dVolume, uiSamplerChannel));
1891 senkov 120 LSCPResultSet result;
1892 schoenebeck 53 try {
1893 iliev 1771 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1894 schoenebeck 411 pEngineChannel->Volume(dVolume);
1895 schoenebeck 53 }
1896 schoenebeck 880 catch (Exception e) {
1897 senkov 120 result.Error(e);
1898 schoenebeck 53 }
1899 senkov 120 return result.Produce();
1900 schoenebeck 35 }
1901    
1902     /**
1903 schoenebeck 705 * Will be called by the parser to mute/unmute particular sampler channel.
1904     */
1905     String LSCPServer::SetChannelMute(bool bMute, uint uiSamplerChannel) {
1906     dmsg(2,("LSCPServer: SetChannelMute(bMute=%d,uiSamplerChannel=%d)\n",bMute,uiSamplerChannel));
1907     LSCPResultSet result;
1908     try {
1909 iliev 1771 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1910 schoenebeck 705
1911     if(!bMute) pEngineChannel->SetMute((HasSoloChannel() && !pEngineChannel->GetSolo()) ? -1 : 0);
1912     else pEngineChannel->SetMute(1);
1913 schoenebeck 880 } catch (Exception e) {
1914 schoenebeck 705 result.Error(e);
1915     }
1916     return result.Produce();
1917     }
1918    
1919     /**
1920     * Will be called by the parser to solo particular sampler channel.
1921     */
1922     String LSCPServer::SetChannelSolo(bool bSolo, uint uiSamplerChannel) {
1923     dmsg(2,("LSCPServer: SetChannelSolo(bSolo=%d,uiSamplerChannel=%d)\n",bSolo,uiSamplerChannel));
1924     LSCPResultSet result;
1925     try {
1926 iliev 1771 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
1927 schoenebeck 705
1928     bool oldSolo = pEngineChannel->GetSolo();
1929     bool hadSoloChannel = HasSoloChannel();
1930 schoenebeck 1009
1931 schoenebeck 705 pEngineChannel->SetSolo(bSolo);
1932 schoenebeck 1009
1933 schoenebeck 705 if(!oldSolo && bSolo) {
1934     if(pEngineChannel->GetMute() == -1) pEngineChannel->SetMute(0);
1935     if(!hadSoloChannel) MuteNonSoloChannels();
1936     }
1937 schoenebeck 1009
1938 schoenebeck 705 if(oldSolo && !bSolo) {
1939     if(!HasSoloChannel()) UnmuteChannels();
1940     else if(!pEngineChannel->GetMute()) pEngineChannel->SetMute(-1);
1941     }
1942 schoenebeck 880 } catch (Exception e) {
1943 schoenebeck 705 result.Error(e);
1944     }
1945     return result.Produce();
1946     }
1947    
1948     /**
1949     * Determines whether there is at least one solo channel in the channel list.
1950     *
1951     * @returns true if there is at least one solo channel in the channel list,
1952     * false otherwise.
1953     */
1954     bool LSCPServer::HasSoloChannel() {
1955     std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
1956     std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
1957     for (; iter != channels.end(); iter++) {
1958     EngineChannel* c = iter->second->GetEngineChannel();
1959     if(c && c->GetSolo()) return true;
1960     }
1961    
1962     return false;
1963     }
1964    
1965     /**
1966     * Mutes all unmuted non-solo channels. Notice that the channels are muted
1967     * with -1 which indicates that they are muted because of the presence
1968     * of a solo channel(s). Channels muted with -1 will be automatically unmuted
1969     * when there are no solo channels left.
1970     */
1971     void LSCPServer::MuteNonSoloChannels() {
1972     dmsg(2,("LSCPServer: MuteNonSoloChannels()\n"));
1973     std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
1974     std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
1975     for (; iter != channels.end(); iter++) {
1976     EngineChannel* c = iter->second->GetEngineChannel();
1977     if(c && !c->GetSolo() && !c->GetMute()) c->SetMute(-1);
1978     }
1979     }
1980    
1981     /**
1982     * Unmutes all channels that are muted because of the presence
1983     * of a solo channel(s).
1984     */
1985     void LSCPServer::UnmuteChannels() {
1986     dmsg(2,("LSCPServer: UnmuteChannels()\n"));
1987     std::map<uint,SamplerChannel*> channels = pSampler->GetSamplerChannels();
1988     std::map<uint,SamplerChannel*>::iterator iter = channels.begin();
1989     for (; iter != channels.end(); iter++) {
1990     EngineChannel* c = iter->second->GetEngineChannel();
1991     if(c && c->GetMute() == -1) c->SetMute(0);
1992     }
1993     }
1994    
1995 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) {
1996 schoenebeck 947 dmsg(2,("LSCPServer: AddOrReplaceMIDIInstrumentMapping()\n"));
1997    
1998     midi_prog_index_t idx;
1999 schoenebeck 973 idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
2000     idx.midi_bank_lsb = MidiBank & 0x7f;
2001 schoenebeck 947 idx.midi_prog = MidiProg;
2002    
2003     MidiInstrumentMapper::entry_t entry;
2004     entry.EngineName = EngineType;
2005     entry.InstrumentFile = InstrumentFile;
2006     entry.InstrumentIndex = InstrumentIndex;
2007     entry.LoadMode = LoadMode;
2008     entry.Volume = Volume;
2009     entry.Name = Name;
2010    
2011     LSCPResultSet result;
2012     try {
2013 schoenebeck 1047 // PERSISTENT mapping commands might block for a long time, so in
2014     // that case we add/replace the mapping in another thread in case
2015     // the NON_MODAL argument was supplied, non persistent mappings
2016     // should return immediately, so we don't need to do that for them
2017     bool bInBackground = (entry.LoadMode == MidiInstrumentMapper::PERSISTENT && !bModal);
2018 schoenebeck 973 MidiInstrumentMapper::AddOrReplaceEntry(MidiMapID, idx, entry, bInBackground);
2019 schoenebeck 947 } catch (Exception e) {
2020     result.Error(e);
2021     }
2022     return result.Produce();
2023     }
2024    
2025 schoenebeck 973 String LSCPServer::RemoveMIDIInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg) {
2026 schoenebeck 947 dmsg(2,("LSCPServer: RemoveMIDIInstrumentMapping()\n"));
2027    
2028     midi_prog_index_t idx;
2029 schoenebeck 973 idx.midi_bank_msb = (MidiBank >> 7) & 0x7f;
2030     idx.midi_bank_lsb = MidiBank & 0x7f;
2031 schoenebeck 947 idx.midi_prog = MidiProg;
2032    
2033     LSCPResultSet result;
2034     try {
2035 schoenebeck 973 MidiInstrumentMapper::RemoveEntry(MidiMapID, idx);
2036 schoenebeck 947 } catch (Exception e) {
2037     result.Error(e);
2038     }
2039     return result.Produce();
2040     }
2041    
2042 schoenebeck 973 String LSCPServer::GetMidiInstrumentMappings(uint MidiMapID) {
2043     dmsg(2,("LSCPServer: GetMidiInstrumentMappings()\n"));
2044 schoenebeck 947 LSCPResultSet result;
2045 schoenebeck 973 try {
2046 iliev 1763 result.Add(MidiInstrumentMapper::GetInstrumentCount(MidiMapID));
2047 schoenebeck 973 } catch (Exception e) {
2048     result.Error(e);
2049     }
2050 schoenebeck 947 return result.Produce();
2051     }
2052    
2053 schoenebeck 973
2054     String LSCPServer::GetAllMidiInstrumentMappings() {
2055     dmsg(2,("LSCPServer: GetAllMidiInstrumentMappings()\n"));
2056     LSCPResultSet result;
2057 iliev 1763 try {
2058     result.Add(MidiInstrumentMapper::GetInstrumentCount());
2059     } catch (Exception e) {
2060     result.Error(e);
2061 schoenebeck 973 }
2062     return result.Produce();
2063     }
2064    
2065     String LSCPServer::GetMidiInstrumentMapping(uint MidiMapID, uint MidiBank, uint MidiProg) {
2066 schoenebeck 947 dmsg(2,("LSCPServer: GetMidiIstrumentMapping()\n"));
2067     LSCPResultSet result;
2068     try {
2069 iliev 1763 MidiInstrumentMapper::entry_t entry = MidiInstrumentMapper::GetEntry(MidiMapID, MidiBank, MidiProg);
2070     // convert the filename into the correct encoding as defined for LSCP
2071     // (especially in terms of special characters -> escape sequences)
2072 schoenebeck 1471 #if WIN32
2073 iliev 1763 const String instrumentFileName = Path::fromWindows(entry.InstrumentFile).toLscp();
2074 schoenebeck 1471 #else
2075 iliev 1763 // assuming POSIX
2076     const String instrumentFileName = Path::fromPosix(entry.InstrumentFile).toLscp();
2077 schoenebeck 1471 #endif
2078    
2079 iliev 1763 result.Add("NAME", _escapeLscpResponse(entry.Name));
2080     result.Add("ENGINE_NAME", entry.EngineName);
2081     result.Add("INSTRUMENT_FILE", instrumentFileName);
2082     result.Add("INSTRUMENT_NR", (int) entry.InstrumentIndex);
2083     String instrumentName;
2084     Engine* pEngine = EngineFactory::Create(entry.EngineName);
2085     if (pEngine) {
2086     if (pEngine->GetInstrumentManager()) {
2087     InstrumentManager::instrument_id_t instrID;
2088     instrID.FileName = entry.InstrumentFile;
2089     instrID.Index = entry.InstrumentIndex;
2090     instrumentName = pEngine->GetInstrumentManager()->GetInstrumentName(instrID);
2091 schoenebeck 947 }
2092 iliev 1763 EngineFactory::Destroy(pEngine);
2093 schoenebeck 947 }
2094 iliev 1763 result.Add("INSTRUMENT_NAME", _escapeLscpResponse(instrumentName));
2095     switch (entry.LoadMode) {
2096     case MidiInstrumentMapper::ON_DEMAND:
2097     result.Add("LOAD_MODE", "ON_DEMAND");
2098     break;
2099     case MidiInstrumentMapper::ON_DEMAND_HOLD:
2100     result.Add("LOAD_MODE", "ON_DEMAND_HOLD");
2101     break;
2102     case MidiInstrumentMapper::PERSISTENT:
2103     result.Add("LOAD_MODE", "PERSISTENT");
2104     break;
2105     default:
2106     throw Exception("entry reflects invalid LOAD_MODE, consider this as a bug!");
2107     }
2108     result.Add("VOLUME", entry.Volume);
2109 schoenebeck 947 } catch (Exception e) {
2110     result.Error(e);
2111     }
2112     return result.Produce();
2113     }
2114    
2115 schoenebeck 973 String LSCPServer::ListMidiInstrumentMappings(uint MidiMapID) {
2116     dmsg(2,("LSCPServer: ListMidiInstrumentMappings()\n"));
2117 schoenebeck 947 LSCPResultSet result;
2118     try {
2119     String s;
2120 schoenebeck 973 std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(MidiMapID);
2121 schoenebeck 947 std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin();
2122     for (; iter != mappings.end(); iter++) {
2123     if (s.size()) s += ",";
2124 schoenebeck 973 s += "{" + ToString(MidiMapID) + ","
2125 schoenebeck 1007 + ToString((int(iter->first.midi_bank_msb) << 7) | int(iter->first.midi_bank_lsb)) + ","
2126 schoenebeck 973 + ToString(int(iter->first.midi_prog)) + "}";
2127 schoenebeck 947 }
2128     result.Add(s);
2129     } catch (Exception e) {
2130     result.Error(e);
2131     }
2132     return result.Produce();
2133     }
2134    
2135 schoenebeck 973 String LSCPServer::ListAllMidiInstrumentMappings() {
2136     dmsg(2,("LSCPServer: ListAllMidiInstrumentMappings()\n"));
2137     LSCPResultSet result;
2138     try {
2139     std::vector<int> maps = MidiInstrumentMapper::Maps();
2140     String s;
2141     for (int i = 0; i < maps.size(); i++) {
2142     std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t> mappings = MidiInstrumentMapper::Entries(maps[i]);
2143     std::map<midi_prog_index_t,MidiInstrumentMapper::entry_t>::iterator iter = mappings.begin();
2144     for (; iter != mappings.end(); iter++) {
2145     if (s.size()) s += ",";
2146     s += "{" + ToString(maps[i]) + ","
2147 schoenebeck 1009 + ToString((int(iter->first.midi_bank_msb) << 7) | int(iter->first.midi_bank_lsb)) + ","
2148 schoenebeck 973 + ToString(int(iter->first.midi_prog)) + "}";
2149     }
2150     }
2151     result.Add(s);
2152     } catch (Exception e) {
2153     result.Error(e);
2154     }
2155     return result.Produce();
2156     }
2157    
2158     String LSCPServer::ClearMidiInstrumentMappings(uint MidiMapID) {
2159 schoenebeck 947 dmsg(2,("LSCPServer: ClearMidiInstrumentMappings()\n"));
2160     LSCPResultSet result;
2161     try {
2162 schoenebeck 973 MidiInstrumentMapper::RemoveAllEntries(MidiMapID);
2163 schoenebeck 947 } catch (Exception e) {
2164     result.Error(e);
2165     }
2166     return result.Produce();
2167     }
2168    
2169 schoenebeck 973 String LSCPServer::ClearAllMidiInstrumentMappings() {
2170     dmsg(2,("LSCPServer: ClearAllMidiInstrumentMappings()\n"));
2171     LSCPResultSet result;
2172     try {
2173     std::vector<int> maps = MidiInstrumentMapper::Maps();
2174     for (int i = 0; i < maps.size(); i++)
2175     MidiInstrumentMapper::RemoveAllEntries(maps[i]);
2176     } catch (Exception e) {
2177     result.Error(e);
2178     }
2179     return result.Produce();
2180     }
2181    
2182     String LSCPServer::AddMidiInstrumentMap(String MapName) {
2183     dmsg(2,("LSCPServer: AddMidiInstrumentMap()\n"));
2184     LSCPResultSet result;
2185     try {
2186     int MapID = MidiInstrumentMapper::AddMap(MapName);
2187     result = LSCPResultSet(MapID);
2188     } catch (Exception e) {
2189     result.Error(e);
2190     }
2191     return result.Produce();
2192     }
2193    
2194     String LSCPServer::RemoveMidiInstrumentMap(uint MidiMapID) {
2195     dmsg(2,("LSCPServer: RemoveMidiInstrumentMap()\n"));
2196     LSCPResultSet result;
2197     try {
2198     MidiInstrumentMapper::RemoveMap(MidiMapID);
2199     } catch (Exception e) {
2200     result.Error(e);
2201     }
2202     return result.Produce();
2203     }
2204    
2205     String LSCPServer::RemoveAllMidiInstrumentMaps() {
2206     dmsg(2,("LSCPServer: RemoveAllMidiInstrumentMaps()\n"));
2207     LSCPResultSet result;
2208     try {
2209     MidiInstrumentMapper::RemoveAllMaps();
2210     } catch (Exception e) {
2211     result.Error(e);
2212     }
2213     return result.Produce();
2214     }
2215    
2216     String LSCPServer::GetMidiInstrumentMaps() {
2217     dmsg(2,("LSCPServer: GetMidiInstrumentMaps()\n"));
2218     LSCPResultSet result;
2219     try {
2220     result.Add(MidiInstrumentMapper::Maps().size());
2221     } catch (Exception e) {
2222     result.Error(e);
2223     }
2224     return result.Produce();
2225     }
2226    
2227     String LSCPServer::ListMidiInstrumentMaps() {
2228     dmsg(2,("LSCPServer: ListMidiInstrumentMaps()\n"));
2229     LSCPResultSet result;
2230     try {
2231     std::vector<int> maps = MidiInstrumentMapper::Maps();
2232     String sList;
2233     for (int i = 0; i < maps.size(); i++) {
2234     if (sList != "") sList += ",";
2235     sList += ToString(maps[i]);
2236     }
2237     result.Add(sList);
2238     } catch (Exception e) {
2239     result.Error(e);
2240     }
2241     return result.Produce();
2242     }
2243    
2244     String LSCPServer::GetMidiInstrumentMap(uint MidiMapID) {
2245     dmsg(2,("LSCPServer: GetMidiInstrumentMap()\n"));
2246     LSCPResultSet result;
2247     try {
2248 schoenebeck 1399 result.Add("NAME", _escapeLscpResponse(MidiInstrumentMapper::MapName(MidiMapID)));
2249 iliev 1135 result.Add("DEFAULT", MidiInstrumentMapper::GetDefaultMap() == MidiMapID);
2250 schoenebeck 973 } catch (Exception e) {
2251     result.Error(e);
2252     }
2253     return result.Produce();
2254     }
2255    
2256     String LSCPServer::SetMidiInstrumentMapName(uint MidiMapID, String NewName) {
2257     dmsg(2,("LSCPServer: SetMidiInstrumentMapName()\n"));
2258     LSCPResultSet result;
2259     try {
2260     MidiInstrumentMapper::RenameMap(MidiMapID, NewName);
2261     } catch (Exception e) {
2262     result.Error(e);
2263     }
2264     return result.Produce();
2265     }
2266    
2267 schoenebeck 705 /**
2268 schoenebeck 973 * Set the MIDI instrument map the given sampler channel shall use for
2269     * handling MIDI program change messages. There are the following two
2270     * special (negative) values:
2271     *
2272     * - (-1) : set to NONE (ignore program changes)
2273     * - (-2) : set to DEFAULT map
2274     */
2275     String LSCPServer::SetChannelMap(uint uiSamplerChannel, int MidiMapID) {
2276     dmsg(2,("LSCPServer: SetChannelMap()\n"));
2277     LSCPResultSet result;
2278     try {
2279 iliev 1771 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2280 schoenebeck 973
2281     if (MidiMapID == -1) pEngineChannel->SetMidiInstrumentMapToNone();
2282     else if (MidiMapID == -2) pEngineChannel->SetMidiInstrumentMapToDefault();
2283     else pEngineChannel->SetMidiInstrumentMap(MidiMapID);
2284     } catch (Exception e) {
2285     result.Error(e);
2286     }
2287     return result.Produce();
2288     }
2289    
2290 schoenebeck 1001 String LSCPServer::CreateFxSend(uint uiSamplerChannel, uint MidiCtrl, String Name) {
2291     dmsg(2,("LSCPServer: CreateFxSend()\n"));
2292     LSCPResultSet result;
2293     try {
2294 iliev 1135 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2295 schoenebeck 1252
2296 schoenebeck 1001 FxSend* pFxSend = pEngineChannel->AddFxSend(MidiCtrl, Name);
2297     if (!pFxSend) throw Exception("Could not add FxSend, don't ask, I don't know why (probably a bug)");
2298    
2299     result = LSCPResultSet(pFxSend->Id()); // success
2300     } catch (Exception e) {
2301     result.Error(e);
2302     }
2303     return result.Produce();
2304     }
2305    
2306     String LSCPServer::DestroyFxSend(uint uiSamplerChannel, uint FxSendID) {
2307     dmsg(2,("LSCPServer: DestroyFxSend()\n"));
2308     LSCPResultSet result;
2309     try {
2310 iliev 1135 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2311 schoenebeck 1001
2312     FxSend* pFxSend = NULL;
2313     for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2314     if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
2315     pFxSend = pEngineChannel->GetFxSend(i);
2316     break;
2317     }
2318     }
2319     if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
2320     pEngineChannel->RemoveFxSend(pFxSend);
2321     } catch (Exception e) {
2322     result.Error(e);
2323     }
2324     return result.Produce();
2325     }
2326    
2327     String LSCPServer::GetFxSends(uint uiSamplerChannel) {
2328     dmsg(2,("LSCPServer: GetFxSends()\n"));
2329     LSCPResultSet result;
2330     try {
2331 iliev 1135 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2332 schoenebeck 1001
2333     result.Add(pEngineChannel->GetFxSendCount());
2334     } catch (Exception e) {
2335     result.Error(e);
2336     }
2337     return result.Produce();
2338     }
2339    
2340     String LSCPServer::ListFxSends(uint uiSamplerChannel) {
2341     dmsg(2,("LSCPServer: ListFxSends()\n"));
2342     LSCPResultSet result;
2343     String list;
2344     try {
2345 iliev 1135 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2346 schoenebeck 1001
2347     for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2348     FxSend* pFxSend = pEngineChannel->GetFxSend(i);
2349     if (list != "") list += ",";
2350     list += ToString(pFxSend->Id());
2351     }
2352     result.Add(list);
2353     } catch (Exception e) {
2354     result.Error(e);
2355     }
2356     return result.Produce();
2357     }
2358    
2359 iliev 1135 FxSend* LSCPServer::GetFxSend(uint uiSamplerChannel, uint FxSendID) {
2360     EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2361    
2362     FxSend* pFxSend = NULL;
2363     for (int i = 0; i < pEngineChannel->GetFxSendCount(); i++) {
2364     if (pEngineChannel->GetFxSend(i)->Id() == FxSendID) {
2365     pFxSend = pEngineChannel->GetFxSend(i);
2366     break;
2367     }
2368     }
2369     if (!pFxSend) throw Exception("There is no FxSend with that ID on the given sampler channel");
2370     return pFxSend;
2371     }
2372    
2373 schoenebeck 1001 String LSCPServer::GetFxSendInfo(uint uiSamplerChannel, uint FxSendID) {
2374     dmsg(2,("LSCPServer: GetFxSendInfo()\n"));
2375     LSCPResultSet result;
2376     try {
2377 iliev 1135 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2378     FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2379 schoenebeck 1252
2380 schoenebeck 1001 // gather audio routing informations
2381     String AudioRouting;
2382     for (int chan = 0; chan < pEngineChannel->Channels(); chan++) {
2383     if (AudioRouting != "") AudioRouting += ",";
2384     AudioRouting += ToString(pFxSend->DestinationChannel(chan));
2385     }
2386    
2387 schoenebeck 2137 const String sEffectRouting =
2388     (pFxSend->DestinationEffectChain() >= 0 && pFxSend->DestinationEffectChainPosition() >= 0)
2389     ? ToString(pFxSend->DestinationEffectChain()) + "," + ToString(pFxSend->DestinationEffectChainPosition())
2390     : "NONE";
2391    
2392 schoenebeck 1001 // success
2393 schoenebeck 1399 result.Add("NAME", _escapeLscpResponse(pFxSend->Name()));
2394 schoenebeck 1026 result.Add("MIDI_CONTROLLER", pFxSend->MidiController());
2395     result.Add("LEVEL", ToString(pFxSend->Level()));
2396 schoenebeck 1001 result.Add("AUDIO_OUTPUT_ROUTING", AudioRouting);
2397 schoenebeck 2140 result.Add("EFFECT", sEffectRouting);
2398 schoenebeck 1001 } catch (Exception e) {
2399     result.Error(e);
2400     }
2401     return result.Produce();
2402     }
2403    
2404 iliev 1135 String LSCPServer::SetFxSendName(uint uiSamplerChannel, uint FxSendID, String Name) {
2405     dmsg(2,("LSCPServer: SetFxSendName()\n"));
2406     LSCPResultSet result;
2407     try {
2408     FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2409    
2410     pFxSend->SetName(Name);
2411     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2412     } catch (Exception e) {
2413     result.Error(e);
2414     }
2415     return result.Produce();
2416     }
2417    
2418 schoenebeck 1001 String LSCPServer::SetFxSendAudioOutputChannel(uint uiSamplerChannel, uint FxSendID, uint FxSendChannel, uint DeviceChannel) {
2419     dmsg(2,("LSCPServer: SetFxSendAudioOutputChannel()\n"));
2420     LSCPResultSet result;
2421     try {
2422 iliev 1135 FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2423 schoenebeck 1001
2424     pFxSend->SetDestinationChannel(FxSendChannel, DeviceChannel);
2425 iliev 1108 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2426 schoenebeck 1001 } catch (Exception e) {
2427     result.Error(e);
2428     }
2429     return result.Produce();
2430     }
2431    
2432 schoenebeck 1026 String LSCPServer::SetFxSendMidiController(uint uiSamplerChannel, uint FxSendID, uint MidiController) {
2433     dmsg(2,("LSCPServer: SetFxSendMidiController()\n"));
2434     LSCPResultSet result;
2435     try {
2436 iliev 1135 FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2437 schoenebeck 1026
2438     pFxSend->SetMidiController(MidiController);
2439 iliev 1108 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2440 schoenebeck 1026 } catch (Exception e) {
2441     result.Error(e);
2442     }
2443     return result.Produce();
2444     }
2445    
2446     String LSCPServer::SetFxSendLevel(uint uiSamplerChannel, uint FxSendID, double dLevel) {
2447     dmsg(2,("LSCPServer: SetFxSendLevel()\n"));
2448     LSCPResultSet result;
2449     try {
2450 iliev 1135 FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2451 schoenebeck 1026
2452     pFxSend->SetLevel((float)dLevel);
2453 iliev 1108 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2454 schoenebeck 1026 } catch (Exception e) {
2455     result.Error(e);
2456     }
2457     return result.Produce();
2458     }
2459    
2460 schoenebeck 2137 String LSCPServer::SetFxSendEffect(uint uiSamplerChannel, uint FxSendID, int iSendEffectChain, int iEffectChainPosition) {
2461     dmsg(2,("LSCPServer: SetFxSendEffect(%d,%d)\n", iSendEffectChain, iEffectChainPosition));
2462     LSCPResultSet result;
2463     try {
2464     FxSend* pFxSend = GetFxSend(uiSamplerChannel, FxSendID);
2465    
2466     pFxSend->SetDestinationEffect(iSendEffectChain, iEffectChainPosition);
2467     LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_send_info, uiSamplerChannel, FxSendID));
2468     } catch (Exception e) {
2469     result.Error(e);
2470     }
2471     return result.Produce();
2472     }
2473    
2474 schoenebeck 2135 String LSCPServer::GetAvailableEffects() {
2475     dmsg(2,("LSCPServer: GetAvailableEffects()\n"));
2476     LSCPResultSet result;
2477     try {
2478     int n = EffectFactory::AvailableEffectsCount();
2479     result.Add(n);
2480     }
2481     catch (Exception e) {
2482     result.Error(e);
2483     }
2484     return result.Produce();
2485     }
2486    
2487     String LSCPServer::ListAvailableEffects() {
2488     dmsg(2,("LSCPServer: ListAvailableEffects()\n"));
2489     LSCPResultSet result;
2490     String list;
2491     try {
2492     //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
2493     int n = EffectFactory::AvailableEffectsCount();
2494     for (int i = 0; i < n; i++) {
2495     if (i) list += ",";
2496     list += ToString(i);
2497     }
2498     }
2499     catch (Exception e) {
2500     result.Error(e);
2501     }
2502     result.Add(list);
2503     return result.Produce();
2504     }
2505    
2506     String LSCPServer::GetEffectInfo(int iEffectIndex) {
2507     dmsg(2,("LSCPServer: GetEffectInfo(%d)\n", iEffectIndex));
2508     LSCPResultSet result;
2509     try {
2510     EffectInfo* pEffectInfo = EffectFactory::GetEffectInfo(iEffectIndex);
2511     if (!pEffectInfo)
2512     throw Exception("There is no effect with index " + ToString(iEffectIndex));
2513    
2514     // convert the filename into the correct encoding as defined for LSCP
2515     // (especially in terms of special characters -> escape sequences)
2516     #if WIN32
2517     const String dllFileName = Path::fromWindows(pEffectInfo->Module()).toLscp();
2518     #else
2519     // assuming POSIX
2520     const String dllFileName = Path::fromPosix(pEffectInfo->Module()).toLscp();
2521     #endif
2522    
2523     result.Add("SYSTEM", pEffectInfo->EffectSystem());
2524     result.Add("MODULE", dllFileName);
2525     result.Add("NAME", _escapeLscpResponse(pEffectInfo->Name()));
2526     result.Add("DESCRIPTION", _escapeLscpResponse(pEffectInfo->Description()));
2527     }
2528     catch (Exception e) {
2529     result.Error(e);
2530     }
2531     return result.Produce();
2532     }
2533    
2534 schoenebeck 2137 String LSCPServer::GetEffectInstanceInfo(int iEffectInstance) {
2535     dmsg(2,("LSCPServer: GetEffectInstanceInfo(%d)\n", iEffectInstance));
2536 schoenebeck 2135 LSCPResultSet result;
2537     try {
2538 schoenebeck 2137 Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2539 schoenebeck 2135 if (!pEffect)
2540 schoenebeck 2137 throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2541 schoenebeck 2135
2542     EffectInfo* pEffectInfo = pEffect->GetEffectInfo();
2543    
2544     // convert the filename into the correct encoding as defined for LSCP
2545     // (especially in terms of special characters -> escape sequences)
2546     #if WIN32
2547     const String dllFileName = Path::fromWindows(pEffectInfo->Module()).toLscp();
2548     #else
2549     // assuming POSIX
2550     const String dllFileName = Path::fromPosix(pEffectInfo->Module()).toLscp();
2551     #endif
2552    
2553     result.Add("SYSTEM", pEffectInfo->EffectSystem());
2554     result.Add("MODULE", dllFileName);
2555     result.Add("NAME", _escapeLscpResponse(pEffectInfo->Name()));
2556     result.Add("DESCRIPTION", _escapeLscpResponse(pEffectInfo->Description()));
2557     result.Add("INPUT_CONTROLS", ToString(pEffect->InputControlCount()));
2558     }
2559     catch (Exception e) {
2560     result.Error(e);
2561     }
2562     return result.Produce();
2563     }
2564    
2565 schoenebeck 2137 String LSCPServer::GetEffectInstanceInputControlInfo(int iEffectInstance, int iInputControlIndex) {
2566     dmsg(2,("LSCPServer: GetEffectInstanceInputControlInfo(%d,%d)\n", iEffectInstance, iInputControlIndex));
2567 schoenebeck 2135 LSCPResultSet result;
2568     try {
2569 schoenebeck 2137 Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2570 schoenebeck 2135 if (!pEffect)
2571 schoenebeck 2137 throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2572 schoenebeck 2135
2573     EffectControl* pEffectControl = pEffect->InputControl(iInputControlIndex);
2574     if (!pEffectControl)
2575     throw Exception(
2576 schoenebeck 2137 "Effect instance " + ToString(iEffectInstance) +
2577 schoenebeck 2135 " does not have an input control with index " +
2578     ToString(iInputControlIndex)
2579     );
2580    
2581     result.Add("DESCRIPTION", _escapeLscpResponse(pEffectControl->Description()));
2582     result.Add("VALUE", pEffectControl->Value());
2583     if (pEffectControl->MinValue())
2584     result.Add("RANGE_MIN", *pEffectControl->MinValue());
2585     if (pEffectControl->MaxValue())
2586     result.Add("RANGE_MAX", *pEffectControl->MaxValue());
2587     if (!pEffectControl->Possibilities().empty())
2588     result.Add("POSSIBILITIES", pEffectControl->Possibilities());
2589     if (pEffectControl->DefaultValue())
2590     result.Add("DEFAULT", *pEffectControl->DefaultValue());
2591     } catch (Exception e) {
2592     result.Error(e);
2593     }
2594     return result.Produce();
2595     }
2596    
2597 schoenebeck 2137 String LSCPServer::SetEffectInstanceInputControlValue(int iEffectInstance, int iInputControlIndex, double dValue) {
2598     dmsg(2,("LSCPServer: SetEffectInstanceInputControlValue(%d,%d,%f)\n", iEffectInstance, iInputControlIndex, dValue));
2599 schoenebeck 2135 LSCPResultSet result;
2600     try {
2601 schoenebeck 2137 Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2602 schoenebeck 2135 if (!pEffect)
2603 schoenebeck 2137 throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2604 schoenebeck 2135
2605     EffectControl* pEffectControl = pEffect->InputControl(iInputControlIndex);
2606     if (!pEffectControl)
2607     throw Exception(
2608 schoenebeck 2137 "Effect instance " + ToString(iEffectInstance) +
2609 schoenebeck 2135 " does not have an input control with index " +
2610     ToString(iInputControlIndex)
2611     );
2612    
2613     pEffectControl->SetValue(dValue);
2614 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_info, iEffectInstance));
2615 schoenebeck 2135 } catch (Exception e) {
2616     result.Error(e);
2617     }
2618     return result.Produce();
2619     }
2620    
2621 schoenebeck 2137 String LSCPServer::CreateEffectInstance(int iEffectIndex) {
2622     dmsg(2,("LSCPServer: CreateEffectInstance(%d)\n", iEffectIndex));
2623 schoenebeck 2135 LSCPResultSet result;
2624     try {
2625 schoenebeck 2137 EffectInfo* pEffectInfo = EffectFactory::GetEffectInfo(iEffectIndex);
2626 schoenebeck 2135 if (!pEffectInfo)
2627 schoenebeck 2137 throw Exception("There is no effect with index " + ToString(iEffectIndex));
2628 schoenebeck 2135 Effect* pEffect = EffectFactory::Create(pEffectInfo);
2629 schoenebeck 2138 result = pEffect->ID(); // success
2630 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_count, EffectFactory::EffectInstancesCount()));
2631 schoenebeck 2135 } catch (Exception e) {
2632     result.Error(e);
2633     }
2634     return result.Produce();
2635     }
2636    
2637     String LSCPServer::CreateEffectInstance(String effectSystem, String module, String effectName) {
2638 schoenebeck 2137 dmsg(2,("LSCPServer: CreateEffectInstance('%s','%s','%s')\n", effectSystem.c_str(), module.c_str(), effectName.c_str()));
2639 schoenebeck 2135 LSCPResultSet result;
2640     try {
2641     // to allow loading the same LSCP session file on different systems
2642     // successfully, probably with different effect plugin DLL paths or even
2643     // running completely different operating systems, we do the following
2644     // for finding the right effect:
2645     //
2646     // first try to search for an exact match of the effect plugin DLL
2647     // (a.k.a 'module'), to avoid picking the wrong DLL with the same
2648     // effect name ...
2649     EffectInfo* pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_MATCH_EXACTLY);
2650     // ... if no effect with exactly matchin DLL filename was found, then
2651     // try to lower the restrictions of matching the effect plugin DLL
2652     // filename and try again and again ...
2653     if (!pEffectInfo) {
2654     dmsg(2,("no exact module match, trying MODULE_IGNORE_PATH\n"));
2655     pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_PATH);
2656     }
2657     if (!pEffectInfo) {
2658     dmsg(2,("no module match, trying MODULE_IGNORE_PATH | MODULE_IGNORE_CASE\n"));
2659     pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_PATH | EffectFactory::MODULE_IGNORE_CASE);
2660     }
2661     if (!pEffectInfo) {
2662     dmsg(2,("no module match, trying MODULE_IGNORE_PATH | MODULE_IGNORE_CASE | MODULE_IGNORE_EXTENSION\n"));
2663     pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_PATH | EffectFactory::MODULE_IGNORE_CASE | EffectFactory::MODULE_IGNORE_EXTENSION);
2664     }
2665     // ... if there was still no effect found, then completely ignore the
2666     // DLL plugin filename argument and just search for the matching effect
2667     // system type and effect name
2668     if (!pEffectInfo) {
2669     dmsg(2,("no module match, trying MODULE_IGNORE_ALL\n"));
2670     pEffectInfo = EffectFactory::GetEffectInfo(effectSystem, module, effectName, EffectFactory::MODULE_IGNORE_ALL);
2671     }
2672     if (!pEffectInfo)
2673     throw Exception("There is no such effect '" + effectSystem + "' '" + module + "' '" + effectName + "'");
2674    
2675     Effect* pEffect = EffectFactory::Create(pEffectInfo);
2676     result = LSCPResultSet(pEffect->ID());
2677 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_count, EffectFactory::EffectInstancesCount()));
2678 schoenebeck 2135 } catch (Exception e) {
2679     result.Error(e);
2680     }
2681     return result.Produce();
2682     }
2683    
2684 schoenebeck 2137 String LSCPServer::DestroyEffectInstance(int iEffectInstance) {
2685     dmsg(2,("LSCPServer: DestroyEffectInstance(%d)\n", iEffectInstance));
2686 schoenebeck 2135 LSCPResultSet result;
2687     try {
2688 schoenebeck 2137 Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2689 schoenebeck 2135 if (!pEffect)
2690 schoenebeck 2137 throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2691 schoenebeck 2135 EffectFactory::Destroy(pEffect);
2692 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_fx_instance_count, EffectFactory::EffectInstancesCount()));
2693 schoenebeck 2135 } catch (Exception e) {
2694     result.Error(e);
2695     }
2696     return result.Produce();
2697     }
2698    
2699     String LSCPServer::GetEffectInstances() {
2700     dmsg(2,("LSCPServer: GetEffectInstances()\n"));
2701     LSCPResultSet result;
2702     try {
2703     int n = EffectFactory::EffectInstancesCount();
2704     result.Add(n);
2705     } catch (Exception e) {
2706     result.Error(e);
2707     }
2708     return result.Produce();
2709     }
2710    
2711     String LSCPServer::ListEffectInstances() {
2712     dmsg(2,("LSCPServer: ListEffectInstances()\n"));
2713     LSCPResultSet result;
2714     String list;
2715     try {
2716     int n = EffectFactory::EffectInstancesCount();
2717     for (int i = 0; i < n; i++) {
2718     Effect* pEffect = EffectFactory::GetEffectInstance(i);
2719     if (i) list += ",";
2720     list += ToString(pEffect->ID());
2721     }
2722     } catch (Exception e) {
2723     result.Error(e);
2724     }
2725     result.Add(list);
2726     return result.Produce();
2727     }
2728    
2729 schoenebeck 2137 String LSCPServer::GetSendEffectChains(int iAudioOutputDevice) {
2730     dmsg(2,("LSCPServer: GetSendEffectChains(%d)\n", iAudioOutputDevice));
2731 schoenebeck 2135 LSCPResultSet result;
2732     try {
2733     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2734     if (!devices.count(iAudioOutputDevice))
2735     throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2736     AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2737 schoenebeck 2137 int n = pDevice->SendEffectChainCount();
2738 schoenebeck 2135 result.Add(n);
2739     } catch (Exception e) {
2740     result.Error(e);
2741     }
2742     return result.Produce();
2743     }
2744    
2745 schoenebeck 2137 String LSCPServer::ListSendEffectChains(int iAudioOutputDevice) {
2746     dmsg(2,("LSCPServer: ListSendEffectChains(%d)\n", iAudioOutputDevice));
2747 schoenebeck 2135 LSCPResultSet result;
2748     String list;
2749     try {
2750     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2751     if (!devices.count(iAudioOutputDevice))
2752     throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2753     AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2754 schoenebeck 2137 int n = pDevice->SendEffectChainCount();
2755 schoenebeck 2135 for (int i = 0; i < n; i++) {
2756 schoenebeck 2137 EffectChain* pEffectChain = pDevice->SendEffectChain(i);
2757 schoenebeck 2135 if (i) list += ",";
2758     list += ToString(pEffectChain->ID());
2759     }
2760     } catch (Exception e) {
2761     result.Error(e);
2762     }
2763     result.Add(list);
2764     return result.Produce();
2765     }
2766    
2767 schoenebeck 2137 String LSCPServer::AddSendEffectChain(int iAudioOutputDevice) {
2768     dmsg(2,("LSCPServer: AddSendEffectChain(%d)\n", iAudioOutputDevice));
2769 schoenebeck 2135 LSCPResultSet result;
2770     try {
2771     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2772     if (!devices.count(iAudioOutputDevice))
2773     throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2774     AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2775 schoenebeck 2137 EffectChain* pEffectChain = pDevice->AddSendEffectChain();
2776 schoenebeck 2138 result = pEffectChain->ID();
2777 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_count, iAudioOutputDevice, pDevice->SendEffectChainCount()));
2778 schoenebeck 2135 } catch (Exception e) {
2779     result.Error(e);
2780     }
2781     return result.Produce();
2782     }
2783    
2784 schoenebeck 2137 String LSCPServer::RemoveSendEffectChain(int iAudioOutputDevice, int iSendEffectChain) {
2785     dmsg(2,("LSCPServer: RemoveSendEffectChain(%d,%d)\n", iAudioOutputDevice, iSendEffectChain));
2786 schoenebeck 2135 LSCPResultSet result;
2787     try {
2788     std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2789     if (!devices.count(iAudioOutputDevice))
2790     throw Exception("There is no audio output device with index " + ToString(iAudioOutputDevice) + ".");
2791 iliev 2198
2792     std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();
2793     std::set<EngineChannel*>::iterator itEngineChannel = engineChannels.begin();
2794     std::set<EngineChannel*>::iterator itEnd = engineChannels.end();
2795     for (; itEngineChannel != itEnd; ++itEngineChannel) {
2796     AudioOutputDevice* pDev = (*itEngineChannel)->GetAudioOutputDevice();
2797     if (pDev != NULL && pDev->deviceId() == iAudioOutputDevice) {
2798     for (int i = 0; i < (*itEngineChannel)->GetFxSendCount(); i++) {
2799     FxSend* fxs = (*itEngineChannel)->GetFxSend(i);
2800     if(fxs != NULL && fxs->DestinationEffectChain() == iSendEffectChain) {
2801     throw Exception("The effect chain is still in use by channel " + ToString((*itEngineChannel)->GetSamplerChannel()->Index()));
2802     }
2803     }
2804     }
2805     }
2806    
2807 schoenebeck 2135 AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2808 schoenebeck 2137 for (int i = 0; i < pDevice->SendEffectChainCount(); i++) {
2809     EffectChain* pEffectChain = pDevice->SendEffectChain(i);
2810     if (pEffectChain->ID() == iSendEffectChain) {
2811     pDevice->RemoveSendEffectChain(i);
2812 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_count, iAudioOutputDevice, pDevice->SendEffectChainCount()));
2813 schoenebeck 2135 return result.Produce();
2814     }
2815     }
2816     throw Exception(
2817 schoenebeck 2137 "There is no send effect chain with ID " +
2818     ToString(iSendEffectChain) + " for audio output device " +
2819 schoenebeck 2135 ToString(iAudioOutputDevice) + "."
2820     );
2821     } catch (Exception e) {
2822     result.Error(e);
2823     }
2824     return result.Produce();
2825     }
2826    
2827 schoenebeck 2137 static EffectChain* _getSendEffectChain(Sampler* pSampler, int iAudioOutputDevice, int iSendEffectChain) throw (Exception) {
2828 schoenebeck 2135 std::map<uint,AudioOutputDevice*> devices = pSampler->GetAudioOutputDevices();
2829     if (!devices.count(iAudioOutputDevice))
2830     throw Exception(
2831     "There is no audio output device with index " +
2832     ToString(iAudioOutputDevice) + "."
2833     );
2834     AudioOutputDevice* pDevice = devices[iAudioOutputDevice];
2835 iliev 2198 EffectChain* pEffectChain = pDevice->SendEffectChainByID(iSendEffectChain);
2836     if(pEffectChain != NULL) return pEffectChain;
2837 schoenebeck 2135 throw Exception(
2838 schoenebeck 2137 "There is no send effect chain with ID " +
2839     ToString(iSendEffectChain) + " for audio output device " +
2840 schoenebeck 2135 ToString(iAudioOutputDevice) + "."
2841     );
2842     }
2843    
2844 schoenebeck 2137 String LSCPServer::GetSendEffectChainInfo(int iAudioOutputDevice, int iSendEffectChain) {
2845     dmsg(2,("LSCPServer: GetSendEffectChainInfo(%d,%d)\n", iAudioOutputDevice, iSendEffectChain));
2846 schoenebeck 2135 LSCPResultSet result;
2847     try {
2848     EffectChain* pEffectChain =
2849 schoenebeck 2137 _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
2850 schoenebeck 2135 String sEffectSequence;
2851     for (int i = 0; i < pEffectChain->EffectCount(); i++) {
2852     if (i) sEffectSequence += ",";
2853     sEffectSequence += ToString(pEffectChain->GetEffect(i)->ID());
2854     }
2855     result.Add("EFFECT_COUNT", pEffectChain->EffectCount());
2856     result.Add("EFFECT_SEQUENCE", sEffectSequence);
2857     } catch (Exception e) {
2858     result.Error(e);
2859     }
2860     return result.Produce();
2861     }
2862    
2863 schoenebeck 2137 String LSCPServer::AppendSendEffectChainEffect(int iAudioOutputDevice, int iSendEffectChain, int iEffectInstance) {
2864     dmsg(2,("LSCPServer: AppendSendEffectChainEffect(%d,%d,%d)\n", iAudioOutputDevice, iSendEffectChain, iEffectInstance));
2865 schoenebeck 2135 LSCPResultSet result;
2866     try {
2867     EffectChain* pEffectChain =
2868 schoenebeck 2137 _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
2869 schoenebeck 2135 Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2870     if (!pEffect)
2871 schoenebeck 2137 throw Exception("There is no effect instance with ID " + ToString(iEffectInstance));
2872 schoenebeck 2135 pEffectChain->AppendEffect(pEffect);
2873 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_info, iAudioOutputDevice, iSendEffectChain, pEffectChain->EffectCount()));
2874 schoenebeck 2135 } catch (Exception e) {
2875     result.Error(e);
2876     }
2877     return result.Produce();
2878     }
2879    
2880 schoenebeck 2137 String LSCPServer::InsertSendEffectChainEffect(int iAudioOutputDevice, int iSendEffectChain, int iEffectChainPosition, int iEffectInstance) {
2881     dmsg(2,("LSCPServer: InsertSendEffectChainEffect(%d,%d,%d,%d)\n", iAudioOutputDevice, iSendEffectChain, iEffectChainPosition, iEffectInstance));
2882 schoenebeck 2135 LSCPResultSet result;
2883     try {
2884     EffectChain* pEffectChain =
2885 schoenebeck 2137 _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
2886 schoenebeck 2135 Effect* pEffect = EffectFactory::GetEffectInstanceByID(iEffectInstance);
2887     if (!pEffect)
2888     throw Exception("There is no effect instance with index " + ToString(iEffectInstance));
2889     pEffectChain->InsertEffect(pEffect, iEffectChainPosition);
2890 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_info, iAudioOutputDevice, iSendEffectChain, pEffectChain->EffectCount()));
2891 schoenebeck 2135 } catch (Exception e) {
2892     result.Error(e);
2893     }
2894     return result.Produce();
2895     }
2896    
2897 schoenebeck 2137 String LSCPServer::RemoveSendEffectChainEffect(int iAudioOutputDevice, int iSendEffectChain, int iEffectChainPosition) {
2898     dmsg(2,("LSCPServer: RemoveSendEffectChainEffect(%d,%d,%d)\n", iAudioOutputDevice, iSendEffectChain, iEffectChainPosition));
2899 schoenebeck 2135 LSCPResultSet result;
2900     try {
2901     EffectChain* pEffectChain =
2902 schoenebeck 2137 _getSendEffectChain(pSampler, iAudioOutputDevice, iSendEffectChain);
2903 iliev 2198
2904     std::set<EngineChannel*> engineChannels = EngineChannelFactory::EngineChannelInstances();
2905     std::set<EngineChannel*>::iterator itEngineChannel = engineChannels.begin();
2906     std::set<EngineChannel*>::iterator itEnd = engineChannels.end();
2907     for (; itEngineChannel != itEnd; ++itEngineChannel) {
2908     AudioOutputDevice* pDev = (*itEngineChannel)->GetAudioOutputDevice();
2909     if (pDev != NULL && pDev->deviceId() == iAudioOutputDevice) {
2910     for (int i = 0; i < (*itEngineChannel)->GetFxSendCount(); i++) {
2911     FxSend* fxs = (*itEngineChannel)->GetFxSend(i);
2912     if(fxs != NULL && fxs->DestinationEffectChain() == iSendEffectChain && fxs->DestinationEffectChainPosition() == iEffectChainPosition) {
2913     throw Exception("The effect instance is still in use by channel " + ToString((*itEngineChannel)->GetSamplerChannel()->Index()));
2914     }
2915     }
2916     }
2917     }
2918    
2919 schoenebeck 2137 pEffectChain->RemoveEffect(iEffectChainPosition);
2920 iliev 2188 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_send_fx_chain_info, iAudioOutputDevice, iSendEffectChain, pEffectChain->EffectCount()));
2921 schoenebeck 2135 } catch (Exception e) {
2922     result.Error(e);
2923     }
2924     return result.Produce();
2925     }
2926    
2927 schoenebeck 1212 String LSCPServer::EditSamplerChannelInstrument(uint uiSamplerChannel) {
2928     dmsg(2,("LSCPServer: EditSamplerChannelInstrument(SamplerChannel=%d)\n", uiSamplerChannel));
2929     LSCPResultSet result;
2930     try {
2931 iliev 1771 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2932 iliev 1337 if (pEngineChannel->InstrumentStatus() < 0) throw Exception("No instrument loaded to sampler channel");
2933 schoenebeck 1212 Engine* pEngine = pEngineChannel->GetEngine();
2934     InstrumentManager* pInstrumentManager = pEngine->GetInstrumentManager();
2935     if (!pInstrumentManager) throw Exception("Engine does not provide an instrument manager");
2936     InstrumentManager::instrument_id_t instrumentID;
2937     instrumentID.FileName = pEngineChannel->InstrumentFileName();
2938     instrumentID.Index = pEngineChannel->InstrumentIndex();
2939     pInstrumentManager->LaunchInstrumentEditor(instrumentID);
2940     } catch (Exception e) {
2941     result.Error(e);
2942     }
2943     return result.Produce();
2944     }
2945    
2946 iliev 1771 String LSCPServer::SendChannelMidiData(String MidiMsg, uint uiSamplerChannel, uint Arg1, uint Arg2) {
2947     dmsg(2,("LSCPServer: SendChannelMidiData(MidiMsg=%s,uiSamplerChannel=%d,Arg1=%d,Arg2=%d)\n", MidiMsg.c_str(), uiSamplerChannel, Arg1, Arg2));
2948     LSCPResultSet result;
2949     try {
2950     EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2951    
2952     if (Arg1 > 127 || Arg2 > 127) {
2953     throw Exception("Invalid MIDI message");
2954     }
2955    
2956     VirtualMidiDevice* pMidiDevice = NULL;
2957     std::vector<EventHandler::midi_listener_entry>::iterator iter = eventHandler.channelMidiListeners.begin();
2958     for (; iter != eventHandler.channelMidiListeners.end(); ++iter) {
2959     if ((*iter).pEngineChannel == pEngineChannel) {
2960     pMidiDevice = (*iter).pMidiListener;
2961     break;
2962     }
2963     }
2964    
2965     if(pMidiDevice == NULL) throw Exception("Couldn't find virtual MIDI device");
2966    
2967     if (MidiMsg == "NOTE_ON") {
2968 iliev 1774 pMidiDevice->SendNoteOnToDevice(Arg1, Arg2);
2969 iliev 1771 bool b = pMidiDevice->SendNoteOnToSampler(Arg1, Arg2);
2970     if (!b) throw Exception("MIDI event failed: " + MidiMsg + " " + ToString(Arg1) + " " + ToString(Arg2));
2971     } else if (MidiMsg == "NOTE_OFF") {
2972 iliev 1774 pMidiDevice->SendNoteOffToDevice(Arg1, Arg2);
2973 iliev 1771 bool b = pMidiDevice->SendNoteOffToSampler(Arg1, Arg2);
2974     if (!b) throw Exception("MIDI event failed: " + MidiMsg + " " + ToString(Arg1) + " " + ToString(Arg2));
2975 schoenebeck 2025 } else if (MidiMsg == "CC") {
2976     pMidiDevice->SendCCToDevice(Arg1, Arg2);
2977     bool b = pMidiDevice->SendCCToSampler(Arg1, Arg2);
2978     if (!b) throw Exception("MIDI event failed: " + MidiMsg + " " + ToString(Arg1) + " " + ToString(Arg2));
2979 iliev 1771 } else {
2980     throw Exception("Unknown MIDI message type: " + MidiMsg);
2981     }
2982     } catch (Exception e) {
2983     result.Error(e);
2984     }
2985     return result.Produce();
2986     }
2987    
2988 schoenebeck 973 /**
2989 schoenebeck 35 * Will be called by the parser to reset a particular sampler channel.
2990     */
2991 schoenebeck 53 String LSCPServer::ResetChannel(uint uiSamplerChannel) {
2992     dmsg(2,("LSCPServer: ResetChannel(SamplerChannel=%d)\n", uiSamplerChannel));
2993 senkov 120 LSCPResultSet result;
2994 schoenebeck 53 try {
2995 iliev 1771 EngineChannel* pEngineChannel = GetEngineChannel(uiSamplerChannel);
2996 schoenebeck 670 pEngineChannel->Reset();
2997 schoenebeck 53 }
2998 schoenebeck 880 catch (Exception e) {
2999 senkov 120 result.Error(e);
3000 schoenebeck 53 }
3001 senkov 120 return result.Produce();
3002 schoenebeck 35 }
3003    
3004     /**
3005 schoenebeck 212 * Will be called by the parser to reset the whole sampler.
3006     */
3007     String LSCPServer::ResetSampler() {
3008     dmsg(2,("LSCPServer: ResetSampler()\n"));
3009     pSampler->Reset();
3010     LSCPResultSet result;
3011     return result.Produce();
3012     }
3013    
3014     /**
3015 schoenebeck 563 * Will be called by the parser to return general informations about this
3016     * sampler.
3017     */
3018     String LSCPServer::GetServerInfo() {
3019     dmsg(2,("LSCPServer: GetServerInfo()\n"));
3020 schoenebeck 1399 const std::string description =
3021     _escapeLscpResponse("LinuxSampler - modular, streaming capable sampler");
3022 schoenebeck 563 LSCPResultSet result;
3023 schoenebeck 1399 result.Add("DESCRIPTION", description);
3024 schoenebeck 570 result.Add("VERSION", VERSION);
3025 schoenebeck 947 result.Add("PROTOCOL_VERSION", ToString(LSCP_RELEASE_MAJOR) + "." + ToString(LSCP_RELEASE_MINOR));
3026 iliev 1161 #if HAVE_SQLITE3
3027     result.Add("INSTRUMENTS_DB_SUPPORT", "yes");
3028     #else
3029     result.Add("INSTRUMENTS_DB_SUPPORT", "no");
3030     #endif
3031 schoenebeck 1252
3032 schoenebeck 563 return result.Produce();
3033     }
3034    
3035     /**
3036 iliev 1541 * Will be called by the parser to return the current number of all active streams.
3037     */
3038     String LSCPServer::GetTotalStreamCount() {
3039     dmsg(2,("LSCPServer: GetTotalStreamCount()\n"));
3040     LSCPResultSet result;
3041     result.Add(pSampler->GetDiskStreamCount());
3042     return result.Produce();
3043     }
3044    
3045     /**
3046 iliev 778 * Will be called by the parser to return the current number of all active voices.
3047     */
3048     String LSCPServer::GetTotalVoiceCount() {
3049     dmsg(2,("LSCPServer: GetTotalVoiceCount()\n"));
3050     LSCPResultSet result;
3051     result.Add(pSampler->GetVoiceCount());
3052     return result.Produce();
3053     }
3054    
3055     /**
3056     * Will be called by the parser to return the maximum number of voices.
3057     */
3058     String LSCPServer::GetTotalVoiceCountMax() {
3059     dmsg(2,("LSCPServer: GetTotalVoiceCountMax()\n"));
3060     LSCPResultSet result;
3061 schoenebeck 2375 result.Add(EngineFactory::EngineInstances().size() * pSampler->GetGlobalMaxVoices());
3062 iliev 778 return result.Produce();
3063     }
3064    
3065 schoenebeck 1800 /**
3066     * Will be called by the parser to return the sampler global maximum
3067     * allowed number of voices.
3068     */
3069     String LSCPServer::GetGlobalMaxVoices() {
3070     dmsg(2,("LSCPServer: GetGlobalMaxVoices()\n"));
3071     LSCPResultSet result;
3072 schoenebeck 2375 result.Add(pSampler->GetGlobalMaxVoices());
3073 schoenebeck 1800 return result.Produce();
3074     }
3075    
3076     /**
3077     * Will be called by the parser to set the sampler global maximum number of
3078     * voices.
3079     */
3080     String LSCPServer::SetGlobalMaxVoices(int iVoices) {
3081     dmsg(2,("LSCPServer: SetGlobalMaxVoices(%d)\n", iVoices));
3082     LSCPResultSet result;
3083     try {
3084 schoenebeck 2375 pSampler->SetGlobalMaxVoices(iVoices);
3085     LSCPServer::SendLSCPNotify(
3086     LSCPEvent(LSCPEvent::event_global_info, "VOICES", pSampler->GetGlobalMaxVoices())
3087     );
3088 schoenebeck 1800 } catch (Exception e) {
3089     result.Error(e);
3090     }
3091     return result.Produce();
3092     }
3093    
3094     /**
3095     * Will be called by the parser to return the sampler global maximum
3096     * allowed number of disk streams.
3097     */
3098     String LSCPServer::GetGlobalMaxStreams() {
3099     dmsg(2,("LSCPServer: GetGlobalMaxStreams()\n"));
3100     LSCPResultSet result;
3101 schoenebeck 2375 result.Add(pSampler->GetGlobalMaxStreams());
3102 schoenebeck 1800 return result.Produce();
3103     }
3104    
3105     /**
3106     * Will be called by the parser to set the sampler global maximum number of
3107     * disk streams.
3108     */
3109     String LSCPServer::SetGlobalMaxStreams(int iStreams) {
3110     dmsg(2,("LSCPServer: SetGlobalMaxStreams(%d)\n", iStreams));
3111     LSCPResultSet result;
3112     try {
3113 schoenebeck 2375 pSampler->SetGlobalMaxStreams(iStreams);
3114     LSCPServer::SendLSCPNotify(
3115     LSCPEvent(LSCPEvent::event_global_info, "STREAMS", pSampler->GetGlobalMaxStreams())
3116     );
3117 schoenebeck 1800 } catch (Exception e) {
3118     result.Error(e);
3119     }
3120     return result.Produce();
3121     }
3122    
3123 schoenebeck 1005 String LSCPServer::GetGlobalVolume() {
3124     LSCPResultSet result;
3125     result.Add(ToString(GLOBAL_VOLUME)); // see common/global.cpp
3126     return result.Produce();
3127     }
3128    
3129     String LSCPServer::SetGlobalVolume(double dVolume) {
3130     LSCPResultSet result;
3131     try {
3132     if (dVolume < 0) throw Exception("Volume may not be negative");
3133 schoenebeck 1724 GLOBAL_VOLUME = dVolume; // see common/global_private.cpp
3134 iliev 1108 LSCPServer::SendLSCPNotify(LSCPEvent(LSCPEvent::event_global_info, "VOLUME", GLOBAL_VOLUME));
3135 schoenebeck 1005 } catch (Exception e) {
3136     result.Error(e);
3137     }
3138     return result.Produce();
3139     }
3140    
3141 schoenebeck 1525 String LSCPServer::GetFileInstruments(String Filename) {
3142 iliev 1535 dmsg(2,("LSCPServer: GetFileInstruments(String Filename=%s)\n",Filename.c_str()));
3143 schoenebeck 1525 LSCPResultSet result;
3144 iliev 1535 try {
3145     VerifyFile(Filename);
3146     } catch (Exception e) {
3147     result.Error(e);
3148     return result.Produce();
3149     }
3150 schoenebeck 1525 // try to find a sampler engine that can handle the file
3151     bool bFound = false;
3152     std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
3153     for (int i = 0; !bFound && i < engineTypes.size(); i++) {
3154     Engine* pEngine = NULL;
3155     try {
3156     pEngine = EngineFactory::Create(engineTypes[i]);
3157     if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
3158     InstrumentManager* pManager = pEngine->GetInstrumentManager();
3159     if (pManager) {
3160     std::vector<InstrumentManager::instrument_id_t> IDs =
3161     pManager->GetInstrumentFileContent(Filename);
3162     // return the amount of instruments in the file
3163     result.Add(IDs.size());
3164     // no more need to ask other engine types
3165     bFound = true;
3166     } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
3167     } catch (Exception e) {
3168     // NOOP, as exception is thrown if engine doesn't support file
3169     }
3170     if (pEngine) EngineFactory::Destroy(pEngine);
3171     }
3172 iliev 1535
3173     if (!bFound) result.Error("Unknown file format");
3174 schoenebeck 1525 return result.Produce();
3175     }
3176    
3177     String LSCPServer::ListFileInstruments(String Filename) {
3178 iliev 1535 dmsg(2,("LSCPServer: ListFileInstruments(String Filename=%s)\n",Filename.c_str()));
3179 schoenebeck 1525 LSCPResultSet result;
3180 iliev 1535 try {
3181     VerifyFile(Filename);
3182     } catch (Exception e) {
3183     result.Error(e);
3184     return result.Produce();
3185     }
3186 schoenebeck 1525 // try to find a sampler engine that can handle the file
3187     bool bFound = false;
3188     std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
3189     for (int i = 0; !bFound && i < engineTypes.size(); i++) {
3190     Engine* pEngine = NULL;
3191     try {
3192     pEngine = EngineFactory::Create(engineTypes[i]);
3193     if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
3194     InstrumentManager* pManager = pEngine->GetInstrumentManager();
3195     if (pManager) {
3196     std::vector<InstrumentManager::instrument_id_t> IDs =
3197     pManager->GetInstrumentFileContent(Filename);
3198     // return a list of IDs of the instruments in the file
3199     String s;
3200     for (int j = 0; j < IDs.size(); j++) {
3201     if (s.size()) s += ",";
3202     s += ToString(IDs[j].Index);
3203     }
3204     result.Add(s);
3205     // no more need to ask other engine types
3206     bFound = true;
3207     } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
3208     } catch (Exception e) {
3209     // NOOP, as exception is thrown if engine doesn't support file
3210     }
3211     if (pEngine) EngineFactory::Destroy(pEngine);
3212     }
3213 iliev 1535
3214     if (!bFound) result.Error("Unknown file format");
3215 schoenebeck 1525 return result.Produce();
3216     }
3217    
3218     String LSCPServer::GetFileInstrumentInfo(String Filename, uint InstrumentID) {
3219 iliev 1535 dmsg(2,("LSCPServer: GetFileInstrumentInfo(String Filename=%s, InstrumentID=%d)\n",Filename.c_str(),InstrumentID));
3220 schoenebeck 1525 LSCPResultSet result;
3221 iliev 1535 try {
3222     VerifyFile(Filename);
3223     } catch (Exception e) {
3224     result.Error(e);
3225     return result.Produce();
3226     }
3227 schoenebeck 1525 InstrumentManager::instrument_id_t id;
3228     id.FileName = Filename;
3229     id.Index = InstrumentID;
3230     // try to find a sampler engine that can handle the file
3231     bool bFound = false;
3232 schoenebeck 1536 bool bFatalErr = false;
3233 schoenebeck 1525 std::vector<String> engineTypes = EngineFactory::AvailableEngineTypes();
3234 schoenebeck 1536 for (int i = 0; !bFound && !bFatalErr && i < engineTypes.size(); i++) {
3235 schoenebeck 1525 Engine* pEngine = NULL;
3236     try {
3237     pEngine = EngineFactory::Create(engineTypes[i]);
3238     if (!pEngine) throw Exception("Internal error: could not create '" + engineTypes[i] + "' engine");
3239     InstrumentManager* pManager = pEngine->GetInstrumentManager();
3240     if (pManager) {
3241 schoenebeck 1536 // check if the instrument index is valid
3242     // FIXME: this won't work if an engine only supports parts of the instrument file
3243     std::vector<InstrumentManager::instrument_id_t> IDs =
3244     pManager->GetInstrumentFileContent(Filename);
3245     if (std::find(IDs.begin(), IDs.end(), id) == IDs.end()) {
3246     std::stringstream ss;
3247     ss << "Invalid instrument index " << InstrumentID << " for instrument file '" << Filename << "'";
3248     bFatalErr = true;
3249     throw Exception(ss.str());
3250     }
3251     // get the info of the requested instrument
3252 schoenebeck 1525 InstrumentManager::instrument_info_t info =
3253     pManager->GetInstrumentInfo(id);
3254     // return detailed informations about the file
3255     result.Add("NAME", info.InstrumentName);
3256 iliev 1535 result.Add("FORMAT_FAMILY", engineTypes[i]);
3257 schoenebeck 1525 result.Add("FORMAT_VERSION", info.FormatVersion);
3258     result.Add("PRODUCT", info.Product);
3259     result.Add("ARTISTS", info.Artists);
3260 iliev 1771
3261     std::stringstream ss;
3262     bool b = false;
3263     for (int i = 0; i < 128; i++) {
3264     if (info.KeyBindings[i]) {
3265     if (b) ss << ',';
3266     ss << i; b = true;
3267     }
3268     }
3269     result.Add("KEY_BINDINGS", ss.str());
3270    
3271 iliev 1774 b = false;
3272 iliev 1771 std::stringstream ss2;
3273     for (int i = 0; i < 128; i++) {
3274     if (info.KeySwitchBindings[i]) {
3275     if (b) ss2 << ',';
3276     ss2 << i; b = true;
3277     }
3278     }
3279     result.Add("KEYSWITCH_BINDINGS", ss2.str());
3280 schoenebeck 1525 // no more need to ask other engine types
3281     bFound = true;
3282     } else dmsg(1,("Warning: engine '%s' does not provide an instrument manager\n", engineTypes[i].c_str()));
3283     } catch (Exception e) {
3284 schoenebeck 1536 // usually NOOP, as exception is thrown if engine doesn't support file
3285     if (bFatalErr) result.Error(e);
3286 schoenebeck 1525 }
3287     if (pEngine) EngineFactory::Destroy(pEngine);
3288     }
3289 iliev 1535
3290 schoenebeck 1536 if (!bFound && !bFatalErr) result.Error("Unknown file format");
3291 schoenebeck 1525 return result.Produce();
3292     }
3293    
3294 iliev 1535 void LSCPServer::VerifyFile(String Filename) {
3295 senoner 1537 #if WIN32
3296     WIN32_FIND_DATA win32FileAttributeData;
3297     BOOL res = GetFileAttributesEx( Filename.c_str(), GetFileExInfoStandard, &win32FileAttributeData );
3298     if (!res) {
3299     std::stringstream ss;
3300     ss << "File does not exist, GetFileAttributesEx failed `" << Filename << "`: Error " << GetLastError();
3301     throw Exception(ss.str());
3302     }
3303     if ( win32FileAttributeData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) {
3304     throw Exception("Directory is specified");
3305     }
3306 schoenebeck 1551 #else
3307 iliev 1835 File f(Filename);
3308     if(!f.Exist()) throw Exception(f.GetErrorMsg());
3309     if (f.IsDirectory()) throw Exception("Directory is specified");
3310 senoner 1537 #endif
3311 iliev 1535 }
3312    
3313 iliev 778 /**
3314 schoenebeck 35 * Will be called by the parser to subscribe a client (frontend) on the
3315     * server for receiving event messages.
3316     */
3317 senkov 170 String LSCPServer::SubscribeNotification(LSCPEvent::event_t type) {
3318     dmsg(2,("LSCPServer: SubscribeNotification(Event=%s)\n", LSCPEvent::Name(type).c_str()));
3319     LSCPResultSet result;
3320 persson 2427 {
3321     LockGuard lock(SubscriptionMutex);
3322     eventSubscriptions[type].push_back(currentSocket);
3323     }
3324 senkov 170 return result.Produce();
3325 schoenebeck 35 }
3326    
3327     /**
3328     * Will be called by the parser to unsubscribe a client on the server
3329     * for not receiving further event messages.
3330     */
3331 senkov 170 String LSCPServer::UnsubscribeNotification(LSCPEvent::event_t type) {
3332     dmsg(2,("LSCPServer: UnsubscribeNotification(Event=%s)\n", LSCPEvent::Name(type).c_str()));
3333     LSCPResultSet result;
3334 persson 2427 {
3335     LockGuard lock(SubscriptionMutex);
3336     eventSubscriptions[type].remove(currentSocket);
3337     }
3338 senkov 170 return result.Produce();
3339 schoenebeck 35 }
3340 capela 133
3341 iliev 1161 String LSCPServer::AddDbInstrumentDirectory(String Dir) {
3342     dmsg(2,("LSCPServer: AddDbInstrumentDirectory(Dir=%s)\n", Dir.c_str()));
3343     LSCPResultSet result;
3344     #if HAVE_SQLITE3
3345     try {
3346     InstrumentsDb::GetInstrumentsDb()->AddDirectory(Dir);
3347     } catch (Exception e) {
3348     result.Error(e);
3349     }
3350     #else
3351     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3352     #endif
3353     return result.Produce();
3354 senkov 397 }
3355    
3356 iliev 1161 String LSCPServer::RemoveDbInstrumentDirectory(String Dir, bool Force) {
3357     dmsg(2,("LSCPServer: RemoveDbInstrumentDirectory(Dir=%s,Force=%d)\n", Dir.c_str(), Force));
3358 senkov 397 LSCPResultSet result;
3359 schoenebeck 401 #if HAVE_SQLITE3
3360 iliev 1161 try {
3361     InstrumentsDb::GetInstrumentsDb()->RemoveDirectory(Dir, Force);
3362     } catch (Exception e) {
3363     result.Error(e);
3364     }
3365     #else
3366     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3367     #endif
3368     return result.Produce();
3369     }
3370 senkov 397
3371 iliev 1187 String LSCPServer::GetDbInstrumentDirectoryCount(String Dir, bool Recursive) {
3372     dmsg(2,("LSCPServer: GetDbInstrumentDirectoryCount(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3373 iliev 1161 LSCPResultSet result;
3374     #if HAVE_SQLITE3
3375     try {
3376 iliev 1187 result.Add(InstrumentsDb::GetInstrumentsDb()->GetDirectoryCount(Dir, Recursive));
3377 iliev 1161 } catch (Exception e) {
3378     result.Error(e);
3379 senkov 397 }
3380 iliev 1161 #else
3381     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3382     #endif
3383     return result.Produce();
3384     }
3385    
3386 iliev 1187 String LSCPServer::GetDbInstrumentDirectories(String Dir, bool Recursive) {
3387     dmsg(2,("LSCPServer: GetDbInstrumentDirectories(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3388 iliev 1161 LSCPResultSet result;
3389     #if HAVE_SQLITE3
3390     try {
3391     String list;
3392 iliev 1187 StringListPtr dirs = InstrumentsDb::GetInstrumentsDb()->GetDirectories(Dir, Recursive);
3393 iliev 1161
3394     for (int i = 0; i < dirs->size(); i++) {
3395     if (list != "") list += ",";
3396 iliev 1350 list += "'" + InstrumentsDb::toEscapedPath(dirs->at(i)) + "'";
3397 iliev 1161 }
3398    
3399     result.Add(list);
3400     } catch (Exception e) {
3401     result.Error(e);
3402 senkov 397 }
3403     #else
3404 iliev 1161 result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3405 senkov 397 #endif
3406     return result.Produce();
3407     }
3408    
3409 iliev 1161 String LSCPServer::GetDbInstrumentDirectoryInfo(String Dir) {
3410     dmsg(2,("LSCPServer: GetDbInstrumentDirectoryInfo(Dir=%s)\n", Dir.c_str()));
3411     LSCPResultSet result;
3412     #if HAVE_SQLITE3
3413     try {
3414     DbDirectory info = InstrumentsDb::GetInstrumentsDb()->GetDirectoryInfo(Dir);
3415    
3416 iliev 1403 result.Add("DESCRIPTION", _escapeLscpResponse(info.Description));
3417 iliev 1161 result.Add("CREATED", info.Created);
3418     result.Add("MODIFIED", info.Modified);
3419     } catch (Exception e) {
3420     result.Error(e);
3421     }
3422     #else
3423     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3424     #endif
3425     return result.Produce();
3426     }
3427    
3428     String LSCPServer::SetDbInstrumentDirectoryName(String Dir, String Name) {
3429     dmsg(2,("LSCPServer: SetDbInstrumentDirectoryName(Dir=%s,Name=%s)\n", Dir.c_str(), Name.c_str()));
3430     LSCPResultSet result;
3431     #if HAVE_SQLITE3
3432     try {
3433     InstrumentsDb::GetInstrumentsDb()->RenameDirectory(Dir, Name);
3434     } catch (Exception e) {
3435     result.Error(e);
3436     }
3437     #else
3438     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3439     #endif
3440     return result.Produce();
3441     }
3442    
3443     String LSCPServer::MoveDbInstrumentDirectory(String Dir, String Dst) {
3444     dmsg(2,("LSCPServer: MoveDbInstrumentDirectory(Dir=%s,Dst=%s)\n", Dir.c_str(), Dst.c_str()));
3445     LSCPResultSet result;
3446     #if HAVE_SQLITE3
3447     try {
3448     InstrumentsDb::GetInstrumentsDb()->MoveDirectory(Dir, Dst);
3449     } catch (Exception e) {
3450     result.Error(e);
3451     }
3452     #else
3453     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3454     #endif
3455     return result.Produce();
3456     }
3457    
3458 iliev 1187 String LSCPServer::CopyDbInstrumentDirectory(String Dir, String Dst) {
3459     dmsg(2,("LSCPServer: CopyDbInstrumentDirectory(Dir=%s,Dst=%s)\n", Dir.c_str(), Dst.c_str()));
3460     LSCPResultSet result;
3461     #if HAVE_SQLITE3
3462     try {
3463     InstrumentsDb::GetInstrumentsDb()->CopyDirectory(Dir, Dst);
3464     } catch (Exception e) {
3465     result.Error(e);
3466     }
3467     #else
3468     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3469     #endif
3470     return result.Produce();
3471     }
3472    
3473 iliev 1161 String LSCPServer::SetDbInstrumentDirectoryDescription(String Dir, String Desc) {
3474     dmsg(2,("LSCPServer: SetDbInstrumentDirectoryDescription(Dir=%s,Desc=%s)\n", Dir.c_str(), Desc.c_str()));
3475     LSCPResultSet result;
3476     #if HAVE_SQLITE3
3477     try {
3478     InstrumentsDb::GetInstrumentsDb()->SetDirectoryDescription(Dir, Desc);
3479     } catch (Exception e) {
3480     result.Error(e);
3481     }
3482     #else
3483     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3484     #endif
3485     return result.Produce();
3486     }
3487    
3488 iliev 1200 String LSCPServer::AddDbInstruments(String DbDir, String FilePath, int Index, bool bBackground) {
3489     dmsg(2,("LSCPServer: AddDbInstruments(DbDir=%s,FilePath=%s,Index=%d,bBackground=%d)\n", DbDir.c_str(), FilePath.c_str(), Index, bBackground));
3490 iliev 1161 LSCPResultSet result;
3491     #if HAVE_SQLITE3
3492     try {
3493 iliev 1200 int id;
3494     InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
3495     id = db->AddInstruments(DbDir, FilePath, Index, bBackground);
3496     if (bBackground) result = id;
3497 iliev 1161 } catch (Exception e) {
3498     result.Error(e);
3499     }
3500     #else
3501     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3502     #endif
3503     return result.Produce();
3504     }
3505    
3506 iliev 1781 String LSCPServer::AddDbInstruments(String ScanMode, String DbDir, String FsDir, bool bBackground, bool insDir) {
3507     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));
3508 iliev 1161 LSCPResultSet result;
3509     #if HAVE_SQLITE3
3510     try {
3511 iliev 1200 int id;
3512     InstrumentsDb* db = InstrumentsDb::GetInstrumentsDb();
3513     if (ScanMode.compare("RECURSIVE") == 0) {
3514 iliev 1781 id = db->AddInstruments(RECURSIVE, DbDir, FsDir, bBackground, insDir);
3515 iliev 1200 } else if (ScanMode.compare("NON_RECURSIVE") == 0) {
3516 iliev 1781 id = db->AddInstruments(NON_RECURSIVE, DbDir, FsDir, bBackground, insDir);
3517 iliev 1200 } else if (ScanMode.compare("FLAT") == 0) {
3518 iliev 1781 id = db->AddInstruments(FLAT, DbDir, FsDir, bBackground, insDir);
3519 iliev 1200 } else {
3520     throw Exception("Unknown scan mode: " + ScanMode);
3521     }
3522 schoenebeck 1252
3523 iliev 1200 if (bBackground) result = id;
3524 iliev 1161 } catch (Exception e) {
3525     result.Error(e);
3526     }
3527     #else
3528     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3529     #endif
3530     return result.Produce();
3531     }
3532    
3533     String LSCPServer::RemoveDbInstrument(String Instr) {
3534     dmsg(2,("LSCPServer: RemoveDbInstrument(Instr=%s)\n", Instr.c_str()));
3535     LSCPResultSet result;
3536     #if HAVE_SQLITE3
3537     try {
3538     InstrumentsDb::GetInstrumentsDb()->RemoveInstrument(Instr);
3539     } catch (Exception e) {
3540     result.Error(e);
3541     }
3542     #else
3543     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3544     #endif
3545     return result.Produce();
3546     }
3547    
3548 iliev 1187 String LSCPServer::GetDbInstrumentCount(String Dir, bool Recursive) {
3549     dmsg(2,("LSCPServer: GetDbInstrumentCount(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3550 iliev 1161 LSCPResultSet result;
3551     #if HAVE_SQLITE3
3552     try {
3553 iliev 1187 result.Add(InstrumentsDb::GetInstrumentsDb()->GetInstrumentCount(Dir, Recursive));
3554 iliev 1161 } catch (Exception e) {
3555     result.Error(e);
3556     }
3557     #else
3558     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3559     #endif
3560     return result.Produce();
3561     }
3562    
3563 iliev 1187 String LSCPServer::GetDbInstruments(String Dir, bool Recursive) {
3564     dmsg(2,("LSCPServer: GetDbInstruments(Dir=%s,Recursive=%d)\n", Dir.c_str(), Recursive));
3565 iliev 1161 LSCPResultSet result;
3566     #if HAVE_SQLITE3
3567     try {
3568     String list;
3569 iliev 1187 StringListPtr instrs = InstrumentsDb::GetInstrumentsDb()->GetInstruments(Dir, Recursive);
3570 iliev 1161
3571     for (int i = 0; i < instrs->size(); i++) {
3572     if (list != "") list += ",";
3573 iliev 1350 list += "'" + InstrumentsDb::toEscapedPath(instrs->at(i)) + "'";
3574 iliev 1161 }
3575    
3576     result.Add(list);
3577     } catch (Exception e) {
3578     result.Error(e);
3579     }
3580     #else
3581     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3582     #endif
3583     return result.Produce();
3584     }
3585    
3586     String LSCPServer::GetDbInstrumentInfo(String Instr) {
3587     dmsg(2,("LSCPServer: GetDbInstrumentInfo(Instr=%s)\n", Instr.c_str()));
3588     LSCPResultSet result;
3589     #if HAVE_SQLITE3
3590     try {
3591     DbInstrument info = InstrumentsDb::GetInstrumentsDb()->GetInstrumentInfo(Instr);
3592    
3593     result.Add("INSTRUMENT_FILE", info.InstrFile);
3594     result.Add("INSTRUMENT_NR", info.InstrNr);
3595     result.Add("FORMAT_FAMILY", info.FormatFamily);
3596     result.Add("FORMAT_VERSION", info.FormatVersion);
3597     result.Add("SIZE", (int)info.Size);
3598     result.Add("CREATED", info.Created);
3599     result.Add("MODIFIED", info.Modified);
3600 iliev 1403 result.Add("DESCRIPTION", _escapeLscpResponse(info.Description));
3601 iliev 1161 result.Add("IS_DRUM", info.IsDrum);
3602 iliev 1403 result.Add("PRODUCT", _escapeLscpResponse(info.Product));
3603     result.Add("ARTISTS", _escapeLscpResponse(info.Artists));
3604     result.Add("KEYWORDS", _escapeLscpResponse(info.Keywords));
3605 iliev 1161 } catch (Exception e) {
3606     result.Error(e);
3607     }
3608     #else
3609     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3610     #endif
3611     return result.Produce();
3612     }
3613    
3614 iliev 1200 String LSCPServer::GetDbInstrumentsJobInfo(int JobId) {
3615     dmsg(2,("LSCPServer: GetDbInstrumentsJobInfo(JobId=%d)\n", JobId));
3616     LSCPResultSet result;
3617     #if HAVE_SQLITE3
3618     try {
3619     ScanJob job = InstrumentsDb::GetInstrumentsDb()->Jobs.GetJobById(JobId);
3620    
3621     result.Add("FILES_TOTAL", job.FilesTotal);
3622     result.Add("FILES_SCANNED", job.FilesScanned);
3623     result.Add("SCANNING", job.Scanning);
3624     result.Add("STATUS", job.Status);
3625     } catch (Exception e) {
3626     result.Error(e);
3627     }
3628     #else
3629     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3630     #endif
3631     return result.Produce();
3632     }
3633    
3634 iliev 1161 String LSCPServer::SetDbInstrumentName(String Instr, String Name) {
3635     dmsg(2,("LSCPServer: SetDbInstrumentName(Instr=%s,Name=%s)\n", Instr.c_str(), Name.c_str()));
3636     LSCPResultSet result;
3637     #if HAVE_SQLITE3
3638     try {
3639     InstrumentsDb::GetInstrumentsDb()->RenameInstrument(Instr, Name);
3640     } catch (Exception e) {
3641     result.Error(e);
3642     }
3643     #else
3644     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3645     #endif
3646     return result.Produce();
3647     }
3648    
3649     String LSCPServer::MoveDbInstrument(String Instr, String Dst) {
3650     dmsg(2,("LSCPServer: MoveDbInstrument(Instr=%s,Dst=%s)\n", Instr.c_str(), Dst.c_str()));
3651     LSCPResultSet result;
3652     #if HAVE_SQLITE3
3653     try {
3654     InstrumentsDb::GetInstrumentsDb()->MoveInstrument(Instr, Dst);
3655     } catch (Exception e) {
3656     result.Error(e);
3657     }
3658     #else
3659     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3660     #endif
3661     return result.Produce();
3662     }
3663    
3664 iliev 1187 String LSCPServer::CopyDbInstrument(String Instr, String Dst) {
3665     dmsg(2,("LSCPServer: CopyDbInstrument(Instr=%s,Dst=%s)\n", Instr.c_str(), Dst.c_str()));
3666     LSCPResultSet result;
3667     #if HAVE_SQLITE3
3668     try {
3669     InstrumentsDb::GetInstrumentsDb()->CopyInstrument(Instr, Dst);
3670     } catch (Exception e) {
3671     result.Error(e);
3672     }
3673     #else
3674     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3675     #endif
3676     return result.Produce();
3677     }
3678    
3679 iliev 1161 String LSCPServer::SetDbInstrumentDescription(String Instr, String Desc) {
3680     dmsg(2,("LSCPServer: SetDbInstrumentDescription(Instr=%s,Desc=%s)\n", Instr.c_str(), Desc.c_str()));
3681     LSCPResultSet result;
3682     #if HAVE_SQLITE3
3683     try {
3684     InstrumentsDb::GetInstrumentsDb()->SetInstrumentDescription(Instr, Desc);
3685     } catch (Exception e) {
3686     result.Error(e);
3687     }
3688     #else
3689     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3690     #endif
3691     return result.Produce();
3692     }
3693    
3694 iliev 1727 String LSCPServer::SetDbInstrumentFilePath(String OldPath, String NewPath) {
3695     dmsg(2,("LSCPServer: SetDbInstrumentFilePath(OldPath=%s,NewPath=%s)\n", OldPath.c_str(), NewPath.c_str()));
3696     LSCPResultSet result;
3697     #if HAVE_SQLITE3
3698     try {
3699     InstrumentsDb::GetInstrumentsDb()->SetInstrumentFilePath(OldPath, NewPath);
3700     } catch (Exception e) {
3701     result.Error(e);
3702     }
3703     #else
3704     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3705     #endif
3706     return result.Produce();
3707     }
3708    
3709     String LSCPServer::FindLostDbInstrumentFiles() {
3710     dmsg(2,("LSCPServer: FindLostDbInstrumentFiles()\n"));
3711     LSCPResultSet result;
3712     #if HAVE_SQLITE3
3713     try {
3714     String list;
3715     StringListPtr pLostFiles = InstrumentsDb::GetInstrumentsDb()->FindLostInstrumentFiles();
3716    
3717     for (int i = 0; i < pLostFiles->size(); i++) {
3718     if (list != "") list += ",";
3719     list += "'" + pLostFiles->at(i) + "'";
3720     }
3721    
3722     result.Add(list);
3723     } catch (Exception e) {
3724     result.Error(e);
3725     }
3726     #else
3727     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3728     #endif
3729     return result.Produce();
3730     }
3731    
3732 iliev 1187 String LSCPServer::FindDbInstrumentDirectories(String Dir, std::map<String,String> Parameters, bool Recursive) {
3733     dmsg(2,("LSCPServer: FindDbInstrumentDirectories(Dir=%s)\n", Dir.c_str()));
3734     LSCPResultSet result;
3735     #if HAVE_SQLITE3
3736     try {
3737     SearchQuery Query;
3738     std::map<String,String>::iterator iter;
3739     for (iter = Parameters.begin(); iter != Parameters.end(); iter++) {
3740     if (iter->first.compare("NAME") == 0) {
3741     Query.Name = iter->second;
3742     } else if (iter->first.compare("CREATED") == 0) {
3743     Query.SetCreated(iter->second);
3744     } else if (iter->first.compare("MODIFIED") == 0) {
3745     Query.SetModified(iter->second);
3746     } else if (iter->first.compare("DESCRIPTION") == 0) {
3747     Query.Description = iter->second;
3748     } else {
3749     throw Exception("Unknown search criteria: " + iter->first);
3750     }
3751     }
3752 iliev 1161
3753 iliev 1187 String list;
3754     StringListPtr pDirectories =
3755     InstrumentsDb::GetInstrumentsDb()->FindDirectories(Dir, &Query, Recursive);
3756    
3757     for (int i = 0; i < pDirectories->size(); i++) {
3758     if (list != "") list += ",";
3759 iliev 1345 list += "'" + InstrumentsDb::toEscapedPath(pDirectories->at(i)) + "'";
3760 iliev 1187 }
3761    
3762     result.Add(list);
3763     } catch (Exception e) {
3764     result.Error(e);
3765     }
3766     #else
3767     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3768     #endif
3769     return result.Produce();
3770     }
3771    
3772     String LSCPServer::FindDbInstruments(String Dir, std::map<String,String> Parameters, bool Recursive) {
3773     dmsg(2,("LSCPServer: FindDbInstruments(Dir=%s)\n", Dir.c_str()));
3774     LSCPResultSet result;
3775     #if HAVE_SQLITE3
3776     try {
3777     SearchQuery Query;
3778     std::map<String,String>::iterator iter;
3779     for (iter = Parameters.begin(); iter != Parameters.end(); iter++) {
3780     if (iter->first.compare("NAME") == 0) {
3781     Query.Name = iter->second;
3782     } else if (iter->first.compare("FORMAT_FAMILIES") == 0) {
3783     Query.SetFormatFamilies(iter->second);
3784     } else if (iter->first.compare("SIZE") == 0) {
3785     Query.SetSize(iter->second);
3786     } else if (iter->first.compare("CREATED") == 0) {
3787     Query.SetCreated(iter->second);
3788     } else if (iter->first.compare("MODIFIED") == 0) {
3789     Query.SetModified(iter->second);
3790     } else if (iter->first.compare("DESCRIPTION") == 0) {
3791     Query.Description = iter->second;
3792     } else if (iter->first.compare("IS_DRUM") == 0) {
3793     if (!strcasecmp(iter->second.c_str(), "true")) {
3794     Query.InstrType = SearchQuery::DRUM;
3795     } else {
3796     Query.InstrType = SearchQuery::CHROMATIC;
3797     }
3798     } else if (iter->first.compare("PRODUCT") == 0) {
3799     Query.Product = iter->second;
3800     } else if (iter->first.compare("ARTISTS") == 0) {
3801     Query.Artists = iter->second;
3802     } else if (iter->first.compare("KEYWORDS") == 0) {
3803     Query.Keywords = iter->second;
3804     } else {
3805     throw Exception("Unknown search criteria: " + iter->first);
3806     }
3807     }
3808    
3809     String list;
3810     StringListPtr pInstruments =
3811     InstrumentsDb::GetInstrumentsDb()->FindInstruments(Dir, &Query, Recursive);
3812    
3813     for (int i = 0; i < pInstruments->size(); i++) {
3814     if (list != "") list += ",";
3815 iliev 1345 list += "'" + InstrumentsDb::toEscapedPath(pInstruments->at(i)) + "'";
3816 iliev 1187 }
3817    
3818     result.Add(list);
3819     } catch (Exception e) {
3820     result.Error(e);
3821     }
3822     #else
3823     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3824     #endif
3825     return result.Produce();
3826     }
3827    
3828 iliev 1353 String LSCPServer::FormatInstrumentsDb() {
3829     dmsg(2,("LSCPServer: FormatInstrumentsDb()\n"));
3830     LSCPResultSet result;
3831     #if HAVE_SQLITE3
3832     try {
3833     InstrumentsDb::GetInstrumentsDb()->Format();
3834     } catch (Exception e) {
3835     result.Error(e);
3836     }
3837     #else
3838     result.Error(String(DOESNT_HAVE_SQLITE3), 0);
3839     #endif
3840     return result.Produce();
3841     }
3842 iliev 1187
3843 iliev 1353
3844 schoenebeck 210 /**
3845     * Will be called by the parser to enable or disable echo mode; if echo
3846     * mode is enabled, all commands from the client will (immediately) be
3847     * echoed back to the client.
3848     */
3849     String LSCPServer::SetEcho(yyparse_param_t* pSession, double boolean_value) {
3850     dmsg(2,("LSCPServer: SetEcho(val=%f)\n", boolean_value));
3851     LSCPResultSet result;
3852     try {
3853     if (boolean_value == 0) pSession->bVerbose = false;
3854     else if (boolean_value == 1) pSession->bVerbose = true;
3855 schoenebeck 880 else throw Exception("Not a boolean value, must either be 0 or 1");
3856 schoenebeck 210 }
3857 schoenebeck 880 catch (Exception e) {
3858 schoenebeck 210 result.Error(e);
3859     }
3860     return result.Produce();
3861     }
3862 persson 1765
3863     }

  ViewVC Help
Powered by ViewVC