src/main.c
author Markus Bröker <mbroeker@largo.dyndns.tv>
Sat, 13 Dec 2008 15:56:39 +0100
changeset 0 06dd3b8d90ad
permissions -rw-r--r--
Virtual Reader committer: Markus Bröker <mbroeker@largo.homelinux.org>

/**
 *  $Id: main.c 53 2008-01-10 00:19:41Z mbroeker $
 * $URL: http://localhost/svn/c/VirtualReader/trunk/src/main.c $
 */

#include <sentence.h>
#include <keyboard.h>
#include <thread.h>
#include <audioplayer.h>
#include <interface.h>

#define STARTWRITER   0
#define      WRITER   1
#define      READER   2

#define        STEP   2         // jump back n-steps

void find_next (ThreadData * data)
{
    long tm = (long)audioplayer_gettime ();
    long position;
    int i, max;

    max = words (data->sentences[data->satz]);

    for (i = 0; i < max; i++) {
        if (data->timings[data->satz][i] > tm)
            break;
    }

    position = data->timings[data->satz][i];
    audioplayer_settime (position);
}

void find_prev (ThreadData * data)
{
    long tm = (long)audioplayer_gettime ();
    long position;
    int i, max;

    max = words (data->sentences[data->satz]);

    for (i = STEP; i < max; i++) {
        if (data->timings[data->satz][i] > tm)
            break;
    }

    position = data->timings[data->satz][i - STEP];
    audioplayer_settime (position);
}

int main (int argc, char **argv)
{
    char **sentences = NULL;    // to store an array of strings
    char *Text = NULL;          // to store the content of a textfile
    long **timings = NULL;      // to store the timings
    int i, count;               // sentence counter
    int verbose = 0;

    pthread_t p_thread, w_thread;

    ThreadData *data[3];        // independent thread data

    tts_options ttsopt = interface_get_cl_opts (argc, argv);
    ttshandles ttsh = interface_init (ttsopt);

    if ((Text = readbuffer (ttsopt.TextFile)) != NULL) {
        sentences = getstrings (Text, &count);
        free (Text);
    } else {
        printf ("ERROR: Textfile %s is corrupt.\n", ttsopt.TextFile);
        free (ttsopt.TextFile);
        free (ttsopt.AudioFile);
        free (ttsopt.Voice);
        free (ttsopt.Path);

        return EXIT_SUCCESS;
    }

    // Timinganalyse des Textes
    if ((timings = calloc ((size_t) count, sizeof (long *) + 1)) == NULL) {
        free (ttsopt.TextFile);
        free (ttsopt.AudioFile);
        free (ttsopt.Voice);
        free (ttsopt.Path);

        return EXIT_SUCCESS;
    }

    for (i = 0; i < count; i++) {
        timings[i] = interface_get_timing (ttsh, sentences[i]);
    }

    /*
     * Initialize Sound
     */
    if (audio_init ())
        fprintf (stderr, "AUDIO ERROR\n");

    for (i = 0; i < 3; i++) {
        data[i] = malloc (sizeof (ThreadData) + 1);
        if (data[i] == NULL)
            exit (0);
        data[i]->ttsopt = ttsopt;
        data[i]->ttsh = ttsh;
        data[i]->fname = ttsopt.TextFile;
        data[i]->sentences = sentences;
        data[i]->timings = timings;
    }

    /*
     * write sentences from 0-1 :)
     */
    data[STARTWRITER]->satz = 0;
    data[STARTWRITER]->items = 1;

    pthread_create (&w_thread, NULL, (void *)writewav, data[STARTWRITER]);
    pthread_join (w_thread, NULL);

    /*
     * write sentences from 1-count :)
     */
    data[WRITER]->satz = 1;
    data[WRITER]->items = count;
    pthread_create (&w_thread, NULL, (void *)writewav, data[WRITER]);

    data[READER]->satz = 0;
    data[READER]->items = count;
    pthread_create (&p_thread, NULL, (void *)readtext, data[READER]);

    while (data[READER]->satz < data[READER]->items) {
        switch (getSingleKey ()) {
        case 'i':
            // next word
            if (data[READER]->satz < data[READER]->items)
                find_next (data[READER]);
            else
                printf ("ERROR: Cannot seek anymore\n");
            break;

        case 'j':
            // previous sentence
            if (data[READER]->satz > 0) {
                data[READER]->satz--;
                p_thread_restart (p_thread, readtext, data[READER]);
            }
            break;

        case 'k':
            // previous word
            find_prev (data[READER]);
            break;

        case 'l':
            // next sentence
            if (data[READER]->satz < data[READER]->items) {
                data[READER]->satz++;
                p_thread_restart (p_thread, readtext, data[READER]);
            }
            break;

        case 'p':
            // print useful informations
            printf ("Current Position:  [%5d/%5d]ms = #%d\n",
                    audioplayer_gettime (), audioplayer_getwavelength (NULL), audioplayer_getposition ());
            break;

        case 'q':
            // quit
            pthread_cancel (w_thread);
            pthread_cancel (p_thread);
            data[READER]->satz = data[READER]->items;
            break;

        case 'r':
            // reset player
            pthread_cancel (p_thread);
            if (!pthread_join (p_thread, NULL))
                printf ("RESET\n");
            break;
        case 's':
            printf ("S[%d]: %s\n", data[READER]->satz, sentences[data[READER]->satz]);
            break;
        case 'v':
            verbose ^= 1;
            audioplayer_setverbose (verbose);
            break;

        default:
            /*
             * unknown command
             */
            break;
        }
    }

    if (!pthread_join (p_thread, NULL))
        printf ("The last thread exited\n");

    // cleanup memory
    for (i = 0; i < count; i++) {
        if (sentences[i] != NULL)
            free (sentences[i]);
        if (timings[i] != NULL)
            free (timings[i]);
    }

    if (sentences != NULL)
        free (sentences);

    if (timings != NULL)
        free (timings);

    for (i = 0; i < 3; i++)
        if (data[i] != NULL)
            free (data[i]);

    /*
     * Cleanup sound
     */
    audio_shutdown ();
    pthread_exit (NULL);
}