Logo Search packages:      
Sourcecode: tcd version File versions  Download package

tcd.c

/* This file is part of TCD 2.0.
   tcd.c - Main source file for curses interface.
   
   Copyright (C) 1997-98 Tim P. Gerla <timg@rrv.net>

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
                   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
                                   
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
                                               
   Tim P. Gerla
   RR 1, Box 40
   Climax, MN  56523
   timg@rrv.net
*/

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>

#include <SDL/SDL.h>

#include "cd-utils.h"
#include "cddb.h"
#include "tcd.h"
#include "tracked.h"
#include "ui.h"
#include "user-interface.h"

/* file global variables definitions */
static struct tcd_state state;

static void sighandler(int sig)
{
    if (sig == SIGTERM || sig == SIGINT) {
        state.quit_requested = 1;
    } else {
        ui_shutdown();
        printf("Signal %d caught, exiting.\n", sig);
        printf("Please mail any info (no core dumps please.) to %s.\n\n",
               PACKAGE_BUGREPORT);
        exit(EXIT_FAILURE);
    }
}

static void handle_pause(void)
{
    if (state.cdrom->status == CD_PLAYING) {
        SDL_CDPause(state.cdrom);
    } else if (state.cdrom->status == CD_PAUSED) {
        SDL_CDResume(state.cdrom);
    }
}

static void handle_play(void)
{
    if (state.cdrom->status == CD_PAUSED) {
        SDL_CDResume(state.cdrom);
    } else if (CD_INDRIVE(state.cdrom->status)) {
        if (state.play_method == REPEAT_TRK) {
            SDL_CDPlayTracks(state.cdrom, 0, 0, 1, 0);
        } else {
            SDL_CDPlayTracks(state.cdrom, 0, 0, 0, 0);
        }
    }
}

static void handle_next_track(void)
{
    if (!CD_INDRIVE(state.cdrom->status)) {
        return;
    }
    if (state.cdrom->cur_track == state.cdrom->numtracks - 1) {
        SDL_CDStop(state.cdrom);
    } else if (state.play_method == REPEAT_TRK) {
        SDL_CDPlayTracks(state.cdrom, state.cdrom->cur_track + 1, 0, 1, 0);
    } else {
        SDL_CDPlayTracks(state.cdrom, state.cdrom->cur_track + 1, 0, 0, 0);
    }
}

static void handle_prev_track(void)
{
    int prev_track;

    if (!CD_INDRIVE(state.cdrom->status)) {
        return;
    }
    if (state.cdrom->cur_track == 0) {
        prev_track = 0;
    } else if (state.cdrom->cur_frame / CD_FPS < 5) {
        prev_track = state.cdrom->cur_track - 1;
    } else {
        prev_track = state.cdrom->cur_track;
    }
    if (state.play_method == REPEAT_TRK) {
        SDL_CDPlayTracks(state.cdrom, prev_track, 0, 1, 0);
    } else {
        SDL_CDPlayTracks(state.cdrom, prev_track, 0, 0, 0);
    }
}

static void handle_goto(void)
{
    int track;
    if ((track = get_i_track()) != -1) {
        if (state.play_method == REPEAT_TRK) {
            SDL_CDPlayTracks(state.cdrom, track, 0, 1, 0);
        } else {
            SDL_CDPlayTracks(state.cdrom, track, 0, 0, 0);
        }
    }
}

static void handle_method(void)
{
    if (state.play_method == PLAY_METHOD_LAST) {
        state.play_method = PLAY_METHOD_FIRST;
    } else {
        state.play_method++;
    }
}

static void handle_repeat_track(void)
{
    state.play_method = REPEAT_TRK;
}

static void handle_eject(void)
{
    SDL_CDEject(state.cdrom);
    state.play_method = NORMAL;
}

static void handle_editor(void)
{
    if (CD_INDRIVE(state.cdrom->status)) {
        edit_trackdb(&state);
    }
}

static void handle_stop(void)
{
    if (CD_INDRIVE(state.cdrom->status)) {
        SDL_CDStop(state.cdrom);
    }
}

static void handle_skip_forward(void)
{
    const int frame = state.cdrom->cur_frame + 4 * CD_FPS;
    if (state.play_method == REPEAT_TRK) {
        SDL_CDPlayTracks(state.cdrom, state.cdrom->cur_track, frame, 1, 0);
    } else {
        SDL_CDPlayTracks(state.cdrom, state.cdrom->cur_track, frame, 0, 0);
    }
}

static void handle_skip_back(void)
{
    const int frame = state.cdrom->cur_frame - 4 * CD_FPS;
    if (state.play_method == REPEAT_TRK) {
        SDL_CDPlayTracks(state.cdrom, state.cdrom->cur_track, frame, 1, 0);
    } else {
        SDL_CDPlayTracks(state.cdrom, state.cdrom->cur_track, frame, 0, 0);
    }
}

static void init_SDL(int cdrom_num)
{
    int err = SDL_Init(SDL_INIT_CDROM);
    if (err != 0) {
        fprintf(stderr, "Error: %s.\n", strerror(err));
        exit(EXIT_FAILURE);
    }
    if (SDL_CDNumDrives() <= 0) {
        fprintf(stderr, "No CDROM devices available\n");
        exit(EXIT_FAILURE);
    }

    state.cdrom = SDL_CDOpen(cdrom_num);
    if (state.cdrom == NULL) {
        fprintf(stderr, "Could not open drive: %s\n", SDL_GetError());
        exit(EXIT_FAILURE);
    }
    (void) SDL_CDStatus(state.cdrom);
}

/**
 * If the CD has stopped but we're in loop play mode, resume the play.
 */
static void play_if_repeat(void)
{
    if (state.cdrom->status == CD_STOPPED) {
        if (state.play_method == REPEAT_CD) {
            SDL_CDPlayTracks(state.cdrom, 0, 0, 0, 0);
        } else if (state.play_method == REPEAT_TRK) {
            SDL_CDPlayTracks(state.cdrom, state.cdrom->cur_track, 0, 1, 0);
        }
        (void) SDL_CDStatus(state.cdrom);
    }
}

static void detect_disc_change(void)
{
    unsigned long discid = cddb_discid(state.cdrom);
    if (discid != state.current_discid) {
        if (state.cd_info.modified) {
            tcd_writediscinfo(&state.cd_info, state.cdrom);
        }
        if (CD_INDRIVE(state.cdrom->status)) {
            tcd_readdiscinfo(&state.cd_info, state.cdrom);
        } else {
            tcd_cleardiscinfo(&state.cd_info);
        }
        state.current_discid = discid;
    }
}

static void usage(FILE *out)
{
    fprintf(out, "%s %s\n\n", PACKAGE_NAME, PACKAGE_VERSION);
    fprintf(out, "usage: tcd [drivenum]\n");
    fprintf(out, "\twhere drivenum is the number of the cdrom drive -- useful if you\n");
    fprintf(out, "\thave more than one.\n");
}

int main(int argc, char **argv)
{
    int i, c;
    int drivenum = 0;

    for (i = SIGHUP; i <= SIGTERM; i++)
        (void) signal(i, sighandler);

    memset(&state, 0, sizeof(state));
    state.play_method = NORMAL;

    for (i = 1; i < argc; i++) {
      if (strcmp(argv[i], "--help") == 0) {
          usage(stdout);
          exit(EXIT_SUCCESS);
      } else if (strcmp(argv[i], "--version") == 0) {
          printf("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
          exit(EXIT_SUCCESS);
      } else {
          drivenum = atoi(argv[i]);
      }
    }
    init_SDL(drivenum);
    if (CD_INDRIVE(state.cdrom->status)) {
        tcd_readdiscinfo(&state.cd_info, state.cdrom);
        state.current_discid = cddb_discid(state.cdrom);
    } else {
        tcd_cleardiscinfo(&state.cd_info);
        state.current_discid = 0;
    }
    ui_init();
    tcd_ui_update(&state);

    while (!state.quit_requested) {
        (void) SDL_CDStatus(state.cdrom);      /* update CD status */
        detect_disc_change();
        play_if_repeat();
        tcd_ui_update(&state);
        switch (c = ui_readkey(5)) {
            case 'U': case 'u': handle_pause(); break;
            case 'P': case 'p': handle_play(); break;
            case 'Q': case 'q': state.quit_requested = 1; break;
            case '=': case '+': handle_next_track(); break;
            case '-': case '_': handle_prev_track(); break;
            case 'g': case 'G': handle_goto(); break;
            case 'c': case 'C': state.play_method = REPEAT_CD; break;
            case 'r': case 'R': handle_repeat_track(); break;
            case 'm': case 'M': handle_method(); break;
            case 'e': case 'E': handle_eject(); break;
            case 't': case 'T': handle_editor(); break;
            case 's': case 'S': handle_stop(); break;
            case ']': handle_skip_forward(); break;
            case '[': handle_skip_back(); break;
      }
    }
    ui_shutdown();
    if (state.cd_info.modified && CD_INDRIVE(state.cdrom->status)) {
        tcd_writediscinfo(&state.cd_info, state.cdrom);
    }
    SDL_CDClose(state.cdrom);
    return 0;
}

Generated by  Doxygen 1.6.0   Back to index