LMMS
Loading...
Searching...
No Matches
RemotePluginClient.h
Go to the documentation of this file.
1/*
2 * RemotePluginClient.h
3 *
4 * Copyright (c) 2008-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
5 *
6 * This file is part of LMMS - https://lmms.io
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program (see COPYING); if not, write to the
20 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301 USA.
22 *
23 */
24
25#ifndef LMMS_REMOTE_PLUGIN_CLIENT_H
26#define LMMS_REMOTE_PLUGIN_CLIENT_H
27
28#include "RemotePluginBase.h"
29
30#include <stdexcept>
31
32#ifndef LMMS_BUILD_WIN32
33# include <condition_variable>
34# include <mutex>
35# include <thread>
36
37# include <signal.h>
38# include <unistd.h>
39#endif
40
41#include "LmmsTypes.h"
42#include "MidiEvent.h"
43#include "SharedMemory.h"
44#include "VstSyncData.h"
45
46namespace lmms
47{
48
49class SampleFrame;
50
52{
53public:
54#ifdef SYNC_WITH_SHM_FIFO
55 RemotePluginClient( const std::string& _shm_in, const std::string& _shm_out );
56#else
57 RemotePluginClient( const char * socketPath );
58#endif
59 ~RemotePluginClient() override;
60
62
63 bool processMessage( const message & _m ) override;
64
65 virtual void process( const SampleFrame* _in_buf,
66 SampleFrame* _out_buf ) = 0;
67
68 virtual void processMidiEvent( const MidiEvent&, const f_cnt_t /* _offset */ )
69 {
70 }
71
72 virtual void updateSampleRate()
73 {
74 }
75
76 virtual void updateBufferSize()
77 {
78 }
79
81 {
82 return m_sampleRate;
83 }
84
85 inline f_cnt_t bufferSize() const
86 {
87 return m_bufferSize;
88 }
89
90 void setInputCount( int _i )
91 {
92 m_inputCount = _i;
93 sendMessage( message( IdChangeInputCount ).addInt( _i ) );
94 }
95
96 void setOutputCount( int _i )
97 {
98 m_outputCount = _i;
99 sendMessage( message( IdChangeOutputCount ).addInt( _i ) );
100 }
101
102 void setInputOutputCount( int i, int o )
103 {
104 m_inputCount = i;
105 m_outputCount = o;
107 .addInt( i )
108 .addInt( o ) );
109 }
110
111 virtual int inputCount() const
112 {
113 return m_inputCount;
114 }
115
116 virtual int outputCount() const
117 {
118 return m_outputCount;
119 }
120
121 void debugMessage( const std::string & _s )
122 {
123 sendMessage( message( IdDebugMessage ).addString( _s ) );
124 }
125
126
127private:
128 void setShmKey(const std::string& key);
129 void doProcessing();
130
133
136
139} ;
140
141#ifndef LMMS_BUILD_WIN32
143{
144public:
146 m_stop{false},
147 m_thread{
148 [this]
149 {
150 using namespace std::literals::chrono_literals;
151 auto lock = std::unique_lock{m_mutex};
152 while (!m_cv.wait_for(lock, 500ms, [this] { return m_stop; }))
153 {
154 if (getppid() == 1)
155 {
156 kill(getpid(), SIGHUP);
157 break;
158 }
159 }
160 }
161 }
162 { }
163
165 {
166 {
167 const auto lock = std::unique_lock{m_mutex};
168 m_stop = true;
169 }
170 m_cv.notify_all();
171 m_thread.join();
172 }
173
174private:
175 bool m_stop;
176 std::mutex m_mutex;
177 std::condition_variable m_cv;
178 std::thread m_thread;
179};
180#endif // LMMS_BUILD_WIN32
181
182#ifdef SYNC_WITH_SHM_FIFO
183RemotePluginClient::RemotePluginClient( const std::string& _shm_in, const std::string& _shm_out ) :
184 RemotePluginBase( new shmFifo( _shm_in ), new shmFifo( _shm_out ) ),
185#else
188#endif
189 m_inputCount( 0 ),
190 m_outputCount( 0 ),
191 m_sampleRate( 44100 ),
192 m_bufferSize( 0 )
193{
194#ifndef SYNC_WITH_SHM_FIFO
195 struct sockaddr_un sa;
196 sa.sun_family = AF_LOCAL;
197
198 size_t length = strlen( socketPath );
199 if ( length >= sizeof sa.sun_path )
200 {
201 length = sizeof sa.sun_path - 1;
202 fprintf( stderr, "Socket path too long.\n" );
203 }
204 memcpy( sa.sun_path, socketPath, length );
205 sa.sun_path[length] = '\0';
206
207 m_socket = socket( PF_LOCAL, SOCK_STREAM, 0 );
208 if ( m_socket == -1 )
209 {
210 fprintf( stderr, "Could not connect to local server.\n" );
211 }
212 if ( ::connect( m_socket, (struct sockaddr *) &sa, sizeof sa ) == -1 )
213 {
214 fprintf( stderr, "Could not connect to local server.\n" );
215 }
216#endif
217}
218
219
220
221
223{
225
226#ifndef SYNC_WITH_SHM_FIFO
227 if ( close( m_socket ) == -1)
228 {
229 fprintf( stderr, "Error freeing resources.\n" );
230 }
231#endif
232}
233
234
235
236
241
242
243
244
246{
247 message reply_message( _m.id );
248 bool reply = false;
249 switch( _m.id )
250 {
251 case IdUndefined:
252 return false;
253
254 case IdSyncKey:
255 try
256 {
257 m_vstSyncData.attach(_m.getString(0));
258 }
259 catch (const std::runtime_error& error)
260 {
261 debugMessage(std::string{"Failed to attach sync data: "} + error.what() + '\n');
262 std::exit(EXIT_FAILURE);
263 }
264 m_bufferSize = m_vstSyncData->bufferSize;
265 m_sampleRate = m_vstSyncData->sampleRate;
266 reply_message.id = IdHostInfoGotten;
267 reply = true;
268 break;
269
271 m_sampleRate = _m.getInt();
273 reply_message.id = IdInformationUpdated;
274 reply = true;
275 break;
276
278 // Should LMMS gain the ability to change buffer size
279 // without a restart, it must wait for this message to
280 // complete processing or else risk VST crashes
281 m_bufferSize = _m.getInt();
283 break;
284
285 case IdQuit:
286 return false;
287
288 case IdMidiEvent:
290 MidiEvent( static_cast<MidiEventTypes>(
291 _m.getInt( 0 ) ),
292 _m.getInt( 1 ),
293 _m.getInt( 2 ),
294 _m.getInt( 3 ) ),
295 _m.getInt( 4 ) );
296 break;
297
299 doProcessing();
300 reply_message.id = IdProcessingDone;
301 reply = true;
302 break;
303
305 setShmKey(_m.getString(0));
306 break;
307
308 case IdInitDone:
309 break;
310
311 default:
312 {
313 char buf[64];
314 std::snprintf(buf, 64, "undefined message: %d\n", _m.id);
315 debugMessage( buf );
316 break;
317 }
318 }
319 if( reply )
320 {
321 sendMessage( reply_message );
322 }
323
324 return true;
325}
326
327
328
329
330void RemotePluginClient::setShmKey(const std::string& key)
331{
332 try
333 {
334 m_audioBuffer.attach(key);
335 }
336 catch (const std::runtime_error& error)
337 {
338 debugMessage(std::string{"failed getting shared memory: "} + error.what() + '\n');
339 }
340}
341
342
343
344
346{
347 if (m_audioBuffer)
348 {
349 process( (SampleFrame*)( m_inputCount > 0 ? m_audioBuffer.get() : nullptr ),
350 (SampleFrame*)( m_audioBuffer.get() +
352 }
353 else
354 {
355 debugMessage( "doProcessing(): have no shared memory!\n" );
356 }
357}
358
359
360} // namespace lmms
361
362#endif // LMMS_REMOTE_PLUGIN_CLIENT_H
static void message(int level, const char *fmt,...)
Definition adplugdb.cpp:120
void process(Alg_seq_ptr seq, bool tempo_flag, double tempo, bool flatten_flag)
Definition allegroconvert.cpp:42
Definition MidiEvent.h:37
bool m_stop
Definition RemotePluginClient.h:175
std::mutex m_mutex
Definition RemotePluginClient.h:176
PollParentThread()
Definition RemotePluginClient.h:145
std::thread m_thread
Definition RemotePluginClient.h:178
~PollParentThread()
Definition RemotePluginClient.h:164
std::condition_variable m_cv
Definition RemotePluginClient.h:177
Definition RemotePluginBase.h:355
int sendMessage(const message &_m)
int m_socket
Definition RemotePluginBase.h:568
void doProcessing()
Definition RemotePluginClient.h:345
void setInputCount(int _i)
Definition RemotePluginClient.h:90
virtual void processMidiEvent(const MidiEvent &, const f_cnt_t)
Definition RemotePluginClient.h:68
virtual int outputCount() const
Definition RemotePluginClient.h:116
~RemotePluginClient() override
Definition RemotePluginClient.h:222
virtual void updateSampleRate()
Definition RemotePluginClient.h:72
void debugMessage(const std::string &_s)
Definition RemotePluginClient.h:121
f_cnt_t m_bufferSize
Definition RemotePluginClient.h:138
bool processMessage(const message &_m) override
Definition RemotePluginClient.h:245
const VstSyncData * getVstSyncData()
Definition RemotePluginClient.h:237
void setInputOutputCount(int i, int o)
Definition RemotePluginClient.h:102
virtual int inputCount() const
Definition RemotePluginClient.h:111
RemotePluginClient(const char *socketPath)
Definition RemotePluginClient.h:186
sample_rate_t sampleRate() const
Definition RemotePluginClient.h:80
void setOutputCount(int _i)
Definition RemotePluginClient.h:96
virtual void process(const SampleFrame *_in_buf, SampleFrame *_out_buf)=0
SharedMemory< const VstSyncData > m_vstSyncData
Definition RemotePluginClient.h:132
sample_rate_t m_sampleRate
Definition RemotePluginClient.h:137
f_cnt_t bufferSize() const
Definition RemotePluginClient.h:85
void setShmKey(const std::string &key)
Definition RemotePluginClient.h:330
int m_inputCount
Definition RemotePluginClient.h:134
int m_outputCount
Definition RemotePluginClient.h:135
virtual void updateBufferSize()
Definition RemotePluginClient.h:76
SharedMemory< float[]> m_audioBuffer
Definition RemotePluginClient.h:131
Definition SampleFrame.h:41
Definition SharedMemory.h:147
register unsigned i
Definition inflate.c:1575
#define EXIT_FAILURE
Definition jerror.c:32
Definition AudioAlsa.cpp:35
std::uint32_t sample_rate_t
Definition LmmsTypes.h:42
std::uint64_t f_cnt_t
Definition LmmsTypes.h:43
MidiEventTypes
Definition Midi.h:34
@ IdDebugMessage
Definition RemotePluginBase.h:347
@ IdSyncKey
Definition RemotePluginBase.h:326
@ IdMidiEvent
Definition RemotePluginBase.h:330
@ IdBufferSizeInformation
Definition RemotePluginBase.h:328
@ IdChangeInputOutputCount
Definition RemotePluginBase.h:336
@ IdStartProcessing
Definition RemotePluginBase.h:331
@ IdChangeSharedMemoryKey
Definition RemotePluginBase.h:333
@ IdProcessingDone
Definition RemotePluginBase.h:332
@ IdInitDone
Definition RemotePluginBase.h:324
@ IdUndefined
Definition RemotePluginBase.h:322
@ IdHostInfoGotten
Definition RemotePluginBase.h:323
@ IdChangeOutputCount
Definition RemotePluginBase.h:335
@ IdQuit
Definition RemotePluginBase.h:325
@ IdInformationUpdated
Definition RemotePluginBase.h:329
@ IdSampleRateInformation
Definition RemotePluginBase.h:327
@ IdChangeInputCount
Definition RemotePluginBase.h:334
#define false
Definition ordinals.h:83
png_uint_32 length
Definition png.c:2247
Definition RemotePluginBase.h:358
std::string getString(int _p=0) const
Definition RemotePluginBase.h:395
int getInt(int _p=0) const
Definition RemotePluginBase.h:407
int id
Definition RemotePluginBase.h:422
Definition VstSyncData.h:43
memcpy(hh, h, RAND_HEAD_LEN)
ZCONST char * key
Definition crypt.c:587
int error
Definition extract.c:1038
else
Definition fileio.c:764
#define const
Definition zconf.h:137