1 /* 2 SuperCollider real time audio synthesis system 3 Copyright (c) 2002 James McCartney. All rights reserved. 4 http://www.audiosynth.com 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21 /* 22 * Having SequencedCommands allows performing actions that might otherwise require 23 * taking a mutex, which is undesirable in a real time thread. 24 * Some commands require several stages of processing at both the real time 25 * and non real time levels. This class does the messaging between levels for you 26 * so that you only need to write the functions. 27 */ 28 29 #pragma once 30 31 #include "OSC_Packet.h" 32 #include "SC_World.h" 33 #include "SC_BufGen.h" 34 #include "sc_msg_iter.h" 35 #include "SC_SndFileHelpers.hpp" 36 #include <new> 37 38 #define CallSequencedCommand(T, inWorld, inSize, inData, inReply) \ 39 void* space = World_Alloc(inWorld, sizeof(T)); \ 40 T* cmd = new (space) T(inWorld, inReply); \ 41 if (!cmd) \ 42 return kSCErr_Failed; \ 43 int err = cmd->Init(inData, inSize); \ 44 if (err) { \ 45 cmd->~T(); \ 46 World_Free(inWorld, space); \ 47 return err; \ 48 } \ 49 if (inWorld->mRealTime) \ 50 cmd->CallNextStage(); \ 51 else \ 52 cmd->CallEveryStage(); 53 54 55 class SC_SequencedCommand { 56 public: 57 SC_SequencedCommand(World* inWorld, ReplyAddress* inReplyAddress); 58 virtual ~SC_SequencedCommand(); 59 60 void Delete(); 61 62 void CallEveryStage(); 63 void CallNextStage(); 64 65 virtual int Init(char* inData, int inSize); 66 67 virtual bool Stage1(); // real time 68 virtual bool Stage2(); // non real time 69 virtual bool Stage3(); // real time 70 virtual void Stage4(); // non real time 71 72 void SendDone(const char* inCommandName); 73 void SendDoneWithIntValue(const char* inCommandName, int value); 74 75 76 protected: 77 int mNextStage; 78 ReplyAddress mReplyAddress; 79 World* mWorld; 80 81 int mMsgSize; 82 char* mMsgData; 83 84 virtual void CallDestructor() = 0; 85 }; 86 87 /////////////////////////////////////////////////////////////////////////// 88 89 class SyncCmd : public SC_SequencedCommand { 90 public: 91 SyncCmd(World* inWorld, ReplyAddress* inReplyAddress); 92 93 virtual int Init(char* inData, int inSize); 94 95 virtual bool Stage2(); // non real time 96 virtual bool Stage3(); // real time 97 virtual void Stage4(); // non real time 98 99 protected: 100 virtual void CallDestructor(); 101 int mID; 102 }; 103 104 /////////////////////////////////////////////////////////////////////////// 105 106 class BufGenCmd : public SC_SequencedCommand { 107 public: 108 BufGenCmd(World* inWorld, ReplyAddress* inReplyAddress); 109 virtual ~BufGenCmd(); 110 111 virtual int Init(char* inData, int inSize); 112 113 virtual bool Stage2(); // non real time 114 virtual bool Stage3(); // real time 115 virtual void Stage4(); // non real time 116 117 protected: 118 int mBufIndex; 119 BufGen* mBufGen; 120 sc_msg_iter mMsg; 121 char* mData; 122 int mSize; 123 SndBuf mSndBuf; 124 float* mFreeData; 125 126 virtual void CallDestructor(); 127 }; 128 129 /////////////////////////////////////////////////////////////////////////// 130 131 class BufAllocCmd : public SC_SequencedCommand { 132 public: 133 BufAllocCmd(World* inWorld, ReplyAddress* inReplyAddress); 134 135 virtual int Init(char* inData, int inSize); 136 137 virtual bool Stage2(); // non real time 138 virtual bool Stage3(); // real time 139 virtual void Stage4(); // non real time 140 141 protected: 142 int mBufIndex; 143 SndBuf mSndBuf; 144 int mNumChannels, mNumFrames; 145 float* mFreeData; 146 147 virtual void CallDestructor(); 148 }; 149 150 /////////////////////////////////////////////////////////////////////////// 151 152 153 class BufFreeCmd : public SC_SequencedCommand { 154 public: 155 BufFreeCmd(World* inWorld, ReplyAddress* inReplyAddress); 156 157 virtual int Init(char* inData, int inSize); 158 159 virtual bool Stage2(); // non real time 160 virtual bool Stage3(); // real time 161 virtual void Stage4(); // non real time 162 163 protected: 164 int mBufIndex; 165 float* mFreeData; 166 167 virtual void CallDestructor(); 168 }; 169 170 171 /////////////////////////////////////////////////////////////////////////// 172 173 174 class BufCloseCmd : public SC_SequencedCommand { 175 public: 176 BufCloseCmd(World* inWorld, ReplyAddress* inReplyAddress); 177 178 virtual int Init(char* inData, int inSize); 179 180 virtual bool Stage2(); // non real time 181 virtual bool Stage3(); // real time 182 virtual void Stage4(); // non real time 183 184 protected: 185 int mBufIndex; 186 187 virtual void CallDestructor(); 188 }; 189 190 191 /////////////////////////////////////////////////////////////////////////// 192 193 194 class BufZeroCmd : public SC_SequencedCommand { 195 public: 196 BufZeroCmd(World* inWorld, ReplyAddress* inReplyAddress); 197 198 virtual int Init(char* inData, int inSize); 199 200 virtual bool Stage2(); // non real time 201 virtual bool Stage3(); // real time 202 virtual void Stage4(); // non real time 203 204 protected: 205 int mBufIndex; 206 207 virtual void CallDestructor(); 208 }; 209 210 /////////////////////////////////////////////////////////////////////////// 211 212 class BufAllocReadCmd : public SC_SequencedCommand { 213 public: 214 BufAllocReadCmd(World* inWorld, ReplyAddress* inReplyAddress); 215 virtual ~BufAllocReadCmd(); 216 217 virtual int Init(char* inData, int inSize); 218 219 virtual bool Stage2(); // non real time 220 virtual bool Stage3(); // real time 221 virtual void Stage4(); // non real time 222 223 protected: 224 int mBufIndex; 225 float* mFreeData; 226 SndBuf mSndBuf; 227 char* mFilename; 228 int mFileOffset, mNumFrames; 229 230 virtual void CallDestructor(); 231 }; 232 233 /////////////////////////////////////////////////////////////////////////// 234 235 class BufReadCmd : public SC_SequencedCommand { 236 public: 237 BufReadCmd(World* inWorld, ReplyAddress* inReplyAddress); 238 virtual ~BufReadCmd(); 239 240 virtual int Init(char* inData, int inSize); 241 242 virtual bool Stage2(); // non real time 243 virtual bool Stage3(); // real time 244 virtual void Stage4(); // non real time 245 246 protected: 247 int mBufIndex; 248 char* mFilename; 249 int mFileOffset, mNumFrames, mBufOffset; 250 bool mLeaveFileOpen; 251 double mSampleRate; 252 virtual void CallDestructor(); 253 }; 254 255 /////////////////////////////////////////////////////////////////////////// 256 257 class SC_BufReadCommand : public SC_SequencedCommand { 258 public: 259 enum { kMaxNumChannels = 32 }; 260 261 SC_BufReadCommand(World* inWorld, ReplyAddress* inReplyAddress); 262 virtual ~SC_BufReadCommand(); 263 264 protected: 265 void InitChannels(sc_msg_iter& msg); 266 bool CheckChannels(int inNumChannels); 267 void CopyChannels(float* dst, float* src, size_t srcChannels, size_t numFrames); 268 269 protected: 270 int mNumChannels; 271 int mChannels[kMaxNumChannels]; 272 }; 273 274 /////////////////////////////////////////////////////////////////////////// 275 276 class BufAllocReadChannelCmd : public SC_BufReadCommand { 277 public: 278 BufAllocReadChannelCmd(World* inWorld, ReplyAddress* inReplyAddress); 279 virtual ~BufAllocReadChannelCmd(); 280 281 virtual int Init(char* inData, int inSize); 282 283 virtual bool Stage2(); // non real time 284 virtual bool Stage3(); // real time 285 virtual void Stage4(); // non real time 286 287 protected: 288 int mBufIndex; 289 float* mFreeData; 290 SndBuf mSndBuf; 291 char* mFilename; 292 int mFileOffset, mNumFrames; 293 virtual void CallDestructor(); 294 }; 295 296 /////////////////////////////////////////////////////////////////////////// 297 298 class BufReadChannelCmd : public SC_BufReadCommand { 299 public: 300 BufReadChannelCmd(World* inWorld, ReplyAddress* inReplyAddress); 301 virtual ~BufReadChannelCmd(); 302 303 virtual int Init(char* inData, int inSize); 304 305 virtual bool Stage2(); // non real time 306 virtual bool Stage3(); // real time 307 virtual void Stage4(); // non real time 308 309 protected: 310 int mBufIndex; 311 char* mFilename; 312 int mFileOffset, mNumFrames, mBufOffset; 313 bool mLeaveFileOpen; 314 double mSampleRate; 315 virtual void CallDestructor(); 316 }; 317 318 /////////////////////////////////////////////////////////////////////////// 319 320 class BufWriteCmd : public SC_SequencedCommand { 321 public: 322 BufWriteCmd(World* inWorld, ReplyAddress* inReplyAddress); 323 virtual ~BufWriteCmd(); 324 325 virtual int Init(char* inData, int inSize); 326 327 virtual bool Stage2(); // non real time 328 virtual bool Stage3(); // real time 329 virtual void Stage4(); // non real time 330 331 protected: 332 int mBufIndex; 333 char* mFilename; 334 #ifndef NO_LIBSNDFILE 335 SF_INFO mFileInfo; 336 #endif 337 int mNumFrames, mBufOffset; 338 bool mLeaveFileOpen; 339 340 virtual void CallDestructor(); 341 }; 342 343 /////////////////////////////////////////////////////////////////////////// 344 345 class AudioQuitCmd : public SC_SequencedCommand { 346 public: 347 AudioQuitCmd(World* inWorld, ReplyAddress* inReplyAddress); 348 349 virtual bool Stage2(); // non real time 350 virtual bool Stage3(); // real time 351 virtual void Stage4(); // non real time 352 353 protected: 354 virtual void CallDestructor(); 355 }; 356 357 /////////////////////////////////////////////////////////////////////////// 358 359 class AudioStatusCmd : public SC_SequencedCommand { 360 public: 361 AudioStatusCmd(World* inWorld, ReplyAddress* inReplyAddress); 362 363 virtual bool Stage2(); // non real time 364 365 protected: 366 virtual void CallDestructor(); 367 }; 368 369 /////////////////////////////////////////////////////////////////////////// 370 371 class NotifyCmd : public SC_SequencedCommand { 372 public: 373 NotifyCmd(World* inWorld, ReplyAddress* inReplyAddress); 374 375 virtual int Init(char* inData, int inSize); 376 377 virtual bool Stage2(); // non real time 378 379 protected: 380 virtual void CallDestructor(); 381 382 int mOnOff; 383 int mID; 384 }; 385 386 387 /////////////////////////////////////////////////////////////////////////// 388 389 #define CallSendFailureCommand(inWorld, inCmdName, inErrString, inReply) \ 390 void* space = World_Alloc(inWorld, sizeof(SendFailureCmd)); \ 391 SendFailureCmd* cmd = new (space) SendFailureCmd(inWorld, inReply); \ 392 if (!cmd) \ 393 return kSCErr_Failed; \ 394 cmd->InitSendFailureCmd(inCmdName, inErrString); \ 395 if (inWorld->mRealTime) \ 396 cmd->CallNextStage(); \ 397 else \ 398 cmd->CallEveryStage(); 399 400 class SendFailureCmd : public SC_SequencedCommand { 401 public: 402 SendFailureCmd(World* inWorld, ReplyAddress* inReplyAddress); 403 virtual ~SendFailureCmd(); 404 405 virtual void InitSendFailureCmd(const char* inCmdName, const char* inErrString); 406 407 virtual bool Stage2(); // non real time 408 409 protected: 410 char *mCmdName, *mErrString; 411 412 virtual void CallDestructor(); 413 }; 414 415 /////////////////////////////////////////////////////////////////////////// 416 417 #include "SC_GraphDef.h" 418 419 class LoadSynthDefCmd : public SC_SequencedCommand { 420 public: 421 LoadSynthDefCmd(World* inWorld, ReplyAddress* inReplyAddress); 422 virtual ~LoadSynthDefCmd(); 423 424 virtual int Init(char* inData, int inSize); 425 426 virtual bool Stage2(); // non real time 427 virtual bool Stage3(); // real time 428 virtual void Stage4(); // non real time 429 430 protected: 431 char* mFilename; 432 GraphDef* mDefs; 433 434 virtual void CallDestructor(); 435 }; 436 437 /////////////////////////////////////////////////////////////////////////// 438 439 #include "SC_GraphDef.h" 440 441 class RecvSynthDefCmd : public SC_SequencedCommand { 442 public: 443 RecvSynthDefCmd(World* inWorld, ReplyAddress* inReplyAddress); 444 virtual ~RecvSynthDefCmd(); 445 446 virtual int Init(char* inData, int inSize); 447 448 virtual bool Stage2(); // non real time 449 virtual bool Stage3(); // real time 450 virtual void Stage4(); // non real time 451 452 protected: 453 char* mBuffer; 454 GraphDef* mDefs; 455 456 virtual void CallDestructor(); 457 }; 458 459 /////////////////////////////////////////////////////////////////////////// 460 461 class LoadSynthDefDirCmd : public SC_SequencedCommand { 462 public: 463 LoadSynthDefDirCmd(World* inWorld, ReplyAddress* inReplyAddress); 464 virtual ~LoadSynthDefDirCmd(); 465 466 virtual int Init(char* inData, int inSize); 467 468 virtual bool Stage2(); // non real time 469 virtual bool Stage3(); // real time 470 virtual void Stage4(); // non real time 471 472 protected: 473 char* mFilename; 474 GraphDef* mDefs; 475 476 virtual void CallDestructor(); 477 }; 478 479 /////////////////////////////////////////////////////////////////////////// 480 481 class SendReplyCmd : public SC_SequencedCommand { 482 public: 483 SendReplyCmd(World* inWorld, ReplyAddress* inReplyAddress); 484 485 virtual int Init(char* inData, int inSize); 486 487 virtual bool Stage2(); // non real time 488 489 protected: 490 virtual void CallDestructor(); 491 }; 492 493 /////////////////////////////////////////////////////////////////////////// 494 495 496 typedef bool (*AsyncStageFn)(World* inWorld, void* cmdData); 497 typedef void (*AsyncFreeFn)(World* inWorld, void* cmdData); 498 499 class AsyncPlugInCmd : public SC_SequencedCommand { 500 public: 501 AsyncPlugInCmd(World* inWorld, ReplyAddress* inReplyAddress, const char* cmdName, void* cmdData, 502 AsyncStageFn stage2, // stage2 is non real time 503 AsyncStageFn stage3, // stage3 is real time - completion msg performed if stage3 returns true 504 AsyncStageFn stage4, // stage4 is non real time - sends done if stage4 returns true 505 AsyncFreeFn cleanup, int completionMsgSize, void* completionMsgData); 506 507 virtual ~AsyncPlugInCmd(); 508 509 virtual bool Stage2(); // non real time 510 virtual bool Stage3(); // real time 511 virtual void Stage4(); // non real time 512 513 protected: 514 const char* mCmdName; 515 void* mCmdData; 516 AsyncStageFn mStage2, mStage3, mStage4; 517 AsyncFreeFn mCleanup; 518 519 virtual void CallDestructor(); 520 }; 521