1 /*
2 Copyright (C) 2008 Grame
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18 */
19 
20 #ifndef __JackLockedEngine__
21 #define __JackLockedEngine__
22 
23 #include "JackEngine.h"
24 #include "JackMutex.h"
25 #include "JackTools.h"
26 #include "JackException.h"
27 
28 namespace Jack
29 {
30 
31 #define TRY_CALL    \
32     try {           \
33 
34 /*
35 See : http://groups.google.com/group/comp.programming.threads/browse_thread/thread/652bcf186fbbf697/f63757846514e5e5
36 
37 catch (...) {
38     // Assuming thread cancellation, must rethrow
39     throw;
40 }
41 */
42 
43 #define CATCH_EXCEPTION_RETURN                      \
44     } catch (std::bad_alloc& e) {                    \
45         jack_error("Memory allocation error...");   \
46         return -1;                                  \
47     } catch (...) {                                 \
48         jack_error("Unknown error...");             \
49         throw;                                      \
50     }                                               \
51 
52 #define CATCH_CLOSE_EXCEPTION_RETURN                      \
53     } catch (std::bad_alloc& e) {                    \
54         jack_error("Memory allocation error...");   \
55         return -1;                                  \
56     } catch (JackTemporaryException& e) {                       \
57         jack_error("JackTemporaryException : now quits...");   \
58         JackTools::KillServer();                     \
59         return 0;                                   \
60     } catch (...) {                                 \
61         jack_error("Unknown error...");             \
62         throw;                                      \
63     }
64 
65 #define CATCH_EXCEPTION                      \
66     } catch (std::bad_alloc& e) {                    \
67         jack_error("Memory allocation error...");   \
68     } catch (...) {                                 \
69         jack_error("Unknown error...");             \
70         throw;                                      \
71     }                                               \
72 
73 
74 /*!
75 \brief Locked Engine, access to methods is serialized using a mutex.
76 */
77 
78 class SERVER_EXPORT JackLockedEngine
79 {
80     private:
81 
82         JackEngine fEngine;
83 
84     public:
85 
JackLockedEngine(JackGraphManager * manager,JackSynchro * table,JackEngineControl * controler,char self_connect_mode)86         JackLockedEngine(JackGraphManager* manager, JackSynchro* table, JackEngineControl* controler, char self_connect_mode):
87             fEngine(manager, table, controler, self_connect_mode)
88         {}
~JackLockedEngine()89         ~JackLockedEngine()
90         {}
91 
Lock()92         bool Lock() { return fEngine.Lock(); }
Unlock()93         bool Unlock() { return fEngine.Unlock(); }
Trylock()94         bool Trylock() { return fEngine.Trylock(); }
95 
Open()96         int Open()
97         {
98             // No lock needed
99             TRY_CALL
100             return fEngine.Open();
101             CATCH_EXCEPTION_RETURN
102         }
Close()103         int Close()
104         {
105             // No lock needed
106             TRY_CALL
107             return fEngine.Close();
108             CATCH_EXCEPTION_RETURN
109         }
110 
111         // Client management
ClientCheck(const char * name,jack_uuid_t uuid,char * name_res,int protocol,int options,int * status)112         int ClientCheck(const char* name, jack_uuid_t uuid, char* name_res, int protocol, int options, int* status)
113         {
114             TRY_CALL
115             JackLock lock(&fEngine);
116             return fEngine.ClientCheck(name, uuid, name_res, protocol, options, status);
117             CATCH_EXCEPTION_RETURN
118         }
ClientExternalOpen(const char * name,int pid,jack_uuid_t uuid,int * ref,int * shared_engine,int * shared_client,int * shared_graph_manager)119         int ClientExternalOpen(const char* name, int pid, jack_uuid_t uuid, int* ref, int* shared_engine, int* shared_client, int* shared_graph_manager)
120         {
121             TRY_CALL
122             JackLock lock(&fEngine);
123             return fEngine.ClientExternalOpen(name, pid, uuid, ref, shared_engine, shared_client, shared_graph_manager);
124             CATCH_EXCEPTION_RETURN
125         }
ClientInternalOpen(const char * name,int * ref,JackEngineControl ** shared_engine,JackGraphManager ** shared_manager,JackClientInterface * client,bool wait)126         int ClientInternalOpen(const char* name, int* ref, JackEngineControl** shared_engine, JackGraphManager** shared_manager, JackClientInterface* client, bool wait)
127         {
128             TRY_CALL
129             JackLock lock(&fEngine);
130             return fEngine.ClientInternalOpen(name, ref, shared_engine, shared_manager, client, wait);
131             CATCH_EXCEPTION_RETURN
132         }
133 
ClientExternalClose(int refnum)134         int ClientExternalClose(int refnum)
135         {
136             TRY_CALL
137             JackLock lock(&fEngine);
138             return (fEngine.CheckClient(refnum)) ? fEngine.ClientExternalClose(refnum) : -1;
139             CATCH_CLOSE_EXCEPTION_RETURN
140         }
ClientInternalClose(int refnum,bool wait)141         int ClientInternalClose(int refnum, bool wait)
142         {
143             TRY_CALL
144             JackLock lock(&fEngine);
145             return (fEngine.CheckClient(refnum)) ? fEngine.ClientInternalClose(refnum, wait) : -1;
146             CATCH_CLOSE_EXCEPTION_RETURN
147         }
148 
ClientActivate(int refnum,bool is_real_time)149         int ClientActivate(int refnum, bool is_real_time)
150         {
151             TRY_CALL
152             JackLock lock(&fEngine);
153             return (fEngine.CheckClient(refnum)) ? fEngine.ClientActivate(refnum, is_real_time) : -1;
154             CATCH_EXCEPTION_RETURN
155         }
ClientDeactivate(int refnum)156         int ClientDeactivate(int refnum)
157         {
158             TRY_CALL
159             JackLock lock(&fEngine);
160             return (fEngine.CheckClient(refnum)) ? fEngine.ClientDeactivate(refnum) : -1;
161             CATCH_EXCEPTION_RETURN
162         }
ClientKill(int refnum)163         void ClientKill(int refnum)
164         {
165             TRY_CALL
166             JackLock lock(&fEngine);
167             fEngine.ClientKill(refnum);
168             CATCH_EXCEPTION
169         }
170 
171         // Internal client management
GetInternalClientName(int int_ref,char * name_res)172         int GetInternalClientName(int int_ref, char* name_res)
173         {
174             TRY_CALL
175             JackLock lock(&fEngine);
176             return fEngine.GetInternalClientName(int_ref, name_res);
177             CATCH_EXCEPTION_RETURN
178         }
InternalClientHandle(const char * client_name,int * status,int * int_ref)179         int InternalClientHandle(const char* client_name, int* status, int* int_ref)
180         {
181             TRY_CALL
182             JackLock lock(&fEngine);
183             return fEngine.InternalClientHandle(client_name, status, int_ref);
184             CATCH_EXCEPTION_RETURN
185         }
InternalClientUnload(int refnum,int * status)186         int InternalClientUnload(int refnum, int* status)
187         {
188             TRY_CALL
189             JackLock lock(&fEngine);
190             // Client is tested in fEngine.InternalClientUnload
191             return fEngine.InternalClientUnload(refnum, status);
192             CATCH_EXCEPTION_RETURN
193         }
194 
195         // Port management
PortRegister(int refnum,const char * name,const char * type,unsigned int flags,unsigned int buffer_size,jack_port_id_t * port)196         int PortRegister(int refnum, const char* name, const char *type, unsigned int flags, unsigned int buffer_size, jack_port_id_t* port)
197         {
198             TRY_CALL
199             JackLock lock(&fEngine);
200             return (fEngine.CheckClient(refnum)) ? fEngine.PortRegister(refnum, name, type, flags, buffer_size, port) : -1;
201             CATCH_EXCEPTION_RETURN
202         }
PortUnRegister(int refnum,jack_port_id_t port)203         int PortUnRegister(int refnum, jack_port_id_t port)
204         {
205             TRY_CALL
206             JackLock lock(&fEngine);
207             return (fEngine.CheckClient(refnum)) ? fEngine.PortUnRegister(refnum, port) : -1;
208             CATCH_EXCEPTION_RETURN
209         }
210 
PortConnect(int refnum,const char * src,const char * dst)211         int PortConnect(int refnum, const char* src, const char* dst)
212         {
213             TRY_CALL
214             JackLock lock(&fEngine);
215             return (fEngine.CheckClient(refnum)) ? fEngine.PortConnect(refnum, src, dst) : -1;
216             CATCH_EXCEPTION_RETURN
217         }
PortDisconnect(int refnum,const char * src,const char * dst)218         int PortDisconnect(int refnum, const char* src, const char* dst)
219         {
220             TRY_CALL
221             JackLock lock(&fEngine);
222             return (fEngine.CheckClient(refnum)) ? fEngine.PortDisconnect(refnum, src, dst) : -1;
223             CATCH_EXCEPTION_RETURN
224         }
225 
PortConnect(int refnum,jack_port_id_t src,jack_port_id_t dst)226         int PortConnect(int refnum, jack_port_id_t src, jack_port_id_t dst)
227         {
228             TRY_CALL
229             JackLock lock(&fEngine);
230             return (fEngine.CheckClient(refnum)) ? fEngine.PortConnect(refnum, src, dst) : -1;
231             CATCH_EXCEPTION_RETURN
232         }
PortDisconnect(int refnum,jack_port_id_t src,jack_port_id_t dst)233         int PortDisconnect(int refnum, jack_port_id_t src, jack_port_id_t dst)
234         {
235             TRY_CALL
236             JackLock lock(&fEngine);
237             return (fEngine.CheckClient(refnum)) ? fEngine.PortDisconnect(refnum, src, dst) : -1;
238             CATCH_EXCEPTION_RETURN
239         }
240 
PortRename(int refnum,jack_port_id_t port,const char * name)241         int PortRename(int refnum, jack_port_id_t port, const char* name)
242         {
243             TRY_CALL
244             JackLock lock(&fEngine);
245             return (fEngine.CheckClient(refnum)) ? fEngine.PortRename(refnum, port, name) : -1;
246             CATCH_EXCEPTION_RETURN
247         }
248 
PortSetDefaultMetadata(int refnum,jack_port_id_t port,const char * pretty_name)249         int PortSetDefaultMetadata(int refnum, jack_port_id_t port, const char* pretty_name)
250         {
251             TRY_CALL
252             JackLock lock(&fEngine);
253             return (fEngine.CheckClient(refnum)) ? fEngine.PortSetDefaultMetadata(port, pretty_name) : -1;
254             CATCH_EXCEPTION_RETURN
255         }
256 
ComputeTotalLatencies()257         int ComputeTotalLatencies()
258         {
259             TRY_CALL
260             JackLock lock(&fEngine);
261             return fEngine.ComputeTotalLatencies();
262             CATCH_EXCEPTION_RETURN
263         }
264 
265         // Graph
Process(jack_time_t cur_cycle_begin,jack_time_t prev_cycle_end)266         bool Process(jack_time_t cur_cycle_begin, jack_time_t prev_cycle_end)
267         {
268             // RT : no lock
269             return fEngine.Process(cur_cycle_begin, prev_cycle_end);
270         }
271 
272         // Notifications
NotifyDriverXRun()273         void NotifyDriverXRun()
274         {
275             // Coming from the driver in RT : no lock
276             fEngine.NotifyDriverXRun();
277         }
278 
NotifyClientXRun(int refnum)279         void NotifyClientXRun(int refnum)
280         {
281             TRY_CALL
282             JackLock lock(&fEngine);
283             fEngine.NotifyClientXRun(refnum);
284             CATCH_EXCEPTION
285         }
286 
NotifyGraphReorder()287         void NotifyGraphReorder()
288         {
289             TRY_CALL
290             JackLock lock(&fEngine);
291             fEngine.NotifyGraphReorder();
292             CATCH_EXCEPTION
293         }
294 
NotifyBufferSize(jack_nframes_t buffer_size)295         void NotifyBufferSize(jack_nframes_t buffer_size)
296         {
297             TRY_CALL
298             JackLock lock(&fEngine);
299             fEngine.NotifyBufferSize(buffer_size);
300             CATCH_EXCEPTION
301         }
NotifySampleRate(jack_nframes_t sample_rate)302         void NotifySampleRate(jack_nframes_t sample_rate)
303         {
304             TRY_CALL
305             JackLock lock(&fEngine);
306             fEngine.NotifySampleRate(sample_rate);
307             CATCH_EXCEPTION
308         }
NotifyFreewheel(bool onoff)309         void NotifyFreewheel(bool onoff)
310         {
311             TRY_CALL
312             JackLock lock(&fEngine);
313             fEngine.NotifyFreewheel(onoff);
314             CATCH_EXCEPTION
315         }
316 
NotifyFailure(int code,const char * reason)317         void NotifyFailure(int code, const char* reason)
318         {
319             TRY_CALL
320             JackLock lock(&fEngine);
321             fEngine.NotifyFailure(code, reason);
322             CATCH_EXCEPTION
323         }
324 
GetClientPID(const char * name)325         int GetClientPID(const char* name)
326         {
327             TRY_CALL
328             JackLock lock(&fEngine);
329             return fEngine.GetClientPID(name);
330             CATCH_EXCEPTION_RETURN
331         }
332 
GetClientRefNum(const char * name)333         int GetClientRefNum(const char* name)
334         {
335             TRY_CALL
336             JackLock lock(&fEngine);
337             return fEngine.GetClientRefNum(name);
338             CATCH_EXCEPTION_RETURN
339         }
340 
NotifyQuit()341         void NotifyQuit()
342         {
343             // No lock needed
344             TRY_CALL
345             return fEngine.NotifyQuit();
346             CATCH_EXCEPTION
347         }
348 
SessionNotify(int refnum,const char * target,jack_session_event_type_t type,const char * path,detail::JackChannelTransactionInterface * socket,JackSessionNotifyResult ** result)349         void SessionNotify(int refnum, const char* target, jack_session_event_type_t type, const char *path, detail::JackChannelTransactionInterface *socket, JackSessionNotifyResult** result)
350         {
351             TRY_CALL
352             JackLock lock(&fEngine);
353             fEngine.SessionNotify(refnum, target, type, path, socket, result);
354             CATCH_EXCEPTION
355         }
356 
SessionReply(int refnum)357         int SessionReply(int refnum)
358         {
359             TRY_CALL
360             JackLock lock(&fEngine);
361             return fEngine.SessionReply(refnum);
362             CATCH_EXCEPTION_RETURN
363         }
364 
GetUUIDForClientName(const char * client_name,char * uuid_res)365         int GetUUIDForClientName(const char *client_name, char *uuid_res)
366         {
367             TRY_CALL
368             JackLock lock(&fEngine);
369             return fEngine.GetUUIDForClientName(client_name, uuid_res);
370             CATCH_EXCEPTION_RETURN
371         }
372 
GetClientNameForUUID(const char * uuid,char * name_res)373         int GetClientNameForUUID(const char *uuid, char *name_res)
374         {
375             TRY_CALL
376             JackLock lock(&fEngine);
377             return fEngine.GetClientNameForUUID(uuid, name_res);
378             CATCH_EXCEPTION_RETURN
379         }
ReserveClientName(const char * name,const char * uuid)380         int ReserveClientName(const char *name, const char *uuid)
381         {
382             TRY_CALL
383             JackLock lock(&fEngine);
384             return fEngine.ReserveClientName(name, uuid);
385             CATCH_EXCEPTION_RETURN
386         }
387 
ClientHasSessionCallback(const char * name)388         int ClientHasSessionCallback(const char *name)
389         {
390             TRY_CALL
391             JackLock lock(&fEngine);
392             return fEngine.ClientHasSessionCallback(name);
393             CATCH_EXCEPTION_RETURN
394         }
395 
PropertyChangeNotify(jack_uuid_t subject,const char * key,jack_property_change_t change)396         int PropertyChangeNotify(jack_uuid_t subject, const char* key, jack_property_change_t change)
397         {
398             TRY_CALL
399             JackLock lock(&fEngine);
400             return fEngine.PropertyChangeNotify(subject, key, change);
401             CATCH_EXCEPTION_RETURN
402         }
403 };
404 
405 } // end of namespace
406 
407 #endif
408 
409