/[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 2188 - (hide annotations) (download)
Fri Jun 24 19:39:11 2011 UTC (12 years, 9 months ago) by iliev
File size: 153165 byte(s)
* Added LSCP commands "SUBSCRIBE EFFECT_INSTANCE_COUNT",
  "SUBSCRIBE EFFECT_INSTANCE_INFO", "SUBSCRIBE SEND_EFFECT_CHAIN_COUNT",
  "SUBSCRIBE SEND_EFFECT_CHAIN_INFO"

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

  ViewVC Help
Powered by ViewVC