void RThread::handleOutput (char *buf, int buf_length) { RK_TRACE (RBACKEND); // TODO: output sometimes arrives in small chunks. Maybe it would be better to keep an internal buffer, and only append it to the output, when R_FlushConsole gets called? if (!buf_length) return; waitIfOutputPaused (); MUTEX_LOCK; if (current_output) { if (current_output->type != ROutput::Output) { flushOutput (); } } if (!current_output) { // not an else, might have been set to 0 in the above if current_output = new ROutput; current_output->type = ROutput::Output; current_output->output.reserve (MAX_BUF_LENGTH + 50); } current_output->output.append (QString::fromLocal8Bit (buf)); if ((out_buf_len += buf_length) > MAX_BUF_LENGTH) { RK_DO (qDebug ("Output buffer has %d characters. Forcing flush", out_buf_len), RBACKEND, DL_DEBUG); flushOutput (); } MUTEX_UNLOCK; }
/** * allocates a new buffer for the next write iterations */ void generateOutputBuffer( int amountOfChannels ) { flushOutput(); // free previous contents cachedBuffer = new AudioBuffer( amountOfChannels, outputBufferSize ); outputWriterIndex = 0; }
void AltSoftSerial::end(void) { DISABLE_INT_COMPARE_B(); DISABLE_INT_INPUT_CAPTURE(); flushInput(); flushOutput(); DISABLE_INT_COMPARE_A(); // TODO: restore timer to original settings? }
int Serial::write(str *data) { unsigned char c; for(int i=0; i<data->unit.size(); i++) { c = data->unit[i]; ssize_t result = ::write(fd, &c, 1); assert(result==1); } flushOutput(); flushInput(); }
/* * Process one request */ static void processRequest() { char *appName, *url; int flags; appName = mprStrdup(mpr, pathInfo); if (*appName == '/') { appName++; } if ((url = strchr(appName, '/')) != 0) { *url++ = '\0'; } if (strncmp(url, "web/", 4) == 0) { copyFile(url); flushOutput(output); return; } /* * Set default response headers */ setHeader(NULL, 0, "Content-Type", "text/html"); setHeader(NULL, 0, "Last-Modified", currentDate); setHeader(NULL, 0, "Cache-Control", "no-cache"); flags = 0; if (ext == 0) { flags |= EJS_WEB_FLAG_APP; } if ((web = ejsCreateWebRequest(mpr, control, NULL, scriptName, pathInfo, documentRoot, flags)) == 0) { error(NULL, 0, "Can't create web request"); return; } ejs = web->ejs; if (ejsRunWebRequest(web) < 0) { error(NULL, 0, "%s", web->error); return; } flushOutput(output); }
static int writeLine (void) { if (inputCarriageReturn) if (!writeByte('\r')) return 0; if (writeByte('\n')) if (flushOutput()) return 1; return 0; }
/* * Emit all headers */ static void emitHeaders() { MprHash *hp; int len; hp = mprGetFirstHash(responseHeaders); while (hp) { len = strlen(hp->key) + strlen(hp->data) + 4; if (mprGetBufSpace(headerOutput) < len) { flushOutput(headerOutput); } mprPutStringToBuf(headerOutput, hp->key); mprPutStringToBuf(headerOutput, ": "); mprPutStringToBuf(headerOutput, hp->data); mprPutStringToBuf(headerOutput, "\r\n"); hp = mprGetNextHash(responseHeaders, hp); } mprPutStringToBuf(headerOutput, "\r\n"); flushOutput(headerOutput); headersEmitted = 1; }
static int writeBytes (const char *bytes, size_t length) { while (length) { size_t count = OUTPUT_SIZE - outputLength; if (length < count) count = length; memcpy(&outputBuffer[outputLength], bytes, count); bytes += count; length -= count; if ((outputLength += count) == OUTPUT_SIZE) if (!flushOutput()) return 0; } return 1; }
void RThread::handleError (QString *call, int call_length) { RK_TRACE (RBACKEND); if (!call_length) return; waitIfOutputPaused (); MUTEX_LOCK; // Unfortunately, errors still get printed to the output. We try this crude method for the time being: flushOutput (); current_command->output_list.last ()->type = ROutput::Error; current_command->status |= RCommand::HasError; RK_DO (qDebug ("error '%s'", call[0].latin1 ()), RBACKEND, DL_DEBUG); MUTEX_UNLOCK; }
/* * Write data to the client. Will buffer and flush as required. will create headers if required. */ static int writeBlock(void *handle, cchar *buf, int size) { int len, rc; len = mprGetBufLength(output); if ((len + size) < EJS_CGI_MAX_BUF) { rc = mprPutBlockToBuf(output, buf, size); } else { flushOutput(output); if (size < EJS_CGI_MAX_BUF) { rc = mprPutBlockToBuf(output, buf, size); } else { rc = write(1, (char*) buf, size); } } return rc; }
/** * write the contents of the write buffer into * an output file, this will only write content * up until the point if was written to in case * the buffer wasn't full yet */ void writeBufferToFile( int aSampleRate, int aNumChannels, bool broadcastUpdate ) { // quick assertion if ( cachedBuffer == 0 ) return; // copy string contents for appending of filename std::string outputFile = std::string( outputDirectory.c_str()); int bufferSize = outputBufferSize; // recorded less than maximum available in buffer ? cut silence // by writing recording into temporary buffers if ( outputWriterIndex < bufferSize ) { bufferSize = outputWriterIndex; AudioBuffer* tempBuffer = new AudioBuffer( aNumChannels, bufferSize ); for ( int i = 0; i < bufferSize; ++i ) { for ( int c = 0; c < aNumChannels; ++c ) tempBuffer->getBufferForChannel( c )[ i ] = cachedBuffer->getBufferForChannel( c )[ i ]; } WaveWriter::bufferToFile( outputFile.append( SSTR( AudioEngine::recordingFileId )), tempBuffer, aSampleRate ); // free memory allocated by temporary buffer delete tempBuffer; } else { WaveWriter::bufferToFile( outputFile.append( SSTR( AudioEngine::recordingFileId )), cachedBuffer, aSampleRate ); } flushOutput(); // free memory // broadcast update, pass buffer identifier to identify last recording if ( broadcastUpdate ) Notifier::broadcast( Notifications::RECORDING_STATE_UPDATED, AudioEngine::recordingFileId ); }
void RThread::handleSubstackCall (QString *call, int call_length) { RK_TRACE (RBACKEND); RCommand *prev_command = current_command; REvalRequest *request = new REvalRequest; request->call = call; request->call_length = call_length; MUTEX_LOCK; flushOutput (); RCommandStack *reply_stack = new RCommandStack (); request->in_chain = reply_stack->startChain (reply_stack); MUTEX_UNLOCK; QCustomEvent *event = new QCustomEvent (R_EVAL_REQUEST_EVENT); event->setData (request); qApp->postEvent (RKGlobals::rInterface (), event); bool done = false; while (!done) { MUTEX_LOCK; processX11Events (); // while commands are in queue, don't wait while (reply_stack->isActive () && !locked) { RCommand *command = reply_stack->pop (); if (command) { // mutex will be unlocked inside doCommand (command); processX11Events (); } } if (reply_stack->isEmpty ()) { done = true; } MUTEX_UNLOCK; // if no commands are in queue, sleep for a while current_command = prev_command; msleep (10); } delete reply_stack; }
void RThread::handleStandardCallback (RCallbackArgs *args) { RK_TRACE (RBACKEND); MUTEX_LOCK; flushOutput (); MUTEX_UNLOCK; args->done = false; QCustomEvent *event = new QCustomEvent (R_CALLBACK_REQUEST_EVENT); event->setData (args); qApp->postEvent (RKGlobals::rInterface (), event); bool *done = &(args->done); while (!(*done)) { msleep (10); // callback not done yet? Sleep for a while if (!locked) { // what's with that lock? If the current command is cancelled, while we're in this loop, we must not lock the mutex and/or call anything in R. We may get long-jumped out of the loop before we get a chance to unlock MUTEX_LOCK; if (!locked) processX11Events (); MUTEX_UNLOCK; } } }
RInterface::RInterface () { RK_TRACE (RBACKEND); #ifndef DISABLE_RKWINDOWCATCHER window_catcher = new RKWindowCatcher (0); window_catcher->hide (); #endif // DISABLE_RKWINDOWCATCHER // If R_HOME is not set, most certainly the user called the binary without the wrapper script if (!getenv ("R_HOME")) { RK_DO (qDebug ("No R_HOME environment variable set. RKWard will quit in a moment. Always start rkward in the default way unless you know what you're doing."), RBACKEND, DL_ERROR); } RCommandStack::regular_stack = new RCommandStack (); running_command_canceled = 0; r_thread = new RThread (); watch = new RKwatch (); flush_timer = new QTimer (this); connect (flush_timer, SIGNAL (timeout ()), this, SLOT (flushOutput ())); flush_timer->start (FLUSH_INTERVAL); }
int RThread::initialize () { RK_TRACE (RBACKEND); // we create a fake RCommand to capture all the output/errors during startup current_command = new RCommand (i18n ("R Startup"), RCommand::App, i18n ("R Startup")); int argc = 2; char* argv[2] = { qstrdup ("--slave"), qstrdup ("--no-save") }; startR (argc, argv); for (--argc; argc >= 0; --argc) { delete argv[argc]; } connectCallbacks (); RKWardRError error; int status = 0; runCommandInternal ("library (\"rkward\")\n", &error); if (error) status |= LibLoadFail; int c; QString *paths = getCommandAsStringVector ("library.dynam (\"rkward\", \"rkward\")[[\"path\"]]\n", &c, &error); if ((error) || (c != 1)) { status |= LibLoadFail; } else { if (!registerFunctions (paths[0].local8Bit ())) status |= LibLoadFail; } delete [] paths; // find out about standard library locations QString *standardliblocs = getCommandAsStringVector (".libPaths ()\n", &c, &error); if (error) status |= OtherFail; for (int i = 0; i < c; ++i) { RKSettingsModuleRPackages::defaultliblocs.append (standardliblocs[i]); } delete [] standardliblocs; // apply user configurable run time options QStringList commands = RKSettingsModuleR::makeRRunTimeOptionCommands () + RKSettingsModuleRPackages::makeRRunTimeOptionCommands (); for (QStringList::const_iterator it = commands.begin (); it != commands.end (); ++it) { runCommandInternal ((*it).local8Bit (), &error); if (error) { status |= OtherFail; RK_DO (qDebug ("error in initialization call '%s'", (*it).latin1()), RBACKEND, DL_ERROR); } } // error sink and help browser runCommandInternal ("options (error=quote (.rk.do.error ()))\n", &error); if (error) status |= SinkFail; /* runCommandInternal (".rk.init.handlers ()\n", &error); if (error) status |= SinkFail; */ runCommandInternal ("options (htmlhelp=TRUE); options (browser=\"dcop " + kapp->dcopClient ()->appId () + " rkwardapp openHTMLHelp \")", &error); if (error) status |= OtherFail; // TODO: error-handling? MUTEX_LOCK; flushOutput (); MUTEX_UNLOCK; QCustomEvent *event = new QCustomEvent (RCOMMAND_OUT_EVENT); event->setData (current_command); qApp->postEvent (RKGlobals::rInterface (), event); return status; }
void Component::flushAll() { flushInput(); flushOutput(); }
void RThread::doCommand (RCommand *command) { RK_TRACE (RBACKEND); // step 1: notify GUI-thread that a new command is being tried and initialize QCustomEvent *event = new QCustomEvent (RCOMMAND_IN_EVENT); event->setData (command); qApp->postEvent (RKGlobals::rInterface (), event); current_command = command; // step 2: actual handling if (!((command->type () & RCommand::EmptyCommand) || (command->status & RCommand::Canceled))) { RKWardRError error; int ctype = command->type (); QCString localc = command->command ().local8Bit (); // needed so the string below does not go out of scope const char *ccommand = localc; RK_DO (qDebug ("running command: %s", ccommand), RBACKEND, DL_DEBUG); if (command->type () & RCommand::DirectToOutput) { runCommandInternal (QString ("sink (\"" + RKSettingsModuleGeneral::filesPath () + "/rk_out.html\", append=TRUE, split=TRUE)\n").local8Bit (), &error); } MUTEX_UNLOCK; if (ctype & RCommand::GetStringVector) { command->string_data = getCommandAsStringVector (ccommand, &(command->string_count), &error); } else if (ctype & RCommand::GetRealVector) { command->real_data = getCommandAsRealVector (ccommand, &(command->real_count), &error); } else if (ctype & RCommand::GetIntVector) { command->integer_data = getCommandAsIntVector (ccommand, &(command->integer_count), &error); } else { runCommandInternal (ccommand, &error, ctype & RCommand::User); } MUTEX_LOCK; #ifdef RKWARD_DEBUG int dl = DL_WARNING; // failed application commands are an issue worth reporting, failed user commands are not if (command->type () | RCommand::User) dl = DL_DEBUG; #endif if (error != NoError) { command->status |= RCommand::WasTried | RCommand::Failed; if (error == Incomplete) { command->status |= RCommand::ErrorIncomplete; RK_DO (qDebug ("Command failed (incomplete)"), RBACKEND, dl); } else if (error == SyntaxError) { command->status |= RCommand::ErrorSyntax; RK_DO (qDebug ("Command failed (syntax)"), RBACKEND, dl); } else if (command->status & RCommand::Canceled) { RK_DO (qDebug ("Command failed (interrupted)"), RBACKEND, dl); } else { command->status |= RCommand::ErrorOther; #ifdef RKWARD_DEBUG dl = DL_WARNING; // always interested in strange errors #endif RK_DO (qDebug ("Command failed (other)"), RBACKEND, dl); } RK_DO (qDebug ("failed command was: '%s'", command->command ().latin1 ()), RBACKEND, dl); } else { command->status |= RCommand::WasTried; } RKWardRError dummy; if (command->type () & RCommand::DirectToOutput) { runCommandInternal ("sink ()\n", &dummy); } if (error) { RK_DO (qDebug ("- error message was: '%s'", command->error ().latin1 ()), RBACKEND, dl); // runCommandInternal (".rk.init.handlers ()\n", &dummy); } RK_DO (qDebug ("done running command"), RBACKEND, DL_DEBUG); flushOutput (); } // step 3: cleanup // notify GUI-thread that command was finished event = new QCustomEvent (RCOMMAND_OUT_EVENT); event->setData (command); qApp->postEvent (RKGlobals::rInterface (), event); }
rtems_status_code rtems_termios_ioctl (void *arg) { rtems_libio_ioctl_args_t *args = arg; struct rtems_termios_tty *tty = args->iop->data1; struct ttywakeup *wakeup = (struct ttywakeup *)args->buffer; rtems_status_code sc; args->ioctl_return = 0; sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); if (sc != RTEMS_SUCCESSFUL) { return sc; } switch (args->command) { default: if (rtems_termios_linesw[tty->t_line].l_ioctl != NULL) { sc = rtems_termios_linesw[tty->t_line].l_ioctl(tty,args); } else { sc = RTEMS_INVALID_NUMBER; } break; case RTEMS_IO_GET_ATTRIBUTES: *(struct termios *)args->buffer = tty->termios; break; case RTEMS_IO_SET_ATTRIBUTES: tty->termios = *(struct termios *)args->buffer; /* check for and process change in flow control options */ termios_set_flowctrl(tty); if (tty->termios.c_lflag & ICANON) { tty->rawInBufSemaphoreOptions = RTEMS_WAIT; tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT; tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT; } else { tty->vtimeTicks = tty->termios.c_cc[VTIME] * rtems_clock_get_ticks_per_second() / 10; if (tty->termios.c_cc[VTIME]) { tty->rawInBufSemaphoreOptions = RTEMS_WAIT; tty->rawInBufSemaphoreTimeout = tty->vtimeTicks; if (tty->termios.c_cc[VMIN]) tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT; else tty->rawInBufSemaphoreFirstTimeout = tty->vtimeTicks; } else { if (tty->termios.c_cc[VMIN]) { tty->rawInBufSemaphoreOptions = RTEMS_WAIT; tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT; tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT; } else { tty->rawInBufSemaphoreOptions = RTEMS_NO_WAIT; } } } if (tty->handler.set_attributes) { sc = (*tty->handler.set_attributes)(tty, &tty->termios) ? RTEMS_SUCCESSFUL : RTEMS_IO_ERROR; } break; case RTEMS_IO_TCDRAIN: drainOutput (tty); break; case RTEMS_IO_TCFLUSH: switch ((intptr_t) args->buffer) { case TCIFLUSH: flushInput (tty); break; case TCOFLUSH: flushOutput (tty); break; case TCIOFLUSH: flushOutput (tty); flushInput (tty); break; default: sc = RTEMS_INVALID_NAME; break; } break; case RTEMS_IO_SNDWAKEUP: tty->tty_snd = *wakeup; break; case RTEMS_IO_RCVWAKEUP: tty->tty_rcv = *wakeup; break; /* * FIXME: add various ioctl code handlers */ #if 1 /* FIXME */ case TIOCSETD: /* * close old line discipline */ if (rtems_termios_linesw[tty->t_line].l_close != NULL) { sc = rtems_termios_linesw[tty->t_line].l_close(tty); } tty->t_line=*(int*)(args->buffer); tty->t_sc = NULL; /* ensure that no more valid data */ /* * open new line discipline */ if (rtems_termios_linesw[tty->t_line].l_open != NULL) { sc = rtems_termios_linesw[tty->t_line].l_open(tty); } break; case TIOCGETD: *(int*)(args->buffer)=tty->t_line; break; #endif case FIONREAD: { int rawnc = tty->rawInBuf.Tail - tty->rawInBuf.Head; if ( rawnc < 0 ) rawnc += tty->rawInBuf.Size; /* Half guess that this is the right operation */ *(int *)args->buffer = tty->ccount - tty->cindex + rawnc; } break; } rtems_semaphore_release (tty->osem); return sc; }