/[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 2687 - (hide annotations) (download)
Sun Jan 4 17:16:05 2015 UTC (9 years, 3 months ago) by schoenebeck
File size: 166001 byte(s)
* Instrument editor interface: Changed instrument editor plugin interface,
providing additional informations like the EngineChannel for which the
instrument editor was spawned for. This allows the instrument editors to
interact more actively with the sampler.
* Bumped version (1.0.0.svn60).

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

  ViewVC Help
Powered by ViewVC