/* * This function is an /enumerator/ in the terminology of iteratees * [http://okmij.org/ftp/Streams.html]. * * Return value: 0 - success, -1 - error. */ static int process_file(enum Codec_T ct, const char *inpath, struct Buffer *inbuf, const struct Repr_Format *repr) { debug_print("process_file: \"%s\"", inpath); FILE *f = NULL; if (streq(inpath, "-")) { f = stdin; } else if ((f = fopen(inpath, "rb")) == NULL) { error(0, errno, "%s", inpath); return -1; } if (adjust_buffer(inbuf, f) < 0) { error(0, errno, "%s", inpath); return -1; } int retval = -1; size_t filepos = 0; struct Stream str = STREAM_INIT; void *z = NULL; for (;;) { const size_t orig_size = read_block(inbuf->wptr, inbuf->size, f, &str); str.type = ((str.size = orig_size) == 0) ? S_EOF : S_CHUNK; str.data = inbuf->wptr; if (str.type == S_EOF && str.errmsg != NULL) { error_at_line(0, 0, inpath, filepos, "%s", str.errmsg); break; } const IterV indic = run_codec(ct, &z, &str, repr); assert(indic == IE_DONE || indic == IE_CONT); filepos += orig_size - str.size; if (indic == IE_CONT && str.errmsg != NULL) { error_at_line(0, 0, inpath, filepos, "%s", str.errmsg); break; } assert(str.size == 0); if (indic == IE_DONE) { retval = 0; break; } } if (!streq(inpath, "-")) retval |= fclose(f); free(str.errmsg); free_codec(ct, z); /* XXX malloc/free for each input file is not good */ return retval; }
/* Codec thread function */ static void NORETURN_ATTR codec_thread(void) { struct queue_event ev; while (1) { cancel_cpu_boost(); queue_wait(&codec_queue, &ev); switch (ev.id) { case Q_CODEC_LOAD: LOGFQUEUE("codec < Q_CODEC_LOAD"); load_codec((const struct codec_load_info *)ev.data); break; case Q_CODEC_RUN: LOGFQUEUE("codec < Q_CODEC_RUN"); run_codec(); break; case Q_CODEC_PAUSE: LOGFQUEUE("codec < Q_CODEC_PAUSE"); break; case Q_CODEC_SEEK: LOGFQUEUE("codec < Q_CODEC_SEEK: %lu", (unsigned long)ev.data); seek_codec(ev.data); break; case Q_CODEC_UNLOAD: LOGFQUEUE("codec < Q_CODEC_UNLOAD"); unload_codec(); break; case Q_CODEC_DO_CALLBACK: LOGFQUEUE("codec < Q_CODEC_DO_CALLBACK"); do_callback((void (*)(void))ev.data); break; default: LOGFQUEUE("codec < default : %ld", ev.id); } } }
/* Handle Q_CODEC_SEEK */ static void seek_codec(unsigned long time) { if (codec_type == AFMT_UNKNOWN) { logf("no codec to seek"); codec_queue_ack(Q_CODEC_SEEK); codec_seek_complete_callback(); return; } /* Post it up one level */ queue_post(&codec_queue, Q_CODEC_SEEK, time); codec_queue_ack(Q_CODEC_SEEK); /* Have to run it again */ run_codec(); }