/*JSON{ "type":"idle", "generate" : "jswrap_waveform_idle", "ifndef" : "SAVE_ON_FLASH" }*/ bool jswrap_waveform_idle() { JsVar *waveforms = jsvObjectGetChild(execInfo.hiddenRoot, JSI_WAVEFORM_NAME, 0); if (waveforms) { JsvArrayIterator it; jsvArrayIteratorNew(&it, waveforms); while (jsvArrayIteratorHasElement(&it)) { JsVar *waveform = jsvArrayIteratorGetElement(&it); bool running = jsvGetBoolAndUnLock(jsvObjectGetChild(waveform, "running", 0)); if (running) { JsVar *buffer = jswrap_waveform_getBuffer(waveform,0,0); UtilTimerTask task; // Search for a timer task if (!jstGetLastBufferTimerTask(buffer, &task)) { // if the timer task is now gone... JsVar *arrayBuffer = jsvObjectGetChild(waveform, "buffer", 0); jsiQueueObjectCallbacks(waveform, "#onfinish", &arrayBuffer, 1); jsvUnLock(arrayBuffer); running = false; jsvUnLock(jsvObjectSetChild(waveform, "running", jsvNewFromBool(running))); } else { // If the timer task is still there... if (task.data.buffer.nextBuffer && task.data.buffer.nextBuffer != task.data.buffer.currentBuffer) { // if it is a double-buffered task int currentBuffer = (jsvGetRef(buffer)==task.data.buffer.currentBuffer) ? 0 : 1; JsVar *oldBuffer = jsvObjectGetChild(waveform, "currentBuffer", JSV_INTEGER); if (jsvGetInteger(oldBuffer) !=currentBuffer) { // buffers have changed - fire off a 'buffer' event with the buffer that needs to be filled jsvSetInteger(oldBuffer, currentBuffer); JsVar *arrayBuffer = jsvObjectGetChild(waveform, (currentBuffer==0) ? "buffer" : "buffer2", 0); jsiQueueObjectCallbacks(waveform, "#onbuffer", &arrayBuffer, 1); jsvUnLock(arrayBuffer); } jsvUnLock(oldBuffer); } } jsvUnLock(buffer); } jsvUnLock(waveform); // if not running, remove waveform from this list if (!running) jsvArrayIteratorRemoveAndGotoNext(&it, waveforms); else jsvArrayIteratorNext(&it); } jsvArrayIteratorFree(&it); jsvUnLock(waveforms); } return false; // no need to stay awake - an IRQ will wake us }
static bool handlePipe(JsVar *arr, JsvObjectIterator *it, JsVar* pipe) { bool paused = jsvGetBoolAndUnLock(jsvObjectGetChild(pipe,"drainWait",0)); if (paused) return false; JsVar *position = jsvObjectGetChild(pipe,"position",0); JsVar *chunkSize = jsvObjectGetChild(pipe,"chunkSize",0); JsVar *source = jsvObjectGetChild(pipe,"source",0); JsVar *destination = jsvObjectGetChild(pipe,"destination",0); bool dataTransferred = false; if(source && destination && chunkSize && position) { JsVar *readFunc = jspGetNamedField(source, "read", false); JsVar *writeFunc = jspGetNamedField(destination, "write", false); if (jsvIsFunction(readFunc) && jsvIsFunction(writeFunc)) { // do the objects have the necessary methods on them? JsVar *buffer = jspExecuteFunction(readFunc, source, 1, &chunkSize); if(buffer) { JsVarInt bufferSize = jsvGetLength(buffer); if (bufferSize>0) { JsVar *response = jspExecuteFunction(writeFunc, destination, 1, &buffer); if (jsvIsBoolean(response) && jsvGetBool(response)==false) { // If boolean false was returned, wait for drain event (http://nodejs.org/api/stream.html#stream_writable_write_chunk_encoding_callback) jsvUnLock(jsvObjectSetChild(pipe,"drainWait",jsvNewFromBool(true))); } jsvUnLock(response); jsvSetInteger(position, jsvGetInteger(position) + bufferSize); } jsvUnLock(buffer); dataTransferred = true; // so we don't close the pipe if we get an empty string } } else { if(!jsvIsFunction(readFunc)) jsExceptionHere(JSET_ERROR, "Source Stream does not implement the required read(length) method."); if(!jsvIsFunction(writeFunc)) jsExceptionHere(JSET_ERROR, "Destination Stream does not implement the required write(buffer) method."); } jsvUnLock(readFunc); jsvUnLock(writeFunc); } if(!dataTransferred) { // when no more chunks are possible, execute the callback handlePipeClose(arr, it, pipe); } jsvUnLock(source); jsvUnLock(destination); jsvUnLock(chunkSize); jsvUnLock(position); return dataTransferred; }
/*JSON{ "type":"method", "class": "Array", "name" : "splice", "description" : "Both remove and add items to an array", "generate" : "jswrap_array_splice", "params" : [ [ "index", "int", "Index at which to start changing the array. If negative, will begin that many elements from the end"], [ "howMany", "JsVar", "An integer indicating the number of old array elements to remove. If howMany is 0, no elements are removed."], [ "element1", "JsVar", "A new item to add (optional)" ], [ "element2", "JsVar", "A new item to add (optional)" ], [ "element3", "JsVar", "A new item to add (optional)" ], [ "element4", "JsVar", "A new item to add (optional)" ], [ "element5", "JsVar", "A new item to add (optional)" ], [ "element6", "JsVar", "A new item to add (optional)" ] ], "return" : ["JsVar", "An array containing the removed elements. If only one element is removed, an array of one element is returned."] }*/ JsVar *jswrap_array_splice(JsVar *parent, JsVarInt index, JsVar *howManyVar, JsVar *element1, JsVar *element2, JsVar *element3, JsVar *element4, JsVar *element5, JsVar *element6) { JsVarInt len = jsvGetArrayLength(parent); if (index<0) index+=len; if (index<0) index=0; if (index>len) index=len; JsVarInt howMany = len; // how many to delete! if (jsvIsInt(howManyVar)) howMany = jsvGetInteger(howManyVar); if (howMany > len-index) howMany = len-index; JsVarInt newItems = 0; if (element1) newItems++; if (element2) newItems++; if (element3) newItems++; if (element4) newItems++; if (element5) newItems++; if (element6) newItems++; JsVarInt shift = newItems-howMany; bool needToAdd = false; JsVar *result = jsvNewWithFlags(JSV_ARRAY); JsArrayIterator it; jsvArrayIteratorNew(&it, parent); while (jsvArrayIteratorHasElement(&it) && !needToAdd) { bool goToNext = true; JsVar *idxVar = jsvArrayIteratorGetIndex(&it); if (idxVar && jsvIsInt(idxVar)) { JsVarInt idx = jsvGetInteger(idxVar); if (idx<index) { // do nothing... } else if (idx<index+howMany) { // must delete if (result) { // append to result array JsVar *el = jsvArrayIteratorGetElement(&it); jsvArrayPush(result, el); jsvUnLock(el); } // delete goToNext = false; JsVar *toRemove = jsvArrayIteratorGetIndex(&it); jsvArrayIteratorNext(&it); jsvRemoveChild(parent, toRemove); jsvUnLock(toRemove); } else { // we're greater than the amount we need to remove now needToAdd = true; goToNext = false; } } jsvUnLock(idxVar); if (goToNext) jsvArrayIteratorNext(&it); } // now we add everything JsVar *beforeIndex = jsvArrayIteratorGetIndex(&it); if (element1) jsvArrayInsertBefore(parent, beforeIndex, element1); if (element2) jsvArrayInsertBefore(parent, beforeIndex, element2); if (element3) jsvArrayInsertBefore(parent, beforeIndex, element3); if (element4) jsvArrayInsertBefore(parent, beforeIndex, element4); if (element5) jsvArrayInsertBefore(parent, beforeIndex, element5); if (element6) jsvArrayInsertBefore(parent, beforeIndex, element6); jsvUnLock(beforeIndex); // And finally renumber while (jsvArrayIteratorHasElement(&it)) { JsVar *idxVar = jsvArrayIteratorGetIndex(&it); if (idxVar && jsvIsInt(idxVar)) { jsvSetInteger(idxVar, jsvGetInteger(idxVar)+shift); } jsvUnLock(idxVar); jsvArrayIteratorNext(&it); } // free jsvArrayIteratorFree(&it); return result; }
/*JSON{ "type" : "method", "class" : "Array", "name" : "splice", "generate" : "jswrap_array_splice", "params" : [ ["index","int","Index at which to start changing the array. If negative, will begin that many elements from the end"], ["howMany","JsVar","An integer indicating the number of old array elements to remove. If howMany is 0, no elements are removed."], ["elements","JsVarArray","One or more items to add to the array"] ], "return" : ["JsVar","An array containing the removed elements. If only one element is removed, an array of one element is returned."] } Both remove and add items to an array */ JsVar *jswrap_array_splice(JsVar *parent, JsVarInt index, JsVar *howManyVar, JsVar *elements) { if (!jsvIsArray(parent)) return 0; JsVarInt len = jsvGetArrayLength(parent); if (index<0) index+=len; if (index<0) index=0; if (index>len) index=len; JsVarInt howMany = len; // how many to delete! if (jsvIsInt(howManyVar)) howMany = jsvGetInteger(howManyVar); if (howMany > len-index) howMany = len-index; JsVarInt newItems = jsvGetArrayLength(elements); JsVarInt shift = newItems-howMany; bool needToAdd = false; JsVar *result = jsvNewEmptyArray(); JsvObjectIterator it; jsvObjectIteratorNew(&it, parent); while (jsvObjectIteratorHasValue(&it) && !needToAdd) { bool goToNext = true; JsVar *idxVar = jsvObjectIteratorGetKey(&it); if (idxVar && jsvIsInt(idxVar)) { JsVarInt idx = jsvGetInteger(idxVar); if (idx<index) { // do nothing... } else if (idx<index+howMany) { // must delete if (result) { // append to result array JsVar *el = jsvObjectIteratorGetValue(&it); jsvArrayPushAndUnLock(result, el); } // delete goToNext = false; JsVar *toRemove = jsvObjectIteratorGetKey(&it); jsvObjectIteratorNext(&it); jsvRemoveChild(parent, toRemove); jsvUnLock(toRemove); } else { // we're greater than the amount we need to remove now needToAdd = true; goToNext = false; } } jsvUnLock(idxVar); if (goToNext) jsvObjectIteratorNext(&it); } // now we add everything JsVar *beforeIndex = jsvObjectIteratorGetKey(&it); JsvObjectIterator itElement; jsvObjectIteratorNew(&itElement, elements); while (jsvObjectIteratorHasValue(&itElement)) { JsVar *element = jsvObjectIteratorGetValue(&itElement); jsvArrayInsertBefore(parent, beforeIndex, element); jsvUnLock(element); jsvObjectIteratorNext(&itElement); } jsvObjectIteratorFree(&itElement); jsvUnLock(beforeIndex); // And finally renumber while (jsvObjectIteratorHasValue(&it)) { JsVar *idxVar = jsvObjectIteratorGetKey(&it); if (idxVar && jsvIsInt(idxVar)) { jsvSetInteger(idxVar, jsvGetInteger(idxVar)+shift); } jsvUnLock(idxVar); jsvObjectIteratorNext(&it); } // free jsvObjectIteratorFree(&it); // and reset array size jsvSetArrayLength(parent, len + shift, false); return result; }
static void handlePipeClose(JsVar *arr, JsvObjectIterator *it, JsVar* pipe) { jsiQueueObjectCallbacks(pipe, "#oncomplete", &pipe, 1); // Check the source to see if there was more data... It may not be a stream, // but if it is and it has data it should have a a STREAM_BUFFER_NAME field JsVar *source = jsvObjectGetChild(pipe,"source",0); JsVar *destination = jsvObjectGetChild(pipe,"destination",0); if (source && destination) { JsVar *buffer = jsvObjectGetChild(source, STREAM_BUFFER_NAME, 0); if (buffer && jsvGetStringLength(buffer)) { jsvObjectSetChild(source, STREAM_BUFFER_NAME, 0); // remove outstanding data /* call write fn - we ignore drain/etc here because the source has just closed and we want to get this sorted quickly */ JsVar *writeFunc = jspGetNamedField(destination, "write", false); if (jsvIsFunction(writeFunc)) // do the objects have the necessary methods on them? jsvUnLock(jspExecuteFunction(writeFunc, destination, 1, &buffer)); jsvUnLock(writeFunc); // update position JsVar *position = jsvObjectGetChild(pipe,"position",0); jsvSetInteger(position, jsvGetInteger(position) + (JsVarInt)jsvGetStringLength(buffer)); jsvUnLock(position); } jsvUnLock(buffer); } // also call 'end' if 'end' was passed as an initialisation option if (jsvGetBoolAndUnLock(jsvObjectGetChild(pipe,"end",0))) { // call destination.end if available if (destination) { // remove our drain and close listeners. // TODO: This removes ALL listeners. Maybe we should just remove ours? jswrap_object_removeAllListeners_cstr(destination, "drain"); jswrap_object_removeAllListeners_cstr(destination, "close"); // execute the 'end' function JsVar *endFunc = jspGetNamedField(destination, "end", false); if (endFunc) { jsvUnLock(jspExecuteFunction(endFunc, destination, 0, 0)); jsvUnLock(endFunc); } // execute the 'close' function JsVar *closeFunc = jspGetNamedField(destination, "close", false); if (closeFunc) { jsvUnLock(jspExecuteFunction(closeFunc, destination, 0, 0)); jsvUnLock(closeFunc); } } /* call source.close if available - probably not what node does but seems very sensible in this case. If you don't want it, set end:false */ if (source) { // TODO: This removes ALL listeners. Maybe we should just remove ours? jswrap_object_removeAllListeners_cstr(source, "close"); // execute the 'close' function JsVar *closeFunc = jspGetNamedField(source, "close", false); if (closeFunc) { jsvUnLock(jspExecuteFunction(closeFunc, source, 0, 0)); jsvUnLock(closeFunc); } } } jsvUnLock(source); jsvUnLock(destination); JsVar *idx = jsvObjectIteratorGetKey(it); jsvRemoveChild(arr,idx); jsvUnLock(idx); }