Mercurial > audlegacy-plugins
annotate src/cdaudio-ng/cdaudio-ng.c @ 1282:ced2aa634901
Added cddb support
author | zither@litestep.network |
---|---|
date | Tue, 17 Jul 2007 03:12:32 +0300 |
parents | bf57aa1dc503 |
children | 2a7c9e0b9c0f |
rev | line source |
---|---|
1048 | 1 |
2 /* | |
3 todo: | |
1123 | 4 - vis_pcm...?! |
1189
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
5 - fileinfo dialog |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
6 - about dialog |
1123 | 7 - remove //'s & todo's |
8 - additional comments | |
1193 | 9 - stop playback when configure |
1282 | 10 - configuration for cddb (server, port) |
1048 | 11 */ |
12 | |
13 #include <string.h> | |
14 #include <stdlib.h> | |
15 #include <unistd.h> | |
16 #include <errno.h> | |
17 #include <libgen.h> | |
18 | |
19 #include <cdio/cdio.h> | |
20 #include <cdio/cdtext.h> | |
21 #include <cdio/track.h> | |
22 #include <cdio/cdda.h> | |
23 #include <cdio/audio.h> | |
24 #include <cdio/sector.h> | |
25 #include <cdio/cd_types.h> | |
1282 | 26 #include <cddb/cddb.h> |
1048 | 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; |
1282 | 44 |
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 |
77 static int calculate_digit_sum(int n); | |
78 static unsigned long calculate_cddb_discid(); | |
1282 | 79 |
1048 | 80 |
81 | |
82 static InputPlugin inputplugin = { | |
83 NULL, | |
84 NULL, | |
1123 | 85 "CD Audio Plugin NG", |
1048 | 86 cdaudio_init, |
87 cdaudio_about, | |
88 cdaudio_configure, | |
89 cdaudio_is_our_file, | |
90 cdaudio_scan_dir, | |
91 cdaudio_play_file, | |
92 cdaudio_stop, | |
93 cdaudio_pause, | |
94 cdaudio_seek, | |
95 NULL, | |
96 cdaudio_get_time, | |
97 cdaudio_get_volume, | |
98 cdaudio_set_volume, | |
99 cdaudio_cleanup, | |
100 NULL, | |
101 NULL, | |
102 NULL, | |
103 NULL, | |
104 cdaudio_get_song_info, | |
105 cdaudio_file_info_box, | |
106 NULL, | |
107 cdaudio_get_song_tuple | |
108 }; | |
109 | |
1098
334afe46961c
[svn] - cdaudio-ng (aka Zither's CD Audio Plugin): convert to plugin API v2
nenolod
parents:
1048
diff
changeset
|
110 InputPlugin *cdaudio_iplist[] = { &inputplugin, NULL }; |
1048 | 111 |
1098
334afe46961c
[svn] - cdaudio-ng (aka Zither's CD Audio Plugin): convert to plugin API v2
nenolod
parents:
1048
diff
changeset
|
112 DECLARE_PLUGIN(cdaudio, NULL, NULL, cdaudio_iplist, NULL, NULL, NULL, NULL); |
1048 | 113 |
1123 | 114 |
1048 | 115 void cdaudio_init() |
116 { | |
1193 | 117 if (debug) |
118 printf("cdaudio-ng: cdaudio_init()\n"); | |
1125 | 119 |
1123 | 120 if (!cdio_init()) { |
121 fprintf(stderr, "cdaudio-ng: failed to initialize cdio subsystem\n"); | |
122 cleanup_on_error(); | |
123 return; | |
124 } | |
1282 | 125 |
126 libcddb_init(); | |
127 | |
1189
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 */ |
1282 | 221 if (device != NULL && strlen(device) > 0) { |
1189
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
222 pcdio = cdio_open(device, DRIVER_UNKNOWN); |
1282 | 223 if (pcdio == NULL) { |
224 fprintf(stderr, "cdaudio-ng: failed to open cd device \"%s\"\n", device); | |
225 return NULL; | |
226 } | |
227 } | |
1189
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
228 else { |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
229 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
|
230 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
|
231 pcdio = cdio_open(*ppcd_drives, DRIVER_UNKNOWN); |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
232 if (pcdio == NULL) { |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
233 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
|
234 cleanup_on_error(); |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
235 return NULL; |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
236 } |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
237 } |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
238 else { |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
239 fprintf(stderr, "cdaudio-ng: unable find or access a cdda capable drive\n"); |
1123 | 240 cleanup_on_error(); |
241 return NULL; | |
242 } | |
1193 | 243 if (debug) |
244 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
|
245 cdio_free_device_list(ppcd_drives); |
1048 | 246 } |
247 | |
1193 | 248 /* limit read speed */ |
1282 | 249 if (limitspeed > 0 && !use_dae) { |
1193 | 250 if (debug) |
251 printf("cdaudio-ng: setting drive speed limit to %dx\n", limitspeed); | |
1194 | 252 if (cdio_set_speed(pcdio, limitspeed) != DRIVER_OP_SUCCESS) |
1193 | 253 fprintf(stderr, "cdaudio-ng: failed to set drive speed to %dx\n", limitspeed); |
254 } | |
1282 | 255 |
256 /* get general track initialization */ | |
1194 | 257 cdrom_drive_t *pcdrom_drive = cdio_cddap_identify_cdio(pcdio, 1, NULL); // todo : check return / NULL |
1048 | 258 firsttrackno = cdio_get_first_track_num(pcdrom_drive->p_cdio); |
259 lasttrackno = cdio_get_last_track_num(pcdrom_drive->p_cdio); | |
1123 | 260 if (firsttrackno == CDIO_INVALID_TRACK || lasttrackno == CDIO_INVALID_TRACK) { |
1282 | 261 fprintf(stderr, "cdaudio-ng: failed to retrieve first/last track number\n"); |
1123 | 262 cleanup_on_error(); |
263 return NULL; | |
264 } | |
1193 | 265 if (debug) |
266 printf("cdaudio-ng: first track is %d and last track is %d\n", firsttrackno, lasttrackno); | |
1048 | 267 |
1123 | 268 if (trackinfo != NULL) /* if a previously allocated track information exists, we free it */ |
1048 | 269 free(trackinfo); |
270 trackinfo = (trackinfo_t *) malloc(sizeof(trackinfo_t) * (lasttrackno + 1)); | |
271 int trackno; | |
1282 | 272 |
273 for (trackno = firsttrackno; trackno <= lasttrackno; trackno++) { | |
274 trackinfo[trackno].startlsn = cdio_get_track_lsn(pcdrom_drive->p_cdio, trackno); | |
275 trackinfo[trackno].endlsn = cdio_get_track_last_lsn(pcdrom_drive->p_cdio, trackno); | |
276 | |
277 if (trackinfo[trackno].startlsn == CDIO_INVALID_LSN || trackinfo[trackno].endlsn == CDIO_INVALID_LSN) { | |
278 fprintf(stderr, "cdaudio-ng: failed to retrieve stard/end lsn for track %d\n", trackno); | |
279 cleanup_on_error(); | |
280 return NULL; | |
281 } | |
282 } | |
283 | |
284 /* initialize de cddb subsystem */ | |
285 cddb_conn_t *pcddb_conn = NULL; | |
286 cddb_disc_t *pcddb_disc = NULL; | |
287 cddb_track_t *pcddb_track = NULL; | |
288 | |
289 if (use_cddb) { | |
290 pcddb_conn = cddb_new(); | |
291 if (pcddb_conn == NULL) | |
292 fprintf(stderr, "cdaudio-ng: failed to create the cddb connection\n"); | |
293 else { | |
294 if (debug) | |
295 printf("cdaudio-ng: getting cddb info\n"); | |
296 | |
297 // todo: change the default cddb settings | |
298 | |
299 pcddb_disc = cddb_disc_new(); | |
300 for (trackno = firsttrackno; trackno <= lasttrackno; trackno++) { | |
301 pcddb_track = cddb_track_new(); | |
302 cddb_track_set_frame_offset(pcddb_track, trackinfo[trackno].startlsn); | |
303 cddb_disc_add_track(pcddb_disc, pcddb_track); | |
304 } | |
305 | |
306 msf_t startmsf, endmsf; | |
307 cdio_get_track_msf(pcdio, 1, &startmsf); | |
308 cdio_get_track_msf(pcdio, CDIO_CDROM_LEADOUT_TRACK, &endmsf); | |
309 cddb_disc_set_length(pcddb_disc, cdio_audio_get_msf_seconds(&endmsf) - cdio_audio_get_msf_seconds(&startmsf)); | |
310 | |
311 int matches; | |
312 if ((matches = cddb_query(pcddb_conn, pcddb_disc)) == -1) { | |
313 fprintf(stderr, "cdaudio-ng: failed to query the cddb server: %s\n", cddb_error_str(cddb_errno(pcddb_conn))); | |
314 cddb_disc_destroy(pcddb_disc); | |
315 pcddb_disc = NULL; | |
316 } | |
317 else { | |
318 if (debug) | |
319 printf("cdaudio-ng: discid = %X, category = \"%s\"\n", cddb_disc_get_discid(pcddb_disc), cddb_disc_get_category_str(pcddb_disc)); | |
320 | |
321 cddb_read(pcddb_conn, pcddb_disc); | |
322 if (cddb_errno(pcddb_conn) != CDDB_ERR_OK) { | |
323 fprintf(stderr, "cdaudio-ng: failed to read the cddb info: %s\n", cddb_error_str(cddb_errno(pcddb_conn))); | |
324 cddb_disc_destroy(pcddb_disc); | |
325 pcddb_disc = NULL; | |
326 } | |
327 else { | |
328 if (debug) | |
329 printf("cdaudio-ng: we have got the cddb info\n"); | |
330 | |
331 strcpy(trackinfo[0].performer, cddb_disc_get_artist(pcddb_disc)); | |
332 strcpy(trackinfo[0].name, cddb_disc_get_title(pcddb_disc)); | |
333 strcpy(trackinfo[0].genre, cddb_disc_get_genre(pcddb_disc)); | |
334 } | |
335 } | |
336 } | |
337 } | |
338 | |
339 /* adding trackinfo[0] information (the disc) */ | |
340 if (use_cdtext) { | |
341 if (debug) | |
342 printf("cdaudio-ng: getting cd-text information for disc\n"); | |
343 cdtext_t *pcdtext = cdio_get_cdtext(pcdrom_drive->p_cdio, 0); | |
344 if (pcdtext == NULL || pcdtext->field[CDTEXT_TITLE] == NULL) { | |
345 if (debug) | |
346 printf("cdaudio-ng: no cd-text available for disc\n"); | |
347 } | |
348 else { | |
349 strcpy(trackinfo[0].performer, pcdtext->field[CDTEXT_PERFORMER] != NULL ? pcdtext->field[CDTEXT_PERFORMER] : ""); | |
350 strcpy(trackinfo[0].name, pcdtext->field[CDTEXT_TITLE] != NULL ? pcdtext->field[CDTEXT_TITLE] : ""); | |
351 strcpy(trackinfo[0].genre, pcdtext->field[CDTEXT_GENRE] != NULL ? pcdtext->field[CDTEXT_GENRE] : ""); | |
352 } | |
353 } | |
354 | |
355 /* add track "file" names to the list */ | |
356 GList *list = NULL; | |
1048 | 357 for (trackno = firsttrackno; trackno <= lasttrackno; trackno++) { |
358 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
|
359 cdtext_t *pcdtext = NULL; |
1282 | 360 if (use_cdtext) { |
361 if (debug) | |
362 printf("cdaudio-ng: getting cd-text information for track %d\n", trackno); | |
1189
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
363 pcdtext = cdio_get_cdtext(pcdrom_drive->p_cdio, trackno); |
1282 | 364 if (pcdtext == NULL || pcdtext->field[CDTEXT_PERFORMER] == NULL) { |
365 if (debug) | |
366 printf("cdaudio-ng: no cd-text available for track %d\n", trackno); | |
367 pcdtext = NULL; | |
368 } | |
369 } | |
1048 | 370 |
371 if (pcdtext != NULL) { | |
372 strcpy(trackinfo[trackno].performer, pcdtext->field[CDTEXT_PERFORMER] != NULL ? pcdtext->field[CDTEXT_PERFORMER] : ""); | |
373 strcpy(trackinfo[trackno].name, pcdtext->field[CDTEXT_TITLE] != NULL ? pcdtext->field[CDTEXT_TITLE] : ""); | |
374 strcpy(trackinfo[trackno].genre, pcdtext->field[CDTEXT_GENRE] != NULL ? pcdtext->field[CDTEXT_GENRE] : ""); | |
375 } | |
1282 | 376 else |
377 if (pcddb_disc != NULL) { | |
378 cddb_track_t *pcddb_track = cddb_disc_get_track(pcddb_disc, trackno - 1); | |
379 strcpy(trackinfo[trackno].performer, cddb_track_get_artist(pcddb_track)); | |
380 strcpy(trackinfo[trackno].name, cddb_track_get_title(pcddb_track)); | |
381 strcpy(trackinfo[trackno].genre, cddb_disc_get_genre(pcddb_disc)); | |
382 } | |
383 else { | |
384 strcpy(trackinfo[trackno].performer, ""); | |
385 strcpy(trackinfo[trackno].name, ""); | |
386 strcpy(trackinfo[trackno].genre, ""); | |
387 } | |
388 | |
1048 | 389 if (strlen(trackinfo[trackno].name) == 0) |
390 sprintf(trackinfo[trackno].name, "CD Audio Track %02u", trackno); | |
391 | |
1282 | 392 } |
393 | |
394 if (debug) { | |
395 printf("cdaudio-ng: disc has : performer = \"%s\", name = \"%s\", genre = \"%s\"\n", | |
396 trackinfo[0].performer, trackinfo[0].name, trackinfo[0].genre); | |
397 for (trackno = firsttrackno; trackno <= lasttrackno; trackno++) { | |
398 printf("cdaudio-ng: track %d has : performer = \"%s\", name = \"%s\", genre = \"%s\", startlsn = %d, endlsn = %d\n", | |
399 trackno, trackinfo[trackno].performer, trackinfo[trackno].name, trackinfo[trackno].genre, trackinfo[trackno].startlsn, trackinfo[trackno].endlsn); | |
1123 | 400 } |
1282 | 401 } |
1125 | 402 |
1282 | 403 if (pcddb_disc != NULL) |
404 cddb_disc_destroy(pcddb_disc); | |
405 if (pcddb_conn != NULL) | |
406 cddb_destroy(pcddb_conn); | |
1048 | 407 |
408 return list; | |
409 } | |
410 | |
411 void cdaudio_play_file(InputPlayback *pinputplayback) | |
1125 | 412 { |
1193 | 413 if (debug) |
414 printf("cdaudio-ng: cdaudio_play_file(\"%s\")\n", pinputplayback->filename); | |
1125 | 415 |
1048 | 416 if (trackinfo == NULL) { |
1193 | 417 if (debug) |
418 printf("cdaudio-ng: no cd information, scanning\n"); | |
1125 | 419 cdaudio_scan_dir(CDDA_DEFAULT); |
1048 | 420 } |
421 | |
1123 | 422 if (cdio_get_media_changed(pcdio)) { |
1193 | 423 if (debug) |
424 printf("cdaudio-ng: cd changed, rescanning\n"); | |
1125 | 425 cdaudio_scan_dir(CDDA_DEFAULT); |
1048 | 426 } |
1123 | 427 |
1048 | 428 int trackno = find_trackno_from_filename(pinputplayback->filename); |
1123 | 429 if (trackno < firsttrackno || trackno > lasttrackno) { |
1125 | 430 fprintf(stderr, "cdaudio-ng: trackno %d is out of range [%d..%d]\n", trackno, firsttrackno, lasttrackno); |
1123 | 431 cleanup_on_error(); |
1048 | 432 return; |
1123 | 433 } |
1048 | 434 |
435 pinputplayback->playing = TRUE; | |
436 playing_track = trackno; | |
1123 | 437 is_paused = FALSE; |
438 | |
439 if (use_dae) { | |
1193 | 440 if (debug) |
441 printf("cdaudio-ng: using digital audio extraction\n"); | |
1125 | 442 |
1123 | 443 if (pdae_params != NULL) { |
444 fprintf(stderr, "cdaudio-ng: dae playback seems to be already started\n"); | |
445 return; | |
446 } | |
447 | |
448 if (pinputplayback->output->open_audio(FMT_S16_LE, 44100, 2) == 0) { | |
449 fprintf(stderr, "cdaudio-ng: failed open audio output\n"); | |
450 cleanup_on_error(); | |
451 return; | |
452 } | |
453 | |
1193 | 454 if (debug) |
455 printf("cdaudio-ng: starting dae thread...\n"); | |
1123 | 456 pdae_params = (dae_params_t *) malloc(sizeof(dae_params_t)); |
457 pdae_params->startlsn = trackinfo[trackno].startlsn; | |
458 pdae_params->endlsn = trackinfo[trackno].endlsn; | |
459 pdae_params->pplayback = pinputplayback; | |
460 pdae_params->seektime = -1; | |
461 pdae_params->currlsn = trackinfo[trackno].startlsn; | |
462 pdae_params->thread = g_thread_create((GThreadFunc) dae_playing_thread_core, pdae_params, TRUE, NULL); | |
463 } | |
464 else { | |
1193 | 465 if (debug) |
466 printf("cdaudio-ng: not using digital audio extraction\n"); | |
1125 | 467 |
1123 | 468 msf_t startmsf, endmsf; |
469 cdio_lsn_to_msf(trackinfo[trackno].startlsn, &startmsf); | |
470 cdio_lsn_to_msf(trackinfo[trackno].endlsn, &endmsf); | |
471 if (cdio_audio_play_msf(pcdio, &startmsf, &endmsf) != DRIVER_OP_SUCCESS) { | |
472 fprintf(stderr, "cdaudio-ng: failed to play analog audio cd\n"); | |
473 cleanup_on_error(); | |
474 return; | |
475 } | |
476 } | |
477 | |
1048 | 478 char title[DEF_STRING_LEN]; |
1123 | 479 |
1048 | 480 if (strlen(trackinfo[trackno].performer) > 0) { |
481 strcpy(title, trackinfo[trackno].performer); | |
482 strcat(title, " - "); | |
483 } | |
484 else | |
485 strcpy(title, ""); | |
486 strcat(title, trackinfo[trackno].name); | |
1123 | 487 |
1048 | 488 inputplugin.set_info(title, calculate_track_length(trackinfo[trackno].startlsn, trackinfo[trackno].endlsn), 128000, 44100, 2); |
489 } | |
490 | |
491 void cdaudio_stop(InputPlayback *pinputplayback) | |
1125 | 492 { |
1193 | 493 if (debug) |
494 printf("cdaudio-ng: cdaudio_stop(\"%s\")\n", pinputplayback->filename); | |
1125 | 495 |
1048 | 496 pinputplayback->playing = FALSE; |
497 playing_track = -1; | |
1123 | 498 is_paused = FALSE; |
499 | |
500 if (use_dae) { | |
501 if (pdae_params != NULL) { | |
502 g_thread_join(pdae_params->thread); | |
503 free(pdae_params); | |
504 pdae_params = NULL; | |
505 } | |
506 } | |
507 else { | |
508 if (cdio_audio_stop(pcdio) != DRIVER_OP_SUCCESS) { | |
509 fprintf(stderr, "cdaudio-ng: failed to stop analog cd\n"); | |
510 cleanup_on_error(); | |
511 return; | |
512 } | |
513 } | |
1048 | 514 } |
515 | |
516 void cdaudio_pause(InputPlayback *pinputplayback, gshort paused) | |
517 { | |
1193 | 518 if (debug) |
519 printf("cdaudio-ng: cdaudio_pause(\"%s\", %d)\n", pinputplayback->filename, paused); | |
1125 | 520 |
1048 | 521 if (!is_paused) { |
522 is_paused = TRUE; | |
1123 | 523 if (!use_dae) |
524 if (cdio_audio_pause(pcdio) != DRIVER_OP_SUCCESS) { | |
525 fprintf(stderr, "cdaudio-ng: failed to pause analog cd\n"); | |
526 cleanup_on_error(); | |
527 return; | |
528 } | |
1048 | 529 } |
530 else { | |
531 is_paused = FALSE; | |
1123 | 532 if (!use_dae) |
533 if (cdio_audio_resume(pcdio) != DRIVER_OP_SUCCESS) { | |
534 fprintf(stderr, "cdaudio-ng: failed to resume analog cd\n"); | |
535 cleanup_on_error(); | |
536 return; | |
537 } | |
1048 | 538 } |
539 } | |
540 | |
541 void cdaudio_seek(InputPlayback *pinputplayback, gint time) | |
542 { | |
1193 | 543 if (debug) |
544 printf("cdaudio-ng: cdaudio_seek(\"%s\", %d)\n", pinputplayback->filename, time); | |
1125 | 545 |
1048 | 546 if (playing_track == -1) |
547 return; | |
548 | |
1123 | 549 if (use_dae) { |
550 if (pdae_params != NULL) { | |
551 pdae_params->seektime = time * 1000; | |
552 } | |
553 } | |
554 else { | |
555 int newstartlsn = trackinfo[playing_track].startlsn + time * 75; | |
556 msf_t startmsf, endmsf; | |
557 cdio_lsn_to_msf(newstartlsn, &startmsf); | |
558 cdio_lsn_to_msf(trackinfo[playing_track].endlsn, &endmsf); | |
559 | |
560 if (cdio_audio_play_msf(pcdio, &startmsf, &endmsf) != DRIVER_OP_SUCCESS) { | |
561 fprintf(stderr, "cdaudio-ng: failed to play analog cd\n"); | |
562 cleanup_on_error(); | |
563 return; | |
564 } | |
565 } | |
1048 | 566 } |
567 | |
568 gint cdaudio_get_time(InputPlayback *pinputplayback) | |
569 { | |
1125 | 570 //printf("cdaudio-ng: cdaudio_get_time(\"%s\")\n", pinputplayback->filename); // annoying! |
571 | |
1048 | 572 if (playing_track == -1) |
573 return -1; | |
574 | |
1123 | 575 if (!use_dae) { |
576 cdio_subchannel_t subchannel; | |
577 if (cdio_audio_read_subchannel(pcdio, &subchannel) != DRIVER_OP_SUCCESS) { | |
578 fprintf(stderr, "cdaudio-ng: failed to read analog cd subchannel\n"); | |
579 cleanup_on_error(); | |
580 return -1; | |
581 } | |
582 int currlsn = cdio_msf_to_lsn(&subchannel.abs_addr); | |
1048 | 583 |
1123 | 584 /* check to see if we have reached the end of the song */ |
585 if (currlsn == trackinfo[playing_track].endlsn) { | |
586 cdaudio_stop(pinputplayback); | |
587 return -1; | |
588 } | |
589 | |
590 return calculate_track_length(trackinfo[playing_track].startlsn, currlsn); | |
1048 | 591 } |
1123 | 592 else { |
593 if (pdae_params != NULL) | |
594 return pinputplayback->output->output_time(); | |
595 else | |
596 return -1; | |
597 } | |
1048 | 598 } |
599 | |
600 gint cdaudio_get_volume(gint *l, gint *r) | |
601 { | |
1125 | 602 //printf("cdaudio-ng: cdaudio_get_volume()\n"); // annoying! |
603 | |
1123 | 604 if (use_dae) { |
605 *l = *r = 0; | |
606 return FALSE; | |
607 } | |
608 else { | |
609 cdio_audio_volume_t volume; | |
610 if (cdio_audio_get_volume(pcdio, &volume) != DRIVER_OP_SUCCESS) { | |
611 fprintf(stderr, "cdaudio-ng: failed to retrieve analog cd volume\n"); | |
612 cleanup_on_error(); | |
613 *l = *r = 0; | |
614 return FALSE; | |
615 } | |
616 *l = volume.level[0]; | |
617 *r = volume.level[1]; | |
618 | |
619 return TRUE; | |
620 } | |
1048 | 621 } |
622 | |
623 gint cdaudio_set_volume(gint l, gint r) | |
624 { | |
1193 | 625 if (debug) |
626 printf("cdaudio-ng: cdaudio_set_volume(%d, %d)\n", l, r); | |
1125 | 627 |
1123 | 628 if (use_dae) { |
629 return FALSE; | |
630 } | |
631 else { | |
632 cdio_audio_volume_t volume = {{l, r, 0, 0}}; | |
633 if (cdio_audio_set_volume(pcdio, &volume) != DRIVER_OP_SUCCESS) { | |
634 fprintf(stderr, "cdaudio-ng: failed to set analog cd volume\n"); | |
635 cleanup_on_error(); | |
636 return FALSE; | |
637 } | |
638 | |
639 return TRUE; | |
640 } | |
1048 | 641 } |
642 | |
643 void cdaudio_cleanup() | |
644 { | |
1193 | 645 if (debug) |
646 printf("cdaudio-ng: cdaudio_cleanup()\n"); | |
1125 | 647 |
1282 | 648 libcddb_shutdown(); |
649 | |
1123 | 650 if (pcdio!= NULL) { |
651 if (playing_track != -1 && !use_dae) | |
652 cdio_audio_stop(pcdio); | |
653 cdio_destroy(pcdio); | |
654 pcdio = NULL; | |
655 } | |
656 if (trackinfo != NULL) { | |
657 free(trackinfo); | |
658 trackinfo = NULL; | |
659 } | |
660 playing_track = -1; | |
1282 | 661 |
1189
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
662 // todo: destroy the gui |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
663 |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
664 ConfigDb *db = bmp_cfg_db_open(); |
af5bd4592100
Added cdaudio-ng.h; added a configure dialog
zither@litestep.network
parents:
1125
diff
changeset
|
665 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
|
666 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
|
667 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
|
668 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
|
669 bmp_cfg_db_set_string(db, "CDDA", "device", device); |
1193 | 670 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
|
671 bmp_cfg_db_close(db); |
1048 | 672 } |
673 | |
674 void cdaudio_get_song_info(gchar *filename, gchar **title, gint *length) | |
675 { | |
1193 | 676 if (debug) |
677 printf("cdaudio-ng: cdaudio_get_song_info(\"%s\")\n", filename); | |
1125 | 678 |
679 int trackno = find_trackno_from_filename(filename); | |
680 char *thetitle = (char *) malloc(DEF_STRING_LEN); | |
681 | |
682 if (strlen(trackinfo[trackno].performer) > 0) { | |
683 strcpy(thetitle, trackinfo[trackno].performer); | |
684 strcat(thetitle, " - "); | |
685 } | |
686 else | |
687 strcpy(thetitle, ""); | |
688 strcat(thetitle, trackinfo[trackno].name); | |
689 | |
690 *title = thetitle; | |
691 *length = calculate_track_length(trackinfo[trackno].startlsn, trackinfo[trackno].endlsn); | |
1048 | 692 } |
693 | |
694 void cdaudio_file_info_box(gchar *filename) | |
695 { | |
1193 | 696 if (debug) |
697 printf("cdaudio-ng: cdaudio_file_info_box(\"%s\")\n", filename); | |
1048 | 698 } |
699 | |
700 TitleInput *cdaudio_get_song_tuple(gchar *filename) | |
701 { | |
1193 | 702 if (debug) |
703 printf("cdaudio-ng: cdaudio_get_song_tuple(\"%s\")\n", filename); | |
1125 | 704 |
1048 | 705 TitleInput *tuple = bmp_title_input_new(); |
706 | |
707 /* return information about the requested track */ | |
708 int trackno = find_trackno_from_filename(filename); | |
709 if (trackno < firsttrackno || trackno > lasttrackno) | |
710 return NULL; | |
711 | |
712 tuple->performer = strlen(trackinfo[trackno].performer) > 0 ? g_strdup(trackinfo[trackno].performer) : NULL; | |
1282 | 713 tuple->album_name = strlen(trackinfo[0].name) > 0 ? g_strdup(trackinfo[0].name) : NULL; |
1048 | 714 tuple->track_name = strlen(trackinfo[trackno].name) > 0 ? g_strdup(trackinfo[trackno].name) : NULL; |
715 tuple->track_number = trackno; | |
716 tuple->file_name = g_strdup(basename(filename)); | |
717 tuple->file_path = g_strdup(basename(filename)); | |
718 tuple->file_ext = g_strdup("cda"); | |
719 tuple->length = calculate_track_length(trackinfo[trackno].startlsn, trackinfo[trackno].endlsn); | |
720 tuple->genre = strlen(trackinfo[trackno].genre) > 0 ? g_strdup(trackinfo[trackno].genre) : NULL; | |
721 //tuple->year = 0; todo: set the year | |
722 | |
723 return tuple; | |
724 } | |
725 | |
726 | |
727 /* auxiliar functions */ | |
728 | |
1282 | 729 |
1048 | 730 static int calculate_digit_sum(int n) |
731 { | |
732 int ret = 0; | |
733 | |
734 while (1) { | |
735 ret += n % 10; | |
736 n = n / 10; | |
737 if (n == 0) | |
738 return ret; | |
739 } | |
740 } | |
1282 | 741 |
1048 | 742 |
1282 | 743 |
1048 | 744 static unsigned long calculate_cddb_discid() |
745 { | |
746 int trackno, t, n = 0; | |
747 msf_t startmsf; | |
748 msf_t msf; | |
749 | |
750 for (trackno = firsttrackno; trackno <= lasttrackno; trackno++) { | |
1282 | 751 cdio_get_track_msf(pcdio, trackno, &msf); |
1048 | 752 n += calculate_digit_sum(cdio_audio_get_msf_seconds(&msf)); |
753 } | |
754 | |
1282 | 755 cdio_get_track_msf(pcdio, 1, &startmsf); |
756 cdio_get_track_msf(pcdio, CDIO_CDROM_LEADOUT_TRACK, &msf); | |
1048 | 757 |
758 t = cdio_audio_get_msf_seconds(&msf) - cdio_audio_get_msf_seconds(&startmsf); | |
759 | |
760 return ((n % 0xFF) << 24 | t << 8 | (lasttrackno - firsttrackno + 1)); | |
761 } | |
1282 | 762 |
1048 | 763 |
1123 | 764 void *dae_playing_thread_core(dae_params_t *pdae_params) |
765 { | |
766 unsigned char *buffer = (unsigned char *) malloc(CDDA_DAE_FRAMES * CDIO_CD_FRAMESIZE_RAW); | |
767 | |
1193 | 768 if (debug) |
769 printf("cdaudio-ng: dae thread started\n"); | |
1123 | 770 cdio_lseek(pcdio, pdae_params->startlsn * CDIO_CD_FRAMESIZE_RAW, SEEK_SET); |
771 | |
772 gboolean output_paused = FALSE; | |
1125 | 773 |
1123 | 774 while (pdae_params->pplayback->playing) { |
775 /* handle pause status */ | |
776 if (is_paused) { | |
777 if (!output_paused) { | |
1193 | 778 if (debug) |
779 printf("cdaudio-ng: playback was not paused, pausing\n"); | |
1123 | 780 pdae_params->pplayback->output->pause(TRUE); |
781 output_paused = TRUE; | |
782 } | |
783 usleep(1000); | |
784 continue; | |
785 } | |
1125 | 786 else { |
1123 | 787 if (output_paused) { |
1193 | 788 if (debug) |
789 printf("cdaudio-ng: playback was paused, resuming\n"); | |
1123 | 790 pdae_params->pplayback->output->pause(FALSE); |
791 output_paused = FALSE; | |
792 } | |
1125 | 793 } |
1123 | 794 |
795 /* check if we have to seek */ | |
796 if (pdae_params->seektime != -1) { | |
1193 | 797 if (debug) |
798 printf("cdaudio-ng: requested seek to %d ms\n", pdae_params->seektime); | |
1123 | 799 int newlsn = pdae_params->startlsn + pdae_params->seektime * 75 / 1000; |
800 cdio_lseek(pcdio, newlsn * CDIO_CD_FRAMESIZE_RAW, SEEK_SET); | |
801 pdae_params->pplayback->output->flush(pdae_params->seektime); | |
802 pdae_params->currlsn = newlsn; | |
803 pdae_params->seektime = -1; | |
804 } | |
805 | |
806 /* compute the actual number of sectors to read */ | |
807 int lsncount = CDDA_DAE_FRAMES <= (pdae_params->endlsn - pdae_params->currlsn + 1) ? CDDA_DAE_FRAMES : (pdae_params->endlsn - pdae_params->currlsn + 1); | |
808 /* check too see if we have reached the end of the song */ | |
809 if (lsncount <= 0) | |
810 break; | |
811 | |
812 if (cdio_read_audio_sectors(pcdio, buffer, pdae_params->currlsn, lsncount) != DRIVER_OP_SUCCESS) { | |
813 fprintf(stderr, "cdaudio-ng: failed to read audio sector\n"); | |
814 /* ok, that's it, we go on */ | |
815 } | |
816 | |
817 int remainingbytes = lsncount * CDIO_CD_FRAMESIZE_RAW; | |
818 unsigned char *bytebuff = buffer; | |
819 while (pdae_params->pplayback->playing && remainingbytes > 0 && pdae_params->seektime == -1) { | |
820 /* compute the actual number of bytes to play */ | |
821 int bytecount = CDIO_CD_FRAMESIZE_RAW <= remainingbytes ? CDIO_CD_FRAMESIZE_RAW : remainingbytes; | |
822 /* wait until the output buffer has enough room */ | |
823 while (pdae_params->pplayback->playing && pdae_params->pplayback->output->buffer_free() < bytecount && pdae_params->seektime == -1) | |
824 usleep(1000); | |
825 /* play the sound :) */ | |
826 if (pdae_params->pplayback->playing && pdae_params->seektime == -1) | |
827 produce_audio(pdae_params->pplayback->output->written_time(), FMT_S16_LE, 2, bytecount, bytebuff, &pdae_params->pplayback->playing); | |
828 remainingbytes -= bytecount; | |
829 bytebuff += bytecount; | |
830 } | |
831 pdae_params->currlsn += lsncount; | |
832 } | |
1193 | 833 if (debug) |
834 printf("cdaudio-ng: dae thread ended\n"); | |
1123 | 835 |
836 pdae_params->pplayback->playing = FALSE; | |
837 playing_track = -1; | |
838 is_paused = FALSE; | |
839 | |
840 pdae_params->pplayback->output->close_audio(); | |
841 free(buffer); | |
842 | |
843 g_thread_exit(NULL); | |
844 return NULL; | |
845 } | |
846 | |
1048 | 847 int calculate_track_length(int startlsn, int endlsn) |
848 { | |
849 return ((endlsn - startlsn + 1) * 1000) / 75; | |
850 } | |
851 | |
852 int find_trackno_from_filename(char *filename) | |
853 { | |
854 if ((filename == NULL) || strlen(filename) <= 6) | |
855 return -1; | |
856 | |
857 char tracknostr[3]; | |
858 strncpy(tracknostr, filename + strlen(filename) - 6, 2); | |
859 tracknostr[2] = '\0'; | |
860 return strtol(tracknostr, NULL, 10); | |
861 } | |
1123 | 862 |
863 void cleanup_on_error() | |
864 { | |
865 if (pcdio != NULL) { | |
866 if (playing_track != -1 && !use_dae) | |
867 cdio_audio_stop(pcdio); | |
868 } | |
869 if (trackinfo != NULL) { | |
870 free(trackinfo); | |
871 trackinfo = NULL; | |
872 } | |
873 playing_track = -1; | |
874 } | |
1193 | 875 |