Mercurial > audlegacy-plugins
annotate src/cdaudio-ng/cdaudio-ng.c @ 1263:458d46e65a86
wav-sndfile: in is_our_file, ensure that filename is not NULL before passing it to sf_open
author | Giacomo Lozito <james@develia.org> |
---|---|
date | Fri, 13 Jul 2007 20:55:42 +0200 |
parents | bf57aa1dc503 |
children | ced2aa634901 |
rev | line source |
---|---|
1048 | 1 |
2 /* | |
3 todo: | |
1123 | 4 - vis_pcm...?! |
5 - limit cd read speed | |
6 - cddb | |
1189
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
7 - fileinfo dialog |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
8 - about dialog |
1123 | 9 - remove //'s & todo's |
10 - additional comments | |
1193 | 11 - stop playback when configure |
1048 | 12 */ |
13 | |
14 #include <string.h> | |
15 #include <stdlib.h> | |
16 #include <unistd.h> | |
17 #include <errno.h> | |
18 #include <libgen.h> | |
19 | |
20 #include <cdio/cdio.h> | |
21 #include <cdio/cdtext.h> | |
22 #include <cdio/track.h> | |
23 #include <cdio/cdda.h> | |
24 #include <cdio/audio.h> | |
25 #include <cdio/sector.h> | |
26 #include <cdio/cd_types.h> | |
27 | |
28 #include <glib.h> | |
29 | |
30 #include <audacious/i18n.h> | |
31 #include <audacious/configdb.h> | |
1123 | 32 #include <audacious/plugin.h> |
1048 | 33 #include <audacious/util.h> |
34 #include <audacious/output.h> | |
35 | |
1189
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
36 #include "cdaudio-ng.h" |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
37 #include "configure.h" |
1123 | 38 |
1048 | 39 |
40 static int firsttrackno = -1; | |
41 static int lasttrackno = -1; | |
1123 | 42 static CdIo_t *pcdio = NULL; |
1048 | 43 static trackinfo_t *trackinfo = NULL; |
44 static char album_name[DEF_STRING_LEN]; | |
1123 | 45 static gboolean use_dae = TRUE; |
1189
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
46 static gboolean use_cdtext = TRUE; |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
47 static gboolean use_cddb = TRUE; |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
48 static char device[DEF_STRING_LEN]; |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
49 static int limitspeed = 1; |
1048 | 50 static gboolean is_paused = FALSE; |
51 static int playing_track = -1; | |
1123 | 52 static dae_params_t *pdae_params = NULL; |
1193 | 53 static gboolean debug = FALSE; |
1048 | 54 |
55 static void cdaudio_init(); | |
56 static void cdaudio_about(); | |
57 static void cdaudio_configure(); | |
58 static gint cdaudio_is_our_file(gchar *filename); | |
59 static GList *cdaudio_scan_dir(gchar *dirname); | |
60 static void cdaudio_play_file(InputPlayback *pinputplayback); | |
61 static void cdaudio_stop(InputPlayback *pinputplayback); | |
62 static void cdaudio_pause(InputPlayback *pinputplayback, gshort paused); | |
63 static void cdaudio_seek(InputPlayback *pinputplayback, gint time); | |
64 static gint cdaudio_get_time(InputPlayback *pinputplayback); | |
65 static gint cdaudio_get_volume(gint *l, gint *r); | |
66 static gint cdaudio_set_volume(gint l, gint r); | |
67 static void cdaudio_cleanup(); | |
68 static void cdaudio_get_song_info(gchar *filename, gchar **title, gint *length); | |
69 static void cdaudio_file_info_box(gchar *filename); | |
70 static TitleInput *cdaudio_get_song_tuple(gchar *filename); | |
71 | |
1123 | 72 static void *dae_playing_thread_core(dae_params_t *pdae_params); |
1048 | 73 static int calculate_track_length(int startlsn, int endlsn); |
74 static int find_trackno_from_filename(char *filename); | |
1123 | 75 static void cleanup_on_error(); |
1048 | 76 |
1189
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
77 |
1048 | 78 /* |
79 static int calculate_digit_sum(int n); | |
80 static unsigned long calculate_cddb_discid(); | |
81 */ | |
82 | |
83 | |
84 static InputPlugin inputplugin = { | |
85 NULL, | |
86 NULL, | |
1123 | 87 "CD Audio Plugin NG", |
1048 | 88 cdaudio_init, |
89 cdaudio_about, | |
90 cdaudio_configure, | |
91 cdaudio_is_our_file, | |
92 cdaudio_scan_dir, | |
93 cdaudio_play_file, | |
94 cdaudio_stop, | |
95 cdaudio_pause, | |
96 cdaudio_seek, | |
97 NULL, | |
98 cdaudio_get_time, | |
99 cdaudio_get_volume, | |
100 cdaudio_set_volume, | |
101 cdaudio_cleanup, | |
102 NULL, | |
103 NULL, | |
104 NULL, | |
105 NULL, | |
106 cdaudio_get_song_info, | |
107 cdaudio_file_info_box, | |
108 NULL, | |
109 cdaudio_get_song_tuple | |
110 }; | |
111 | |
1098
334afe46961c
[svn] - cdaudio-ng (aka Zither's CD Audio Plugin): convert to plugin API v2
nenolod
parents:
1048
diff
changeset
|
112 InputPlugin *cdaudio_iplist[] = { &inputplugin, NULL }; |
1048 | 113 |
1098
334afe46961c
[svn] - cdaudio-ng (aka Zither's CD Audio Plugin): convert to plugin API v2
nenolod
parents:
1048
diff
changeset
|
114 DECLARE_PLUGIN(cdaudio, NULL, NULL, cdaudio_iplist, NULL, NULL, NULL, NULL); |
1048 | 115 |
1123 | 116 |
1048 | 117 void cdaudio_init() |
118 { | |
1193 | 119 if (debug) |
120 printf("cdaudio-ng: cdaudio_init()\n"); | |
1125 | 121 |
1123 | 122 if (!cdio_init()) { |
123 fprintf(stderr, "cdaudio-ng: failed to initialize cdio subsystem\n"); | |
124 cleanup_on_error(); | |
125 return; | |
126 } | |
1189
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
127 |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
128 ConfigDb *db = bmp_cfg_db_open(); |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
129 gchar *string = NULL; |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
130 |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
131 if (!bmp_cfg_db_get_bool(db, "CDDA", "use_dae", &use_dae)) |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
132 use_dae = TRUE; |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
133 if (!bmp_cfg_db_get_int(db, "CDDA", "limitspeed", &limitspeed)) |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
134 limitspeed = 1; |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
135 if (!bmp_cfg_db_get_bool(db, "CDDA", "use_cdtext", &use_cdtext)) |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
136 use_cdtext = TRUE; |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
137 if (!bmp_cfg_db_get_bool(db, "CDDA", "use_cddb", &use_cddb)) |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
138 use_cddb = TRUE; |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
139 if (!bmp_cfg_db_get_string(db, "CDDA", "device", &string)) |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
140 strcpy(device, ""); |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
141 else |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
142 strcpy(device, string); |
1193 | 143 if (!bmp_cfg_db_get_bool(db, "CDDA", "debug", &debug)) |
144 debug = FALSE; | |
1189
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
145 |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
146 bmp_cfg_db_close(db); |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
147 |
1193 | 148 if (debug) |
149 printf("cdaudio-ng: configuration: use_dae = %d, limitspeed = %d, use_cdtext = %d, use_cddb = %d, device = \"%s\", debug = %d\n", use_dae, limitspeed, use_cdtext, use_cddb, device, debug); | |
1189
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
150 |
1193 | 151 configure_set_variables(&use_dae, &limitspeed, &use_cdtext, &use_cddb, device, &debug); |
1189
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
152 configure_create_gui(); |
1048 | 153 } |
154 | |
155 void cdaudio_about() | |
156 { | |
1193 | 157 if (debug) |
158 printf("cdaudio-ng: cdaudio_about()\n"); | |
1048 | 159 } |
160 | |
161 void cdaudio_configure() | |
162 { | |
1193 | 163 if (debug) |
164 printf("cdaudio-ng: cdaudio_configure()\n"); | |
1189
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
165 |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
166 configure_show_gui(); |
1048 | 167 } |
168 | |
169 gint cdaudio_is_our_file(gchar *filename) | |
170 { | |
1193 | 171 if (debug) |
172 printf("cdaudio-ng: cdaudio_is_our_file(\"%s\")\n", filename); | |
1125 | 173 |
1048 | 174 if ((filename != NULL) && strlen(filename) > 4 && (!strcasecmp(filename + strlen(filename) - 4, ".cda"))) { |
1123 | 175 /* no CD information yet */ |
176 if (pcdio == NULL) { | |
1193 | 177 if (debug) |
178 printf("cdaudio-ng: no cd information, scanning\n"); | |
1125 | 179 cdaudio_scan_dir(CDDA_DEFAULT); |
1048 | 180 } |
1123 | 181 |
182 /* reload the cd information if the media has changed */ | |
183 if (cdio_get_media_changed(pcdio)) { | |
1193 | 184 if (debug) |
185 printf("cdaudio-ng: cd changed, rescanning\n"); | |
1125 | 186 cdaudio_scan_dir(CDDA_DEFAULT); |
1048 | 187 } |
1123 | 188 |
189 /* check if the requested track actually exists on the current audio cd */ | |
190 int trackno = find_trackno_from_filename(filename); | |
1125 | 191 if (trackno < firsttrackno || trackno > lasttrackno) { |
1193 | 192 if (debug) |
193 printf("cdaudio-ng: \"%s\" is not our file\n", filename); | |
1123 | 194 return FALSE; |
1125 | 195 } |
1123 | 196 |
1193 | 197 if (debug) |
198 printf("cdaudio-ng: \"%s\" is our file\n", filename); | |
1123 | 199 return TRUE; |
1048 | 200 } |
1125 | 201 else { |
1193 | 202 if (debug) |
203 printf("cdaudio-ng: \"%s\" is not our file\n", filename); | |
1123 | 204 return FALSE; |
1125 | 205 } |
1048 | 206 } |
207 | |
208 GList *cdaudio_scan_dir(gchar *dirname) | |
209 { | |
1193 | 210 if (debug) |
211 printf("cdaudio-ng: cdaudio_scan_dir(\"%s\")\n", dirname); | |
1125 | 212 |
1123 | 213 /* if the given dirname does not belong to us, we return NULL */ |
1125 | 214 if (strstr(dirname, CDDA_DEFAULT) == NULL) { |
1193 | 215 if (debug) |
216 printf("cdaudio-ng: \"%s\" directory does not belong to us\n", dirname); | |
1048 | 217 return NULL; |
1125 | 218 } |
1123 | 219 |
1189
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
220 /* find an available, audio capable, cd drive */ |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
221 if (device != NULL && strlen(device) > 0) |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
222 pcdio = cdio_open(device, DRIVER_UNKNOWN); |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
223 else { |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
224 char **ppcd_drives = cdio_get_devices_with_cap(NULL, CDIO_FS_AUDIO, false); |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
225 if (ppcd_drives != NULL) { /* we have at least one audio capable cd drive */ |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
226 pcdio = cdio_open(*ppcd_drives, DRIVER_UNKNOWN); |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
227 if (pcdio == NULL) { |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
228 fprintf(stderr, "cdaudio-ng: failed to open cd\n"); |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
229 cleanup_on_error(); |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
230 return NULL; |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
231 } |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
232 } |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
233 else { |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
234 fprintf(stderr, "cdaudio-ng: unable find or access a cdda capable drive\n"); |
1123 | 235 cleanup_on_error(); |
236 return NULL; | |
237 } | |
1193 | 238 if (debug) |
239 printf("cdaudio-ng: found cd drive \"%s\" with audio capable media\n", *ppcd_drives); | |
1189
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
240 cdio_free_device_list(ppcd_drives); |
1048 | 241 } |
242 | |
1193 | 243 /* limit read speed */ |
244 if (limitspeed > 0) { | |
245 if (debug) | |
246 printf("cdaudio-ng: setting drive speed limit to %dx\n", limitspeed); | |
1194 | 247 if (cdio_set_speed(pcdio, limitspeed) != DRIVER_OP_SUCCESS) |
1193 | 248 fprintf(stderr, "cdaudio-ng: failed to set drive speed to %dx\n", limitspeed); |
249 } | |
1048 | 250 /* get track information */ |
1194 | 251 cdrom_drive_t *pcdrom_drive = cdio_cddap_identify_cdio(pcdio, 1, NULL); // todo : check return / NULL |
1048 | 252 firsttrackno = cdio_get_first_track_num(pcdrom_drive->p_cdio); |
253 lasttrackno = cdio_get_last_track_num(pcdrom_drive->p_cdio); | |
1123 | 254 if (firsttrackno == CDIO_INVALID_TRACK || lasttrackno == CDIO_INVALID_TRACK) { |
255 fprintf(stderr, "cdaudio-ng: failed to retrieve first/last track number"); | |
256 cleanup_on_error(); | |
257 return NULL; | |
258 } | |
1193 | 259 if (debug) |
260 printf("cdaudio-ng: first track is %d and last track is %d\n", firsttrackno, lasttrackno); | |
1048 | 261 |
262 /* add track "file" names to the list */ | |
263 GList *list = NULL; | |
1123 | 264 if (trackinfo != NULL) /* if a previously allocated track information exists, we free it */ |
1048 | 265 free(trackinfo); |
266 trackinfo = (trackinfo_t *) malloc(sizeof(trackinfo_t) * (lasttrackno + 1)); | |
267 int trackno; | |
268 for (trackno = firsttrackno; trackno <= lasttrackno; trackno++) { | |
269 list = g_list_append(list, g_strdup_printf("track%02u.cda", trackno)); | |
1189
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
270 cdtext_t *pcdtext = NULL; |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
271 if (use_cdtext) |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
272 pcdtext = cdio_get_cdtext(pcdrom_drive->p_cdio, trackno); |
1048 | 273 |
274 if (pcdtext != NULL) { | |
275 strcpy(trackinfo[trackno].performer, pcdtext->field[CDTEXT_PERFORMER] != NULL ? pcdtext->field[CDTEXT_PERFORMER] : ""); | |
276 strcpy(trackinfo[trackno].name, pcdtext->field[CDTEXT_TITLE] != NULL ? pcdtext->field[CDTEXT_TITLE] : ""); | |
277 strcpy(trackinfo[trackno].genre, pcdtext->field[CDTEXT_GENRE] != NULL ? pcdtext->field[CDTEXT_GENRE] : ""); | |
278 } | |
279 else { | |
280 strcpy(trackinfo[trackno].performer, ""); | |
281 strcpy(trackinfo[trackno].name, ""); | |
282 strcpy(trackinfo[trackno].genre, ""); | |
283 } | |
284 | |
1189
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
285 // todo: implement cddb |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
286 |
1048 | 287 if (strlen(trackinfo[trackno].name) == 0) |
288 sprintf(trackinfo[trackno].name, "CD Audio Track %02u", trackno); | |
289 | |
290 trackinfo[trackno].startlsn = cdio_get_track_lsn(pcdrom_drive->p_cdio, trackno); | |
291 trackinfo[trackno].endlsn = cdio_get_track_last_lsn(pcdrom_drive->p_cdio, trackno); | |
1123 | 292 |
293 if (trackinfo[trackno].startlsn == CDIO_INVALID_LSN || trackinfo[trackno].endlsn == CDIO_INVALID_LSN) { | |
294 fprintf(stderr, "cdaudio-ng: failed to retrieve stard/end lsn for track %d\n", trackno); | |
295 g_list_free(list); | |
296 cleanup_on_error(); | |
297 return NULL; | |
298 } | |
1125 | 299 |
1193 | 300 if (debug) |
301 printf("cdaudio-ng: track %d has : performer = \"%s\", name = \"%s\", genre = \"%s\", startlsn = %d, endlsn = %d\n", | |
302 trackno, trackinfo[trackno].performer, trackinfo[trackno].name, trackinfo[trackno].genre, trackinfo[trackno].startlsn, trackinfo | |
303 [trackno].endlsn); | |
1048 | 304 } |
305 | |
306 return list; | |
307 } | |
308 | |
309 void cdaudio_play_file(InputPlayback *pinputplayback) | |
1125 | 310 { |
1193 | 311 if (debug) |
312 printf("cdaudio-ng: cdaudio_play_file(\"%s\")\n", pinputplayback->filename); | |
1125 | 313 |
1048 | 314 if (trackinfo == NULL) { |
1193 | 315 if (debug) |
316 printf("cdaudio-ng: no cd information, scanning\n"); | |
1125 | 317 cdaudio_scan_dir(CDDA_DEFAULT); |
1048 | 318 } |
319 | |
1123 | 320 if (cdio_get_media_changed(pcdio)) { |
1193 | 321 if (debug) |
322 printf("cdaudio-ng: cd changed, rescanning\n"); | |
1125 | 323 cdaudio_scan_dir(CDDA_DEFAULT); |
1048 | 324 } |
1123 | 325 |
1048 | 326 int trackno = find_trackno_from_filename(pinputplayback->filename); |
1123 | 327 if (trackno < firsttrackno || trackno > lasttrackno) { |
1125 | 328 fprintf(stderr, "cdaudio-ng: trackno %d is out of range [%d..%d]\n", trackno, firsttrackno, lasttrackno); |
1123 | 329 cleanup_on_error(); |
1048 | 330 return; |
1123 | 331 } |
1048 | 332 |
333 pinputplayback->playing = TRUE; | |
334 playing_track = trackno; | |
1123 | 335 is_paused = FALSE; |
336 | |
337 if (use_dae) { | |
1193 | 338 if (debug) |
339 printf("cdaudio-ng: using digital audio extraction\n"); | |
1125 | 340 |
1123 | 341 if (pdae_params != NULL) { |
342 fprintf(stderr, "cdaudio-ng: dae playback seems to be already started\n"); | |
343 return; | |
344 } | |
345 | |
346 if (pinputplayback->output->open_audio(FMT_S16_LE, 44100, 2) == 0) { | |
347 fprintf(stderr, "cdaudio-ng: failed open audio output\n"); | |
348 cleanup_on_error(); | |
349 return; | |
350 } | |
351 | |
1193 | 352 if (debug) |
353 printf("cdaudio-ng: starting dae thread...\n"); | |
1123 | 354 pdae_params = (dae_params_t *) malloc(sizeof(dae_params_t)); |
355 pdae_params->startlsn = trackinfo[trackno].startlsn; | |
356 pdae_params->endlsn = trackinfo[trackno].endlsn; | |
357 pdae_params->pplayback = pinputplayback; | |
358 pdae_params->seektime = -1; | |
359 pdae_params->currlsn = trackinfo[trackno].startlsn; | |
360 pdae_params->thread = g_thread_create((GThreadFunc) dae_playing_thread_core, pdae_params, TRUE, NULL); | |
361 } | |
362 else { | |
1193 | 363 if (debug) |
364 printf("cdaudio-ng: not using digital audio extraction\n"); | |
1125 | 365 |
1123 | 366 msf_t startmsf, endmsf; |
367 cdio_lsn_to_msf(trackinfo[trackno].startlsn, &startmsf); | |
368 cdio_lsn_to_msf(trackinfo[trackno].endlsn, &endmsf); | |
369 if (cdio_audio_play_msf(pcdio, &startmsf, &endmsf) != DRIVER_OP_SUCCESS) { | |
370 fprintf(stderr, "cdaudio-ng: failed to play analog audio cd\n"); | |
371 cleanup_on_error(); | |
372 return; | |
373 } | |
374 } | |
375 | |
1048 | 376 char title[DEF_STRING_LEN]; |
1123 | 377 |
1048 | 378 if (strlen(trackinfo[trackno].performer) > 0) { |
379 strcpy(title, trackinfo[trackno].performer); | |
380 strcat(title, " - "); | |
381 } | |
382 else | |
383 strcpy(title, ""); | |
384 strcat(title, trackinfo[trackno].name); | |
1123 | 385 |
1048 | 386 inputplugin.set_info(title, calculate_track_length(trackinfo[trackno].startlsn, trackinfo[trackno].endlsn), 128000, 44100, 2); |
387 } | |
388 | |
389 void cdaudio_stop(InputPlayback *pinputplayback) | |
1125 | 390 { |
1193 | 391 if (debug) |
392 printf("cdaudio-ng: cdaudio_stop(\"%s\")\n", pinputplayback->filename); | |
1125 | 393 |
1048 | 394 pinputplayback->playing = FALSE; |
395 playing_track = -1; | |
1123 | 396 is_paused = FALSE; |
397 | |
398 if (use_dae) { | |
399 if (pdae_params != NULL) { | |
400 g_thread_join(pdae_params->thread); | |
401 free(pdae_params); | |
402 pdae_params = NULL; | |
403 } | |
404 } | |
405 else { | |
406 if (cdio_audio_stop(pcdio) != DRIVER_OP_SUCCESS) { | |
407 fprintf(stderr, "cdaudio-ng: failed to stop analog cd\n"); | |
408 cleanup_on_error(); | |
409 return; | |
410 } | |
411 } | |
1048 | 412 } |
413 | |
414 void cdaudio_pause(InputPlayback *pinputplayback, gshort paused) | |
415 { | |
1193 | 416 if (debug) |
417 printf("cdaudio-ng: cdaudio_pause(\"%s\", %d)\n", pinputplayback->filename, paused); | |
1125 | 418 |
1048 | 419 if (!is_paused) { |
420 is_paused = TRUE; | |
1123 | 421 if (!use_dae) |
422 if (cdio_audio_pause(pcdio) != DRIVER_OP_SUCCESS) { | |
423 fprintf(stderr, "cdaudio-ng: failed to pause analog cd\n"); | |
424 cleanup_on_error(); | |
425 return; | |
426 } | |
1048 | 427 } |
428 else { | |
429 is_paused = FALSE; | |
1123 | 430 if (!use_dae) |
431 if (cdio_audio_resume(pcdio) != DRIVER_OP_SUCCESS) { | |
432 fprintf(stderr, "cdaudio-ng: failed to resume analog cd\n"); | |
433 cleanup_on_error(); | |
434 return; | |
435 } | |
1048 | 436 } |
437 } | |
438 | |
439 void cdaudio_seek(InputPlayback *pinputplayback, gint time) | |
440 { | |
1193 | 441 if (debug) |
442 printf("cdaudio-ng: cdaudio_seek(\"%s\", %d)\n", pinputplayback->filename, time); | |
1125 | 443 |
1048 | 444 if (playing_track == -1) |
445 return; | |
446 | |
1123 | 447 if (use_dae) { |
448 if (pdae_params != NULL) { | |
449 pdae_params->seektime = time * 1000; | |
450 } | |
451 } | |
452 else { | |
453 int newstartlsn = trackinfo[playing_track].startlsn + time * 75; | |
454 msf_t startmsf, endmsf; | |
455 cdio_lsn_to_msf(newstartlsn, &startmsf); | |
456 cdio_lsn_to_msf(trackinfo[playing_track].endlsn, &endmsf); | |
457 | |
458 if (cdio_audio_play_msf(pcdio, &startmsf, &endmsf) != DRIVER_OP_SUCCESS) { | |
459 fprintf(stderr, "cdaudio-ng: failed to play analog cd\n"); | |
460 cleanup_on_error(); | |
461 return; | |
462 } | |
463 } | |
1048 | 464 } |
465 | |
466 gint cdaudio_get_time(InputPlayback *pinputplayback) | |
467 { | |
1125 | 468 //printf("cdaudio-ng: cdaudio_get_time(\"%s\")\n", pinputplayback->filename); // annoying! |
469 | |
1048 | 470 if (playing_track == -1) |
471 return -1; | |
472 | |
1123 | 473 if (!use_dae) { |
474 cdio_subchannel_t subchannel; | |
475 if (cdio_audio_read_subchannel(pcdio, &subchannel) != DRIVER_OP_SUCCESS) { | |
476 fprintf(stderr, "cdaudio-ng: failed to read analog cd subchannel\n"); | |
477 cleanup_on_error(); | |
478 return -1; | |
479 } | |
480 int currlsn = cdio_msf_to_lsn(&subchannel.abs_addr); | |
1048 | 481 |
1123 | 482 /* check to see if we have reached the end of the song */ |
483 if (currlsn == trackinfo[playing_track].endlsn) { | |
484 cdaudio_stop(pinputplayback); | |
485 return -1; | |
486 } | |
487 | |
488 return calculate_track_length(trackinfo[playing_track].startlsn, currlsn); | |
1048 | 489 } |
1123 | 490 else { |
491 if (pdae_params != NULL) | |
492 return pinputplayback->output->output_time(); | |
493 else | |
494 return -1; | |
495 } | |
1048 | 496 } |
497 | |
498 gint cdaudio_get_volume(gint *l, gint *r) | |
499 { | |
1125 | 500 //printf("cdaudio-ng: cdaudio_get_volume()\n"); // annoying! |
501 | |
1123 | 502 if (use_dae) { |
503 *l = *r = 0; | |
504 return FALSE; | |
505 } | |
506 else { | |
507 cdio_audio_volume_t volume; | |
508 if (cdio_audio_get_volume(pcdio, &volume) != DRIVER_OP_SUCCESS) { | |
509 fprintf(stderr, "cdaudio-ng: failed to retrieve analog cd volume\n"); | |
510 cleanup_on_error(); | |
511 *l = *r = 0; | |
512 return FALSE; | |
513 } | |
514 *l = volume.level[0]; | |
515 *r = volume.level[1]; | |
516 | |
517 return TRUE; | |
518 } | |
1048 | 519 } |
520 | |
521 gint cdaudio_set_volume(gint l, gint r) | |
522 { | |
1193 | 523 if (debug) |
524 printf("cdaudio-ng: cdaudio_set_volume(%d, %d)\n", l, r); | |
1125 | 525 |
1123 | 526 if (use_dae) { |
527 return FALSE; | |
528 } | |
529 else { | |
530 cdio_audio_volume_t volume = {{l, r, 0, 0}}; | |
531 if (cdio_audio_set_volume(pcdio, &volume) != DRIVER_OP_SUCCESS) { | |
532 fprintf(stderr, "cdaudio-ng: failed to set analog cd volume\n"); | |
533 cleanup_on_error(); | |
534 return FALSE; | |
535 } | |
536 | |
537 return TRUE; | |
538 } | |
1048 | 539 } |
540 | |
541 void cdaudio_cleanup() | |
542 { | |
1193 | 543 if (debug) |
544 printf("cdaudio-ng: cdaudio_cleanup()\n"); | |
1125 | 545 |
1123 | 546 if (pcdio!= NULL) { |
547 if (playing_track != -1 && !use_dae) | |
548 cdio_audio_stop(pcdio); | |
549 cdio_destroy(pcdio); | |
550 pcdio = NULL; | |
551 } | |
552 if (trackinfo != NULL) { | |
553 free(trackinfo); | |
554 trackinfo = NULL; | |
555 } | |
556 playing_track = -1; | |
1189
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
557 |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
558 // todo: destroy the gui |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
559 |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
560 ConfigDb *db = bmp_cfg_db_open(); |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
561 bmp_cfg_db_set_bool(db, "CDDA", "use_dae", use_dae); |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
562 bmp_cfg_db_set_int(db, "CDDA", "limitspeed", limitspeed); |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
563 bmp_cfg_db_set_bool(db, "CDDA", "use_cdtext", use_cdtext); |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
564 bmp_cfg_db_set_bool(db, "CDDA", "use_cddb", use_cddb); |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
565 bmp_cfg_db_set_string(db, "CDDA", "device", device); |
1193 | 566 bmp_cfg_db_set_bool(db, "CDDA", "debug", debug); |
1189
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
567 bmp_cfg_db_close(db); |
1048 | 568 } |
569 | |
570 void cdaudio_get_song_info(gchar *filename, gchar **title, gint *length) | |
571 { | |
1193 | 572 if (debug) |
573 printf("cdaudio-ng: cdaudio_get_song_info(\"%s\")\n", filename); | |
1125 | 574 |
575 int trackno = find_trackno_from_filename(filename); | |
576 char *thetitle = (char *) malloc(DEF_STRING_LEN); | |
577 | |
578 if (strlen(trackinfo[trackno].performer) > 0) { | |
579 strcpy(thetitle, trackinfo[trackno].performer); | |
580 strcat(thetitle, " - "); | |
581 } | |
582 else | |
583 strcpy(thetitle, ""); | |
584 strcat(thetitle, trackinfo[trackno].name); | |
585 | |
586 *title = thetitle; | |
587 *length = calculate_track_length(trackinfo[trackno].startlsn, trackinfo[trackno].endlsn); | |
1048 | 588 } |
589 | |
590 void cdaudio_file_info_box(gchar *filename) | |
591 { | |
1193 | 592 if (debug) |
593 printf("cdaudio-ng: cdaudio_file_info_box(\"%s\")\n", filename); | |
1048 | 594 } |
595 | |
596 TitleInput *cdaudio_get_song_tuple(gchar *filename) | |
597 { | |
1193 | 598 if (debug) |
599 printf("cdaudio-ng: cdaudio_get_song_tuple(\"%s\")\n", filename); | |
1125 | 600 |
1048 | 601 TitleInput *tuple = bmp_title_input_new(); |
602 | |
603 /* return information about the requested track */ | |
604 int trackno = find_trackno_from_filename(filename); | |
605 if (trackno < firsttrackno || trackno > lasttrackno) | |
606 return NULL; | |
607 | |
608 tuple->performer = strlen(trackinfo[trackno].performer) > 0 ? g_strdup(trackinfo[trackno].performer) : NULL; | |
609 tuple->album_name = strlen(album_name) > 0 ? g_strdup(album_name) : NULL; | |
610 tuple->track_name = strlen(trackinfo[trackno].name) > 0 ? g_strdup(trackinfo[trackno].name) : NULL; | |
611 tuple->track_number = trackno; | |
612 tuple->file_name = g_strdup(basename(filename)); | |
613 tuple->file_path = g_strdup(basename(filename)); | |
614 tuple->file_ext = g_strdup("cda"); | |
615 tuple->length = calculate_track_length(trackinfo[trackno].startlsn, trackinfo[trackno].endlsn); | |
616 tuple->genre = strlen(trackinfo[trackno].genre) > 0 ? g_strdup(trackinfo[trackno].genre) : NULL; | |
617 //tuple->year = 0; todo: set the year | |
618 | |
619 return tuple; | |
620 } | |
621 | |
622 | |
623 /* auxiliar functions */ | |
624 | |
625 /* | |
626 static int calculate_digit_sum(int n) | |
627 { | |
628 int ret = 0; | |
629 | |
630 while (1) { | |
631 ret += n % 10; | |
632 n = n / 10; | |
633 if (n == 0) | |
634 return ret; | |
635 } | |
636 } | |
637 */ | |
638 | |
639 /* | |
640 static unsigned long calculate_cddb_discid() | |
641 { | |
642 int trackno, t, n = 0; | |
643 msf_t startmsf; | |
644 msf_t msf; | |
645 | |
646 for (trackno = firsttrackno; trackno <= lasttrackno; trackno++) { | |
647 cdio_get_track_msf(pcdrom_drive->p_cdio, trackno, &msf); | |
648 n += calculate_digit_sum(cdio_audio_get_msf_seconds(&msf)); | |
649 } | |
650 | |
651 cdio_get_track_msf(pcdrom_drive->p_cdio, 1, &startmsf); | |
652 cdio_get_track_msf(pcdrom_drive->p_cdio, CDIO_CDROM_LEADOUT_TRACK, &msf); | |
653 | |
654 t = cdio_audio_get_msf_seconds(&msf) - cdio_audio_get_msf_seconds(&startmsf); | |
655 | |
656 return ((n % 0xFF) << 24 | t << 8 | (lasttrackno - firsttrackno + 1)); | |
657 } | |
658 */ | |
659 | |
1123 | 660 void *dae_playing_thread_core(dae_params_t *pdae_params) |
661 { | |
662 unsigned char *buffer = (unsigned char *) malloc(CDDA_DAE_FRAMES * CDIO_CD_FRAMESIZE_RAW); | |
663 | |
1193 | 664 if (debug) |
665 printf("cdaudio-ng: dae thread started\n"); | |
1123 | 666 cdio_lseek(pcdio, pdae_params->startlsn * CDIO_CD_FRAMESIZE_RAW, SEEK_SET); |
667 | |
668 gboolean output_paused = FALSE; | |
1125 | 669 |
1123 | 670 while (pdae_params->pplayback->playing) { |
671 /* handle pause status */ | |
672 if (is_paused) { | |
673 if (!output_paused) { | |
1193 | 674 if (debug) |
675 printf("cdaudio-ng: playback was not paused, pausing\n"); | |
1123 | 676 pdae_params->pplayback->output->pause(TRUE); |
677 output_paused = TRUE; | |
678 } | |
679 usleep(1000); | |
680 continue; | |
681 } | |
1125 | 682 else { |
1123 | 683 if (output_paused) { |
1193 | 684 if (debug) |
685 printf("cdaudio-ng: playback was paused, resuming\n"); | |
1123 | 686 pdae_params->pplayback->output->pause(FALSE); |
687 output_paused = FALSE; | |
688 } | |
1125 | 689 } |
1123 | 690 |
691 /* check if we have to seek */ | |
692 if (pdae_params->seektime != -1) { | |
1193 | 693 if (debug) |
694 printf("cdaudio-ng: requested seek to %d ms\n", pdae_params->seektime); | |
1123 | 695 int newlsn = pdae_params->startlsn + pdae_params->seektime * 75 / 1000; |
696 cdio_lseek(pcdio, newlsn * CDIO_CD_FRAMESIZE_RAW, SEEK_SET); | |
697 pdae_params->pplayback->output->flush(pdae_params->seektime); | |
698 pdae_params->currlsn = newlsn; | |
699 pdae_params->seektime = -1; | |
700 } | |
701 | |
702 /* compute the actual number of sectors to read */ | |
703 int lsncount = CDDA_DAE_FRAMES <= (pdae_params->endlsn - pdae_params->currlsn + 1) ? CDDA_DAE_FRAMES : (pdae_params->endlsn - pdae_params->currlsn + 1); | |
704 /* check too see if we have reached the end of the song */ | |
705 if (lsncount <= 0) | |
706 break; | |
707 | |
708 if (cdio_read_audio_sectors(pcdio, buffer, pdae_params->currlsn, lsncount) != DRIVER_OP_SUCCESS) { | |
709 fprintf(stderr, "cdaudio-ng: failed to read audio sector\n"); | |
710 /* ok, that's it, we go on */ | |
711 } | |
712 | |
713 int remainingbytes = lsncount * CDIO_CD_FRAMESIZE_RAW; | |
714 unsigned char *bytebuff = buffer; | |
715 while (pdae_params->pplayback->playing && remainingbytes > 0 && pdae_params->seektime == -1) { | |
716 /* compute the actual number of bytes to play */ | |
717 int bytecount = CDIO_CD_FRAMESIZE_RAW <= remainingbytes ? CDIO_CD_FRAMESIZE_RAW : remainingbytes; | |
718 /* wait until the output buffer has enough room */ | |
719 while (pdae_params->pplayback->playing && pdae_params->pplayback->output->buffer_free() < bytecount && pdae_params->seektime == -1) | |
720 usleep(1000); | |
721 /* play the sound :) */ | |
722 if (pdae_params->pplayback->playing && pdae_params->seektime == -1) | |
723 produce_audio(pdae_params->pplayback->output->written_time(), FMT_S16_LE, 2, bytecount, bytebuff, &pdae_params->pplayback->playing); | |
724 remainingbytes -= bytecount; | |
725 bytebuff += bytecount; | |
726 } | |
727 pdae_params->currlsn += lsncount; | |
728 } | |
1193 | 729 if (debug) |
730 printf("cdaudio-ng: dae thread ended\n"); | |
1123 | 731 |
732 pdae_params->pplayback->playing = FALSE; | |
733 playing_track = -1; | |
734 is_paused = FALSE; | |
735 | |
736 pdae_params->pplayback->output->close_audio(); | |
737 free(buffer); | |
738 | |
739 g_thread_exit(NULL); | |
740 return NULL; | |
741 } | |
742 | |
1048 | 743 int calculate_track_length(int startlsn, int endlsn) |
744 { | |
745 return ((endlsn - startlsn + 1) * 1000) / 75; | |
746 } | |
747 | |
748 int find_trackno_from_filename(char *filename) | |
749 { | |
750 if ((filename == NULL) || strlen(filename) <= 6) | |
751 return -1; | |
752 | |
753 char tracknostr[3]; | |
754 strncpy(tracknostr, filename + strlen(filename) - 6, 2); | |
755 tracknostr[2] = '\0'; | |
756 return strtol(tracknostr, NULL, 10); | |
757 } | |
1123 | 758 |
759 void cleanup_on_error() | |
760 { | |
761 if (pcdio != NULL) { | |
762 if (playing_track != -1 && !use_dae) | |
763 cdio_audio_stop(pcdio); | |
764 } | |
765 if (trackinfo != NULL) { | |
766 free(trackinfo); | |
767 trackinfo = NULL; | |
768 } | |
769 playing_track = -1; | |
770 } | |
1193 | 771 |