void SendFailureCmd::InitSendFailureCmd(const char *inCmdName, const char* inErrString) { mCmdName = (char*)World_Alloc(mWorld, strlen(inCmdName)+1); strcpy(mCmdName, inCmdName); mErrString = (char*)World_Alloc(mWorld, strlen(inErrString)+1); strcpy(mErrString, inErrString); }
int BufReadChannelCmd::Init(char *inData, int inSize) { sc_msg_iter msg(inSize, inData); mBufIndex = msg.geti(); const char *filename = msg.gets(); if (!filename) return kSCErr_WrongArgType; if(mWorld->mRestrictedPath){ mFilename = allocAndRestrictPath(mWorld, filename, mWorld->mRestrictedPath); }else{ mFilename = (char*)World_Alloc(mWorld, strlen(filename)+1); strcpy(mFilename, filename); } mFileOffset = msg.geti(); mNumFrames = msg.geti(-1); mBufOffset = msg.geti(); mLeaveFileOpen = msg.geti(); InitChannels(msg); GET_COMPLETION_MSG(msg); return kSCErr_None; }
int SendReplyCmd::Init(char *inData, int inSize) { mMsgSize = inSize; mMsgData = (char*)World_Alloc(mWorld, mMsgSize); memcpy(mMsgData, inData, inSize); return kSCErr_None; }
int BufWriteCmd::Init(char *inData, int inSize) { #ifdef NO_LIBSNDFILE SendFailure(&mReplyAddress, "/b_write", "scsynth compiled without libsndfile\n"); scprintf("scsynth compiled without libsndfile\n"); return false; #else sc_msg_iter msg(inSize, inData); mBufIndex = msg.geti(); const char *filename = msg.gets(); if (!filename) return kSCErr_WrongArgType; if(mWorld->mRestrictedPath){ mFilename = allocAndRestrictPath(mWorld, filename, mWorld->mRestrictedPath); }else{ mFilename = (char*)World_Alloc(mWorld, strlen(filename)+1); strcpy(mFilename, filename); } const char *headerFormatString = msg.gets("aiff"); const char *sampleFormatString = msg.gets("int16"); mNumFrames = msg.geti(-1); mBufOffset = msg.geti(); mLeaveFileOpen = msg.geti(); GET_COMPLETION_MSG(msg); memset(&mFileInfo, 0, sizeof(mFileInfo)); return sndfileFormatInfoFromStrings(&mFileInfo, headerFormatString, sampleFormatString); #endif }
int RecvSynthDefCmd::Init(char *inData, int inSize) { sc_msg_iter msg(inSize, inData); int size = msg.getbsize(); if (!size) throw kSCErr_WrongArgType; mBuffer = (char*)World_Alloc(mWorld, size); msg.getb(mBuffer, size); GET_COMPLETION_MSG(msg); mDefs = 0; return kSCErr_None; }
SCErr SendReplyCmd_d_removed(World * inWorld,int inSize,char* inData, ReplyAddress *inReply) { void* space = World_Alloc(inWorld, sizeof(SendReplyCmd)); SendReplyCmd *cmd = new (space) SendReplyCmd(inWorld, inReply); if (!cmd) return kSCErr_Failed; int err = cmd->Init(inData, inSize); if (err) { cmd->~SendReplyCmd(); World_Free(inWorld, space); return err; } if (inWorld->mRealTime) cmd->CallNextStage(); else cmd->CallEveryStage(); return kSCErr_None; }
int BufGenCmd::Init(char *inData, int inSize) { mSize = inSize; mData = (char*)World_Alloc(mWorld, mSize); memcpy(mData, inData, mSize); sc_msg_iter msg(mSize, mData); mBufIndex = msg.geti(); int32 *genName = msg.gets4(); if (!genName) return kSCErr_WrongArgType; mBufGen = GetBufGen(genName); if (!mBufGen) return kSCErr_BufGenNotFound; mMsg = msg; return kSCErr_None; }
int LoadSynthDefDirCmd::Init(char *inData, int inSize) { sc_msg_iter msg(inSize, inData); const char *filename = msg.gets(); if (!filename) return kSCErr_WrongArgType; if(mWorld->mRestrictedPath){ mFilename = allocAndRestrictPath(mWorld, filename, mWorld->mRestrictedPath); }else{ mFilename = (char*)World_Alloc(mWorld, strlen(filename)+1); strcpy(mFilename, filename); } GET_COMPLETION_MSG(msg); mDefs = 0; return kSCErr_None; }
AsyncPlugInCmd::AsyncPlugInCmd(World *inWorld, ReplyAddress *inReplyAddress, const char* cmdName, void *cmdData, AsyncStageFn stage2, // stage2 is non real time AsyncStageFn stage3, // stage3 is real time - completion msg performed if stage3 returns true AsyncStageFn stage4, // stage4 is non real time - sends done if stage4 returns true AsyncFreeFn cleanup, // cleanup is called in real time int completionMsgSize, void* completionMsgData) : SC_SequencedCommand(inWorld, inReplyAddress), mCmdName(cmdName), mCmdData(cmdData), mStage2(stage2), mStage3(stage3), mStage4(stage4), mCleanup(cleanup) { if (completionMsgSize && completionMsgData) { mMsgSize = completionMsgSize; mMsgData = (char*)World_Alloc(mWorld, mMsgSize); memcpy(mMsgData, completionMsgData, mMsgSize); } }
char* allocAndRestrictPath(World *mWorld, const char* inPath, const char* restrictBase){ char strbuf[PATH_MAX]; int offset = 0; int remain = PATH_MAX; // Ensure begins with the base if(strncmp(inPath, restrictBase, strlen(restrictBase)) != 0){ strcpy(strbuf, restrictBase); offset = strlen(restrictBase); remain -= offset; if(inPath[0]!='/' && strbuf[strlen(strbuf)-1]!='/'){ strbuf[offset] = '/'; ++offset; --remain; } } // Now copy string, but discard any ".." (which could be benign, but easy to abuse) SC_StringParser sp(inPath, '/'); size_t tokenlen; while (!sp.AtEnd()) { const char *token = const_cast<char *>(sp.NextToken()); tokenlen = strlen(token); // now add the new token, then a slash, as long as token is neither dodgy nor overflows if(strcmp(token, "..")!=0 && remain > tokenlen){ strcpy(strbuf+offset, token); offset += tokenlen; remain -= tokenlen; if(!sp.AtEnd()) { strbuf[offset] = '/'; ++offset; --remain; } } } // Now we can make a long-term home for the string and return it char* saferPath = (char*)World_Alloc(mWorld, strlen(strbuf)+1); strcpy(saferPath, strbuf); return saferPath; }
int PerformAsynchronousCommand( World *inWorld, void* replyAddr, const char* cmdName, void *cmdData, AsyncStageFn stage2, // stage2 is non real time AsyncStageFn stage3, // stage3 is real time - completion msg performed if stage3 returns true AsyncStageFn stage4, // stage4 is non real time - sends done if stage4 returns true AsyncFreeFn cleanup, int completionMsgSize, void* completionMsgData ) { void* space = World_Alloc(inWorld, sizeof(AsyncPlugInCmd)); AsyncPlugInCmd *cmd = new (space) AsyncPlugInCmd(inWorld, (ReplyAddress*)replyAddr, cmdName, cmdData, stage2, stage3, stage4, cleanup, completionMsgSize, completionMsgData); if (!cmd) return kSCErr_Failed; if (inWorld->mRealTime) cmd->CallNextStage(); else cmd->CallEveryStage(); return kSCErr_None; }
// Send a reply from a node to a client program. // // This function puts the reply on a FIFO which is harvested by another thread that // actually does the sending. // // NOTE: Only to be called from the realtime thread. void Node_SendReply(Node* inNode, int replyID, const char* cmdName, int numArgs, const float* values) { World *world = inNode->mWorld; if (!world->mRealTime) return; const int cmdNameSize = strlen(cmdName); void* mem = World_Alloc(world, cmdNameSize + numArgs*sizeof(float)); if (mem == 0) return; NodeReplyMsg msg; msg.mWorld = world; msg.mNodeID = inNode->mID; msg.mID = replyID; msg.mValues = (float*)((char*)mem + cmdNameSize); memcpy(msg.mValues, values, numArgs*sizeof(float)); msg.mNumArgs = numArgs; msg.mCmdName = (char*)mem; memcpy(msg.mCmdName, cmdName, cmdNameSize); msg.mCmdNameSize = cmdNameSize; msg.mRTMemory = mem; world->hw->mNodeMsgs.Write(msg); }
// create a new node int Node_New(World *inWorld, NodeDef *def, int32 inID, Node** outNode) { if (inID < 0) { if (inID == -1) { // -1 means generate an id for the event HiddenWorld* hw = inWorld->hw; inID = hw->mHiddenID = (hw->mHiddenID - 8) | 0x80000000; } else { return kSCErr_ReservedNodeID; } } if (World_GetNode(inWorld, inID)) { return kSCErr_DuplicateNodeID; } Node* node = (Node*)World_Alloc(inWorld, def->mAllocSize); node->mWorld = inWorld; node->mDef = def; node->mParent = 0; node->mPrev = 0; node->mNext = 0; node->mIsGroup = false; node->mID = inID; node->mHash = Hash(inID); if (!World_AddNode(inWorld, node)) { World_Free(inWorld, node); return kSCErr_TooManyNodes; } inWorld->hw->mRecentID = inID; *outNode = node; return kSCErr_None; }