Curses improvements. Can now show key/help and list of tracks.

This commit is contained in:
rocky
2005-03-12 16:45:44 +00:00
parent 76369d47fd
commit 6accca02b9

View File

@@ -1,5 +1,5 @@
/* /*
$Id: cdda-player.c,v 1.5 2005/03/12 06:02:36 rocky Exp $ $Id: cdda-player.c,v 1.6 2005/03/12 16:45:44 rocky Exp $
Copyright (C) 2005 Rocky Bernstein <rocky@panix.com> Copyright (C) 2005 Rocky Bernstein <rocky@panix.com>
@@ -80,6 +80,7 @@ track_t i_first_track;
track_t i_last_track; track_t i_last_track;
track_t i_first_audio_track; track_t i_first_audio_track;
track_t i_last_audio_track; track_t i_last_audio_track;
track_t i_last_display_track = CDIO_INVALID_TRACK;
track_t i_tracks; track_t i_tracks;
msf_t toc[CDIO_CDROM_LEADOUT_TRACK+1]; msf_t toc[CDIO_CDROM_LEADOUT_TRACK+1];
cdio_subchannel_t sub; /* subchannel last time read */ cdio_subchannel_t sub; /* subchannel last time read */
@@ -107,8 +108,9 @@ typedef enum {
STOP_PLAYING=3, STOP_PLAYING=3,
EJECT_CD=4, EJECT_CD=4,
CLOSE_CD=5, CLOSE_CD=5,
LIST_TRACKS=6, LIST_KEYS=6,
PS_LIST_TRACKS=7 LIST_TRACKS=7,
PS_LIST_TRACKS=8
} cd_operation_t; } cd_operation_t;
char *psz_device=NULL; char *psz_device=NULL;
@@ -120,6 +122,7 @@ typedef struct
{ {
char title[80]; char title[80];
char artist[80]; char artist[80];
char length[8];
char ext_data[80]; char ext_data[80];
bool b_cdtext; /* true if from CD-Text, false if from CDDB */ bool b_cdtext; /* true if from CD-Text, false if from CDDB */
} cd_track_info_rec_t; } cd_track_info_rec_t;
@@ -143,39 +146,50 @@ cddb_disc_t *p_cddb_disc = NULL;
int i_cddb_matches = 0; int i_cddb_matches = 0;
#endif #endif
const char key_bindings[] = #define MAX_KEY_STR 50
" right play / next track\n" const char key_bindings[][MAX_KEY_STR] = {
" left previous track\n" " right play / next track",
" up 10 sec forward\n" " left previous track",
" down 10 sec back\n" " up 10 sec forward",
" 1-9 jump to track 1-9\n" " down 10 sec back",
" 0 jump to track 10\n" " 1-9 jump to track 1-9",
" F1-F20 jump to track 11-30\n" " 0 jump to track 10",
"\n" " F1-F20 jump to track 11-30",
" e eject\n" " ",
" c close tray\n" " k, h, ? show this key help",
" p, space pause / resume\n" " e eject",
" s stop\n" " c close tray",
" q, ^C quit\n" " p, space pause / resume",
" x quit and continue playing\n" " s stop",
" a toggle auto-mode\n"; " q, ^C quit",
" x quit and continue playing",
" a toggle auto-mode",
};
const unsigned int i_key_bindings = sizeof(key_bindings) / MAX_KEY_STR;
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
/* tty stuff */ /* tty stuff */
#define LINE_STATUS 0 typedef enum {
#define LINE_CDINFO 1 LINE_STATUS = 0,
LINE_CDINFO = 1,
LINE_ARTIST = 3,
LINE_CDNAME = 4,
LINE_GENRE = 5,
LINE_YEAR = 6,
LINE_TRACK_PREV = 8,
LINE_TRACK_TITLE = 9,
LINE_TRACK_ARTIST = 10,
LINE_TRACK_NEXT = 11,
LINE_ACTION = 24,
LINE_LAST = 25
} track_line_t;
#define LINE_ARTIST 3
#define LINE_CDNAME 4
#define LINE_GENRE 5
#define LINE_YEAR 6
#define LINE_TRACK_A 7
#define LINE_TRACK_T 8
#define LINE_ACTION 10
#define LINE_LAST 11
static void static void
tty_raw() tty_raw()
@@ -219,36 +233,37 @@ select_wait(int sec)
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
static void static void
action(const char *txt) action(const char *psz_action)
{ {
if (!interactive) { if (!interactive) {
if (b_verbose) if (b_verbose)
fprintf(stderr,"action: %s\n",txt); fprintf(stderr,"action: %s\n", psz_action);
return; return;
} }
if (txt && strlen(txt)) if (psz_action && strlen(psz_action))
mvprintw(LINE_ACTION,0,"action : %-70s\n",txt); mvprintw(LINE_ACTION,0,"action : %s\n", psz_action);
else else
mvprintw(LINE_ACTION,0,"%-79s\n",""); mvprintw(LINE_ACTION,0,"");
clrtoeol();
refresh(); refresh();
} }
static void inline static void inline
xperror(const char *txt) xperror(const char *psz_msg)
{ {
char line[80]; char line[80];
if (!interactive) { if (!interactive) {
if (b_verbose) { if (b_verbose) {
fprintf(stderr,"error: "); fprintf(stderr, "error: ");
perror(txt); perror(psz_msg);
} }
return; return;
} }
if (b_verbose) { if (b_verbose) {
sprintf(line,"%s: %s",txt,strerror(errno)); sprintf(line,"%s: %s",psz_msg,strerror(errno));
mvprintw(LINE_ACTION, 0, "error : %-70s", line); mvprintw(LINE_ACTION, 0, "error : %-70s", line);
refresh(); refresh();
select_wait(3); select_wait(3);
@@ -257,10 +272,10 @@ xperror(const char *txt)
} }
static void static void
oops(const char *txt, int rc) oops(const char *psz_msg, int rc)
{ {
if(interactive) { if (interactive) {
mvprintw(LINE_LAST, 0, "%s, exiting...\n", txt); mvprintw(LINE_LAST, 0, "%s, exiting...\n", psz_msg);
refresh(); refresh();
} }
tty_restore(); tty_restore();
@@ -279,6 +294,7 @@ cd_stop(CdIo_t *p_cdio)
{ {
if (b_cd && p_cdio) { if (b_cd && p_cdio) {
action("stop..."); action("stop...");
i_last_audio_track = CDIO_INVALID_TRACK;
if (DRIVER_OP_SUCCESS != cdio_audio_stop(p_cdio)) if (DRIVER_OP_SUCCESS != cdio_audio_stop(p_cdio))
xperror("stop"); xperror("stop");
} }
@@ -331,7 +347,7 @@ read_subchannel(CdIo_t *p_cdio)
#define add_cddb_disc_info(format_str, field) \ #define add_cddb_disc_info(format_str, field) \
if (p_cddb_disc->field) \ if (p_cddb_disc->field) \
snprintf(field, sizeof(field)-1, format_str, p_cddb_disc->field); snprintf(field, sizeof(field), format_str, p_cddb_disc->field);
static void static void
read_toc(CdIo_t *p_cdio) read_toc(CdIo_t *p_cdio)
@@ -354,6 +370,7 @@ read_toc(CdIo_t *p_cdio)
xperror("read toc header"); xperror("read toc header");
b_cd = false; b_cd = false;
b_record = false; b_record = false;
i_last_display_track = CDIO_INVALID_TRACK;
} else { } else {
b_cd = true; b_cd = true;
data = 0; data = 0;
@@ -364,21 +381,32 @@ read_toc(CdIo_t *p_cdio)
add_cddb_disc_info("%s", artist); add_cddb_disc_info("%s", artist);
add_cddb_disc_info("%s", title); add_cddb_disc_info("%s", title);
add_cddb_disc_info("%s", genre); add_cddb_disc_info("%s", genre);
add_cddb_disc_info("%5d", year); add_cddb_disc_info("%4d", year);
} }
#else #else
b_db = false; b_db = false;
#endif #endif
for (i = i_first_track; i <= i_last_track+1; i++) { for (i = i_first_track; i <= i_last_track+1; i++) {
int s;
if ( !cdio_get_track_msf(p_cdio, i, &(toc[i])) ) if ( !cdio_get_track_msf(p_cdio, i, &(toc[i])) )
{ {
xperror("read toc entry"); xperror("read toc entry");
b_cd = false; b_cd = false;
return; return;
} }
if ( (TRACK_FORMAT_AUDIO != cdio_get_track_format(p_cdio, i)) && if ( TRACK_FORMAT_AUDIO == cdio_get_track_format(p_cdio, i) ) {
(i != i_last_track+1) ) {
if (i != i_first_track)
{
s = cdio_audio_get_msf_seconds(&toc[i])
- cdio_audio_get_msf_seconds(&toc[i-1]);
snprintf(cd_info[i].length, sizeof(cd_info[0].length),
"%02d:%02d",
s / CDIO_CD_SECS_PER_MIN, s % CDIO_CD_SECS_PER_MIN);
}
} else {
if ((i != i_last_track+1) ) {
data++; data++;
if (i == i_first_track) { if (i == i_first_track) {
if (i == i_last_track) if (i == i_last_track)
@@ -387,6 +415,7 @@ read_toc(CdIo_t *p_cdio)
i_first_audio_track++; i_first_audio_track++;
} }
} }
}
get_cddb_track_info(i); get_cddb_track_info(i);
} }
b_record = true; b_record = true;
@@ -394,6 +423,7 @@ read_toc(CdIo_t *p_cdio)
if (auto_mode && sub.audio_status != CDIO_MMC_READ_SUB_ST_PLAY) if (auto_mode && sub.audio_status != CDIO_MMC_READ_SUB_ST_PLAY)
play_track(1, CDIO_CDROM_LEADOUT_TRACK); play_track(1, CDIO_CDROM_LEADOUT_TRACK);
} }
action(NULL);
display_cdinfo(p_cdio, i_tracks, i_first_track); display_cdinfo(p_cdio, i_tracks, i_first_track);
} }
@@ -481,34 +511,59 @@ display_status()
} else if (sub.audio_status == CDIO_MMC_READ_SUB_ST_PAUSED || } else if (sub.audio_status == CDIO_MMC_READ_SUB_ST_PAUSED ||
sub.audio_status == CDIO_MMC_READ_SUB_ST_PLAY) { sub.audio_status == CDIO_MMC_READ_SUB_ST_PLAY) {
sprintf(line,"%2d - %02d:%02d (%02d:%02d abs) %-10s", sprintf(line,"track %2d - %02d:%02d of %s (%02d:%02d abs) %-10s",
sub.track, sub.track,
sub.rel_addr.msf.m, sub.rel_addr.msf.m,
sub.rel_addr.msf.s, sub.rel_addr.msf.s,
cd_info[sub.track].length,
sub.abs_addr.msf.m, sub.abs_addr.msf.m,
sub.abs_addr.msf.s, sub.abs_addr.msf.s,
mmc_audio_state2str(sub.audio_status)); mmc_audio_state2str(sub.audio_status));
} else { } else {
sprintf(line,"%s", mmc_audio_state2str(sub.audio_status)); sprintf(line,"%s", mmc_audio_state2str(sub.audio_status));
} }
mvprintw(LINE_STATUS,0,"status%s: %-70s",auto_mode ? "*" : " ", line); mvprintw(LINE_STATUS, 0, "status%s: %s",auto_mode ? "*" : " ", line);
clrtoeol();
if (b_db) { if (b_db && i_last_display_track != sub.track &&
if ((sub.audio_status == CDIO_MMC_READ_SUB_ST_PAUSED || (sub.audio_status == CDIO_MMC_READ_SUB_ST_PAUSED ||
sub.audio_status == CDIO_MMC_READ_SUB_ST_PLAY) && sub.audio_status == CDIO_MMC_READ_SUB_ST_PLAY) &&
b_cd) { b_cd) {
if (strlen(cd_info[sub.track].artist)) i_last_display_track = sub.track;
mvprintw(LINE_TRACK_A, 0,"track artist : %-70s", if (i_first_audio_track != sub.track &&
cd_info[sub.track].artist); strlen(cd_info[sub.track-1].title)) {
if (strlen(cd_info[sub.track].title)) mvprintw(LINE_TRACK_PREV, 0, "track %2d title : %s",
mvprintw(LINE_TRACK_T, 0,"track title : %-70s", sub.track-1, cd_info[sub.track-1].title);
cd_info[sub.track].title); clrtoeol();
} else {
mvprintw(LINE_TRACK_PREV, 0, "%s","");
clrtoeol();
} }
if (strlen(cd_info[sub.track].title)) {
mvprintw(LINE_TRACK_TITLE, 0, "track %2d title : %s",
sub.track, cd_info[sub.track].title);
clrtoeol();
} }
if (strlen(cd_info[sub.track].artist)) {
mvprintw(LINE_TRACK_ARTIST, 0, "track %2d artist : %s",
sub.track, cd_info[sub.track].artist);
clrtoeol();
}
if (i_last_audio_track != sub.track &&
strlen(cd_info[sub.track+1].title)) {
mvprintw(LINE_TRACK_NEXT, 0, "track %2d title : %s",
sub.track+1, cd_info[sub.track+1].title);
clrtoeol();
} else {
mvprintw(LINE_TRACK_NEXT, 0, "%s","");
clrtoeol();
}
clrtobot();
}
refresh(); refresh();
action(NULL);
} }
#define add_cddb_track_info(format_str, field) \ #define add_cddb_track_info(format_str, field) \
@@ -553,10 +608,10 @@ display_cdinfo(CdIo_t *p_cdio, track_t i_tracks, track_t i_first_track)
sprintf(line+len,", audio=%u-%u", (unsigned int) i_first_audio_track, sprintf(line+len,", audio=%u-%u", (unsigned int) i_first_audio_track,
(unsigned int) i_last_audio_track); (unsigned int) i_last_audio_track);
display_line(LINE_ARTIST, 0, "Artist : %-70s", artist); display_line(LINE_ARTIST, 0, "CD Artist : %-70s", artist);
display_line(LINE_CDNAME, 0, "CD : %-70s", title); display_line(LINE_CDNAME, 0, "CD Title : %-70s", title);
display_line(LINE_GENRE, 0, "Genre : %-40s", genre); display_line(LINE_GENRE, 0, "CD Genre : %-40s", genre);
display_line(LINE_YEAR, 0, "Year : %5s", year); display_line(LINE_YEAR, 0, "CD Year : %4s", year);
} }
mvprintw(LINE_CDINFO, 0, "CD info: %-70s", line); mvprintw(LINE_CDINFO, 0, "CD info: %-70s", line);
@@ -608,48 +663,68 @@ usage(char *prog)
} }
static void static void
keys() print_keys()
{ {
fprintf(stderr, key_bindings); unsigned int i;
for (i=0; i < i_key_bindings; i++)
fprintf(stderr, "%s\n", key_bindings[i]);
} }
static void static void
tracklist(void) list_keys()
{
unsigned int i;
for (i=0; i < i_key_bindings; i++) {
mvprintw(LINE_TRACK_PREV+i, 0, "%s", key_bindings[i]);
clrtoeol();
}
{
int key;
action("press any key to continue");
key = getch();
clrtobot();
action(NULL);
i_last_display_track = CDIO_INVALID_TRACK;
}
}
static void
list_tracks(void)
{ {
track_t i; track_t i;
int i_line=0;
int s; int s;
if (sub.audio_status == CDIO_MMC_READ_SUB_ST_PLAY) { if (b_record) {
printf("drive plays track %d (%02x:%02x)\n\n", i_line=LINE_TRACK_PREV;
sub.track, sub.rel_addr.msf.m, sub.rel_addr.msf.s);
}
printf("%2d %02x:%02x | ", (int) i_last_track,
toc[i_last_track+1].m,
toc[i_last_track+1].s);
if (b_record)
printf("%s / %s", artist, title);
printf("\n");
printf("-----------+--------------------------------------------------\n");
for (i = i_first_track; i <= i_last_track; i++) { for (i = i_first_track; i <= i_last_track; i++) {
char line[80];
s = cdio_audio_get_msf_seconds(&toc[i+1]) s = cdio_audio_get_msf_seconds(&toc[i+1])
- cdio_audio_get_msf_seconds(&toc[i]); - cdio_audio_get_msf_seconds(&toc[i]);
printf("%2d %02d:%02d %s ", i, sprintf(line, "%2d %02d:%02d %s ", i,
s / CDIO_CD_SECS_PER_MIN, s % CDIO_CD_SECS_PER_MIN, s / CDIO_CD_SECS_PER_MIN, s % CDIO_CD_SECS_PER_MIN,
(sub.audio_status == CDIO_MMC_READ_SUB_ST_PLAY && (sub.audio_status == CDIO_MMC_READ_SUB_ST_PLAY &&
sub.track == i) ? "*" : "|"); sub.track == i) ? "*" : "|");
if (b_record) { if (b_record) {
if ( !strlen(cd_info[i].title) && !strlen(cd_info[i].artist) )
printf("\n");
else {
if ( strlen(cd_info[i].title) ) if ( strlen(cd_info[i].title) )
printf("%s\n", cd_info[i].title); strcat(line, cd_info[i].title);
if ( strlen(cd_info[i].artist) > 0 ) { if ( strlen(cd_info[i].artist) > 0 ) {
printf(" %s %s\n", if (strlen(cd_info[i].title))
(sub.track == i) ? "*" : "|", cd_info[i].artist); strcat(line, " / ");
strcat(line, cd_info[i].artist);
} }
} }
} else mvprintw(i_line++, 0, line);
printf("\n"); clrtoeol();
}
{
int key;
action("press any key to continue");
switch (key = getch());
i_last_display_track = CDIO_INVALID_TRACK;
clrtobot();
action(NULL);
}
} }
} }
@@ -909,7 +984,7 @@ tracklist(void)
static void static void
ps_tracklist(void) ps_list_tracks(void)
{ {
int i,s,y,sy; int i,s,y,sy;
@@ -973,7 +1048,7 @@ ps_tracklist(void)
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
int c,key,nostop=0; int c, nostop=0;
char *h; char *h;
psz_program = strrchr(argv[0],'/'); psz_program = strrchr(argv[0],'/');
@@ -1035,7 +1110,7 @@ main(int argc, char *argv[])
todo = EJECT_CD; todo = EJECT_CD;
break; break;
case 'k': case 'k':
keys(); print_keys();
exit(1); exit(1);
case 'h': case 'h':
usage(psz_program); usage(psz_program);
@@ -1117,11 +1192,8 @@ main(int argc, char *argv[])
/* Should have been handled above. */ /* Should have been handled above. */
cd_eject(); cd_eject();
break; break;
case LIST_TRACKS:
tracklist();
break;
case PS_LIST_TRACKS: case PS_LIST_TRACKS:
ps_tracklist(); ps_list_tracks();
break; break;
case PLAY_TRACK: case PLAY_TRACK:
/* play just this one track */ /* play just this one track */
@@ -1145,6 +1217,7 @@ main(int argc, char *argv[])
} }
while ( !b_sig ) { while ( !b_sig ) {
int key;
if (!b_cd) read_toc(p_cdio); if (!b_cd) read_toc(p_cdio);
read_subchannel(p_cdio); read_subchannel(p_cdio);
display_status(); display_status();
@@ -1175,6 +1248,17 @@ main(int argc, char *argv[])
case 'c': case 'c':
cd_close(psz_device); cd_close(psz_device);
break; break;
case 'L':
case 'l':
list_tracks();
break;
case 'K':
case 'k':
case 'h':
case 'H':
case '?':
list_keys();
break;
case ' ': case ' ':
case 'P': case 'P':
case 'p': case 'p':