# HG changeset patch # User zither # Date 1180196473 25200 # Node ID edf2a1f1e58b40d2ad89b23e019de5c19cbce3f5 # Parent f1571687dca1a838c7813f35082028ce27c1e5c7 [svn] Implemented DAE feature (enabled by default) diff -r f1571687dca1 -r edf2a1f1e58b ChangeLog --- a/ChangeLog Sat May 26 08:49:57 2007 -0700 +++ b/ChangeLog Sat May 26 09:21:13 2007 -0700 @@ -1,3 +1,13 @@ +2007-05-26 15:49:57 +0000 Michael Farber <01mf02@gmail.com> + revision [2410] + - Fix a little spelling error (It's not TiMiDIty just like it's not + FireFox) + + + trunk/src/timidity/src/xmms-timidity.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + + 2007-05-25 09:50:20 +0000 Giacomo Lozito revision [2408] - amidi-plug: small changes diff -r f1571687dca1 -r edf2a1f1e58b src/cdaudio-ng/cdaudio-ng.c --- a/src/cdaudio-ng/cdaudio-ng.c Sat May 26 08:49:57 2007 -0700 +++ b/src/cdaudio-ng/cdaudio-ng.c Sat May 26 09:21:13 2007 -0700 @@ -1,7 +1,13 @@ /* todo: - - if any cdio_* returns an error, stop playing immediately + - move stuff into cdaudio-ng.h + - vis_pcm...?! + - limit cd read speed + - cddb + - dialogs + - remove //'s & todo's + - additional comments */ #include @@ -22,11 +28,13 @@ #include #include +#include #include -#include #include #define DEF_STRING_LEN 256 +#define CDROM_DIR "cdda://default" +#define CDDA_DAE_FRAMES 8 typedef struct { @@ -34,20 +42,32 @@ char performer[DEF_STRING_LEN]; char name[DEF_STRING_LEN]; char genre[DEF_STRING_LEN]; - int startlsn; - int endlsn; + lsn_t startlsn; + lsn_t endlsn; } trackinfo_t; +typedef struct { + + lsn_t startlsn; + lsn_t endlsn; + lsn_t currlsn; + lsn_t seektime; /* in miliseconds */ + InputPlayback *pplayback; + GThread *thread; + +} dae_params_t; + static int firsttrackno = -1; static int lasttrackno = -1; -static cdrom_drive_t *pcdrom_drive = NULL; +static CdIo_t *pcdio = NULL; static trackinfo_t *trackinfo = NULL; static char album_name[DEF_STRING_LEN]; -static gboolean use_dao = FALSE; +static gboolean use_dae = TRUE; static gboolean is_paused = FALSE; static int playing_track = -1; +static dae_params_t *pdae_params = NULL; static void cdaudio_init(); @@ -67,8 +87,10 @@ static void cdaudio_file_info_box(gchar *filename); static TitleInput *cdaudio_get_song_tuple(gchar *filename); +static void *dae_playing_thread_core(dae_params_t *pdae_params); static int calculate_track_length(int startlsn, int endlsn); static int find_trackno_from_filename(char *filename); +static void cleanup_on_error(); /* static int calculate_digit_sum(int n); @@ -79,7 +101,7 @@ static InputPlugin inputplugin = { NULL, NULL, - "Zither's CD Audio Plugin", + "CD Audio Plugin NG", cdaudio_init, cdaudio_about, cdaudio_configure, @@ -108,9 +130,14 @@ DECLARE_PLUGIN(cdaudio, NULL, NULL, cdaudio_iplist, NULL, NULL, NULL, NULL); + void cdaudio_init() { - cdio_init(); + if (!cdio_init()) { + fprintf(stderr, "cdaudio-ng: failed to initialize cdio subsystem\n"); + cleanup_on_error(); + return; + } } void cdaudio_about() @@ -123,49 +150,66 @@ gint cdaudio_is_our_file(gchar *filename) { - printf("is_our_file(\"%s\")\n", filename); if ((filename != NULL) && strlen(filename) > 4 && (!strcasecmp(filename + strlen(filename) - 4, ".cda"))) { - if (pcdrom_drive == NULL) { /* no CD information yet */ - printf("No CD information, rescanning\n"); - cdaudio_scan_dir("/mnt/cdrom"); // todo: :) + /* no CD information yet */ + if (pcdio == NULL) { + printf("cdaudio-ng: no cd information, scanning\n"); + cdaudio_scan_dir(CDROM_DIR); } - - if (cdio_get_media_changed(pcdrom_drive->p_cdio)) { - printf("CD changed, rescanning\n"); - cdaudio_scan_dir("/mnt/cdrom"); // todo: change the hardcoded path + + /* reload the cd information if the media has changed */ + if (cdio_get_media_changed(pcdio)) { + printf("cdaudio-ng: cd changed, rescanning\n"); + cdaudio_scan_dir(CDROM_DIR); } - - return 1; + + /* check if the requested track actually exists on the current audio cd */ + int trackno = find_trackno_from_filename(filename); + if (trackno < firsttrackno || trackno > lasttrackno) + return FALSE; + + return TRUE; } else - return 0; + return FALSE; } GList *cdaudio_scan_dir(gchar *dirname) { - printf("scan_dir(\"%s\")\n", dirname); - - if (strstr(dirname, "/mnt/cdrom") == NULL) // todo: replace this with a more standardised string + /* if the given dirname does not belong to us, we return NULL */ + if (strstr(dirname, CDROM_DIR) == NULL) return NULL; - + /* find the first available, audio capable, cd drive */ char **ppcd_drives = cdio_get_devices_with_cap(NULL, CDIO_FS_AUDIO, false); if (ppcd_drives != NULL) { /* we have at least one audio capable cd drive */ - pcdrom_drive = cdio_cddap_identify(*ppcd_drives, 1, NULL); + pcdio = cdio_open(*ppcd_drives, DRIVER_UNKNOWN); + if (pcdio == NULL) { + fprintf(stderr, "cdaudio-ng: failed to open cd\n"); + cleanup_on_error(); + return NULL; + } } else { - printf("Unable find or access a CD-ROM drive with an audio CD in it.\n"); + fprintf(stderr, "cdaudio-ng: unable find or access a cdda capable drive\n"); + cleanup_on_error(); return NULL; } cdio_free_device_list(ppcd_drives); /* get track information */ + cdrom_drive_t *pcdrom_drive = cdio_cddap_identify_cdio(pcdio, 1, NULL); // todo : check return / NULL firsttrackno = cdio_get_first_track_num(pcdrom_drive->p_cdio); lasttrackno = cdio_get_last_track_num(pcdrom_drive->p_cdio); + if (firsttrackno == CDIO_INVALID_TRACK || lasttrackno == CDIO_INVALID_TRACK) { + fprintf(stderr, "cdaudio-ng: failed to retrieve first/last track number"); + cleanup_on_error(); + return NULL; + } /* add track "file" names to the list */ GList *list = NULL; - if (trackinfo != NULL) + if (trackinfo != NULL) /* if a previously allocated track information exists, we free it */ free(trackinfo); trackinfo = (trackinfo_t *) malloc(sizeof(trackinfo_t) * (lasttrackno + 1)); int trackno; @@ -189,6 +233,13 @@ trackinfo[trackno].startlsn = cdio_get_track_lsn(pcdrom_drive->p_cdio, trackno); trackinfo[trackno].endlsn = cdio_get_track_last_lsn(pcdrom_drive->p_cdio, trackno); + + if (trackinfo[trackno].startlsn == CDIO_INVALID_LSN || trackinfo[trackno].endlsn == CDIO_INVALID_LSN) { + fprintf(stderr, "cdaudio-ng: failed to retrieve stard/end lsn for track %d\n", trackno); + g_list_free(list); + cleanup_on_error(); + return NULL; + } } return list; @@ -196,32 +247,60 @@ void cdaudio_play_file(InputPlayback *pinputplayback) { - printf("play_file(\"%s\")\n", pinputplayback->filename); - if (trackinfo == NULL) { - printf("No CD information, rescanning\n"); - cdaudio_scan_dir("/mnt/cdrom"); // todo: change the hardcoded path + printf("cdaudio-ng: no cd information, scanning\n"); + cdaudio_scan_dir(CDROM_DIR); } - if (cdio_get_media_changed(pcdrom_drive->p_cdio)) { - printf("CD changed, rescanning\n"); - cdaudio_scan_dir("/mnt/cdrom"); // todo: change the hardcoded path + if (cdio_get_media_changed(pcdio)) { + printf("cdaudio-ng: cd changed, rescanning\n"); + cdaudio_scan_dir(CDROM_DIR); } - + int trackno = find_trackno_from_filename(pinputplayback->filename); - if (trackno < firsttrackno || trackno > lasttrackno) + if (trackno < firsttrackno || trackno > lasttrackno) { + fprintf(stderr, "cdaudio-ng: trackno %d should be between %d and %d\n", trackno, firsttrackno, lasttrackno); + cleanup_on_error(); return; - - msf_t startmsf, endmsf; - cdio_lsn_to_msf(trackinfo[trackno].startlsn, &startmsf); - cdio_lsn_to_msf(trackinfo[trackno].endlsn, &endmsf); - cdio_audio_play_msf(pcdrom_drive->p_cdio, &startmsf, &endmsf); + } pinputplayback->playing = TRUE; playing_track = trackno; - + is_paused = FALSE; + + if (use_dae) { + if (pdae_params != NULL) { + fprintf(stderr, "cdaudio-ng: dae playback seems to be already started\n"); + return; + } + + if (pinputplayback->output->open_audio(FMT_S16_LE, 44100, 2) == 0) { + fprintf(stderr, "cdaudio-ng: failed open audio output\n"); + cleanup_on_error(); + return; + } + + pdae_params = (dae_params_t *) malloc(sizeof(dae_params_t)); + pdae_params->startlsn = trackinfo[trackno].startlsn; + pdae_params->endlsn = trackinfo[trackno].endlsn; + pdae_params->pplayback = pinputplayback; + pdae_params->seektime = -1; + pdae_params->currlsn = trackinfo[trackno].startlsn; + pdae_params->thread = g_thread_create((GThreadFunc) dae_playing_thread_core, pdae_params, TRUE, NULL); + } + else { + msf_t startmsf, endmsf; + cdio_lsn_to_msf(trackinfo[trackno].startlsn, &startmsf); + cdio_lsn_to_msf(trackinfo[trackno].endlsn, &endmsf); + if (cdio_audio_play_msf(pcdio, &startmsf, &endmsf) != DRIVER_OP_SUCCESS) { + fprintf(stderr, "cdaudio-ng: failed to play analog audio cd\n"); + cleanup_on_error(); + return; + } + } + char title[DEF_STRING_LEN]; - + if (strlen(trackinfo[trackno].performer) > 0) { strcpy(title, trackinfo[trackno].performer); strcat(title, " - "); @@ -229,44 +308,76 @@ else strcpy(title, ""); strcat(title, trackinfo[trackno].name); - + inputplugin.set_info(title, calculate_track_length(trackinfo[trackno].startlsn, trackinfo[trackno].endlsn), 128000, 44100, 2); } void cdaudio_stop(InputPlayback *pinputplayback) { - printf("stop(\"%s\")\n", pinputplayback->filename); - - cdio_audio_stop(pcdrom_drive->p_cdio); pinputplayback->playing = FALSE; playing_track = -1; + is_paused = FALSE; + + if (use_dae) { + if (pdae_params != NULL) { + g_thread_join(pdae_params->thread); + free(pdae_params); + pdae_params = NULL; + } + } + else { + if (cdio_audio_stop(pcdio) != DRIVER_OP_SUCCESS) { + fprintf(stderr, "cdaudio-ng: failed to stop analog cd\n"); + cleanup_on_error(); + return; + } + } } void cdaudio_pause(InputPlayback *pinputplayback, gshort paused) { if (!is_paused) { is_paused = TRUE; - cdio_audio_pause(pcdrom_drive->p_cdio); + if (!use_dae) + if (cdio_audio_pause(pcdio) != DRIVER_OP_SUCCESS) { + fprintf(stderr, "cdaudio-ng: failed to pause analog cd\n"); + cleanup_on_error(); + return; + } } else { is_paused = FALSE; - cdio_audio_resume(pcdrom_drive->p_cdio); + if (!use_dae) + if (cdio_audio_resume(pcdio) != DRIVER_OP_SUCCESS) { + fprintf(stderr, "cdaudio-ng: failed to resume analog cd\n"); + cleanup_on_error(); + return; + } } } void cdaudio_seek(InputPlayback *pinputplayback, gint time) { - printf("seek(%d)\n", time); if (playing_track == -1) return; - int lsnoffs = (time * 75); - int startlsn = trackinfo[playing_track].startlsn + lsnoffs; - - msf_t startmsf, endmsf; - cdio_lsn_to_msf(startlsn, &startmsf); - cdio_lsn_to_msf(trackinfo[playing_track].endlsn, &endmsf); - cdio_audio_play_msf(pcdrom_drive->p_cdio, &startmsf, &endmsf); + if (use_dae) { + if (pdae_params != NULL) { + pdae_params->seektime = time * 1000; + } + } + else { + int newstartlsn = trackinfo[playing_track].startlsn + time * 75; + msf_t startmsf, endmsf; + cdio_lsn_to_msf(newstartlsn, &startmsf); + cdio_lsn_to_msf(trackinfo[playing_track].endlsn, &endmsf); + + if (cdio_audio_play_msf(pcdio, &startmsf, &endmsf) != DRIVER_OP_SUCCESS) { + fprintf(stderr, "cdaudio-ng: failed to play analog cd\n"); + cleanup_on_error(); + return; + } + } } gint cdaudio_get_time(InputPlayback *pinputplayback) @@ -274,62 +385,96 @@ if (playing_track == -1) return -1; - cdio_subchannel_t subchannel; - cdio_audio_read_subchannel(pcdrom_drive->p_cdio, &subchannel); - int currentlsn = cdio_msf_to_lsn(&subchannel.abs_addr); + if (!use_dae) { + cdio_subchannel_t subchannel; + if (cdio_audio_read_subchannel(pcdio, &subchannel) != DRIVER_OP_SUCCESS) { + fprintf(stderr, "cdaudio-ng: failed to read analog cd subchannel\n"); + cleanup_on_error(); + return -1; + } + int currlsn = cdio_msf_to_lsn(&subchannel.abs_addr); - /* check to see if we have reached the end of the song */ - if (currentlsn == trackinfo[playing_track].endlsn) { - cdaudio_stop(pinputplayback); - return -1; + /* check to see if we have reached the end of the song */ + if (currlsn == trackinfo[playing_track].endlsn) { + cdaudio_stop(pinputplayback); + return -1; + } + + return calculate_track_length(trackinfo[playing_track].startlsn, currlsn); } - - int seconds = calculate_track_length(trackinfo[playing_track].startlsn, currentlsn); - // printf("%d\n", seconds); - return seconds; + else { + if (pdae_params != NULL) + return pinputplayback->output->output_time(); + else + return -1; + } } gint cdaudio_get_volume(gint *l, gint *r) { - // printf("get_volume()\n"); - - cdio_audio_volume_t volume;; - cdio_audio_set_volume(pcdrom_drive->p_cdio, &volume); - *l = volume.level[0]; - *r = volume.level[1]; - - return 0; + if (use_dae) { + *l = *r = 0; + return FALSE; + } + else { + cdio_audio_volume_t volume; + if (cdio_audio_get_volume(pcdio, &volume) != DRIVER_OP_SUCCESS) { + fprintf(stderr, "cdaudio-ng: failed to retrieve analog cd volume\n"); + cleanup_on_error(); + *l = *r = 0; + return FALSE; + } + *l = volume.level[0]; + *r = volume.level[1]; + + return TRUE; + } } gint cdaudio_set_volume(gint l, gint r) { - printf("set_volume(%d, %d)\n", l, r); - - cdio_audio_volume_t volume = {{l, r, 0, 0}}; - cdio_audio_set_volume(pcdrom_drive->p_cdio, &volume); - - return 0; + if (use_dae) { + return FALSE; + } + else { + cdio_audio_volume_t volume = {{l, r, 0, 0}}; + if (cdio_audio_set_volume(pcdio, &volume) != DRIVER_OP_SUCCESS) { + fprintf(stderr, "cdaudio-ng: failed to set analog cd volume\n"); + cleanup_on_error(); + return FALSE; + } + + return TRUE; + } } void cdaudio_cleanup() { - cdio_destroy(pcdrom_drive->p_cdio); + if (pcdio!= NULL) { + if (playing_track != -1 && !use_dae) + cdio_audio_stop(pcdio); + cdio_destroy(pcdio); + pcdio = NULL; + } + if (trackinfo != NULL) { + free(trackinfo); + trackinfo = NULL; + } + playing_track = -1; } void cdaudio_get_song_info(gchar *filename, gchar **title, gint *length) { - printf("get_song_info(\"%s\")\n", filename); + fprintf(stderr, "DEBUG: get_song_info(\"%s\")\n", filename); } void cdaudio_file_info_box(gchar *filename) { - + fprintf(stderr, "DEBUG: file_info_box(\"%s\")\n", filename); } TitleInput *cdaudio_get_song_tuple(gchar *filename) { - printf("get_song_tuple(\"%s\")\n", filename); - TitleInput *tuple = bmp_title_input_new(); /* return information about the requested track */ @@ -389,6 +534,78 @@ } */ +void *dae_playing_thread_core(dae_params_t *pdae_params) +{ + unsigned char *buffer = (unsigned char *) malloc(CDDA_DAE_FRAMES * CDIO_CD_FRAMESIZE_RAW); + + cdio_lseek(pcdio, pdae_params->startlsn * CDIO_CD_FRAMESIZE_RAW, SEEK_SET); + + gboolean output_paused = FALSE; + + while (pdae_params->pplayback->playing) { + /* handle pause status */ + if (is_paused) { + if (!output_paused) { + pdae_params->pplayback->output->pause(TRUE); + output_paused = TRUE; + } + usleep(1000); + continue; + } + else + if (output_paused) { + pdae_params->pplayback->output->pause(FALSE); + output_paused = FALSE; + } + + /* check if we have to seek */ + if (pdae_params->seektime != -1) { + int newlsn = pdae_params->startlsn + pdae_params->seektime * 75 / 1000; + cdio_lseek(pcdio, newlsn * CDIO_CD_FRAMESIZE_RAW, SEEK_SET); + pdae_params->pplayback->output->flush(pdae_params->seektime); + pdae_params->currlsn = newlsn; + pdae_params->seektime = -1; + } + + /* compute the actual number of sectors to read */ + int lsncount = CDDA_DAE_FRAMES <= (pdae_params->endlsn - pdae_params->currlsn + 1) ? CDDA_DAE_FRAMES : (pdae_params->endlsn - pdae_params->currlsn + 1); + /* check too see if we have reached the end of the song */ + if (lsncount <= 0) + break; + + if (cdio_read_audio_sectors(pcdio, buffer, pdae_params->currlsn, lsncount) != DRIVER_OP_SUCCESS) { + fprintf(stderr, "cdaudio-ng: failed to read audio sector\n"); + /* ok, that's it, we go on */ + } + + int remainingbytes = lsncount * CDIO_CD_FRAMESIZE_RAW; + unsigned char *bytebuff = buffer; + while (pdae_params->pplayback->playing && remainingbytes > 0 && pdae_params->seektime == -1) { + /* compute the actual number of bytes to play */ + int bytecount = CDIO_CD_FRAMESIZE_RAW <= remainingbytes ? CDIO_CD_FRAMESIZE_RAW : remainingbytes; + /* wait until the output buffer has enough room */ + while (pdae_params->pplayback->playing && pdae_params->pplayback->output->buffer_free() < bytecount && pdae_params->seektime == -1) + usleep(1000); + /* play the sound :) */ + if (pdae_params->pplayback->playing && pdae_params->seektime == -1) + produce_audio(pdae_params->pplayback->output->written_time(), FMT_S16_LE, 2, bytecount, bytebuff, &pdae_params->pplayback->playing); + remainingbytes -= bytecount; + bytebuff += bytecount; + } + pdae_params->currlsn += lsncount; + } + + pdae_params->pplayback->playing = FALSE; + playing_track = -1; + is_paused = FALSE; + + pdae_params->pplayback->output->close_audio(); + free(buffer); + + g_thread_exit(NULL); + return NULL; +} + int calculate_track_length(int startlsn, int endlsn) { return ((endlsn - startlsn + 1) * 1000) / 75; @@ -404,3 +621,16 @@ tracknostr[2] = '\0'; return strtol(tracknostr, NULL, 10); } + +void cleanup_on_error() +{ + if (pcdio != NULL) { + if (playing_track != -1 && !use_dae) + cdio_audio_stop(pcdio); + } + if (trackinfo != NULL) { + free(trackinfo); + trackinfo = NULL; + } + playing_track = -1; +}