/[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 2528 - (hide annotations) (download)
Mon Mar 3 12:02:40 2014 UTC (10 years, 1 month ago) by schoenebeck
File size: 162389 byte(s)
* LSCP shell: in case of multiple possibilities or non-terminal symbols,
  show them right to the current command line immediately while typing
  (no double tab required for this feature, as it would be the case in
  other shells)
* LSCP shell: fixed sluggish behavior when doing tab auto complete
* LSCP shell: fixed conflicting behavior between keyboard input and
  LSCP server evaluation result, that caused an inconsistent screen
  output (keybord input is now never printed directly on screen, only
  the result returned from LSCP server)

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

  ViewVC Help
Powered by ViewVC