Mercurial > audlegacy-plugins
comparison src/madplug/input.c @ 611:3f7a52adfe0e trunk
[svn] merge recent changes from yaz's branch.
- stable shoutcast playback.
- tag handling improvement.
- view track detail on streaming won't crash. (disabled.)
- filepopup for streaming is partially supported. filepopup displays track name and stream name, but not updated automatically.
author | yaz |
---|---|
date | Tue, 06 Feb 2007 12:11:42 -0800 |
parents | 862190d39e00 |
children | 951b24719ce9 |
comparison
equal
deleted
inserted
replaced
610:862190d39e00 | 611:3f7a52adfe0e |
---|---|
64 #define HEADER_SIZE 256 | 64 #define HEADER_SIZE 256 |
65 #define LINE_LENGTH 256 | 65 #define LINE_LENGTH 256 |
66 | 66 |
67 extern gboolean scan_file(struct mad_info_t *info, gboolean fast); | 67 extern gboolean scan_file(struct mad_info_t *info, gboolean fast); |
68 | 68 |
69 // new VFS handles url. | |
70 static void input_parse_url(struct mad_info_t *info) | |
71 { | |
72 info->filename = g_strdup(info->url); | |
73 return; | |
74 } | |
75 | |
76 | |
69 /** | 77 /** |
70 * init the mad_info_t struct. | 78 * init the mad_info_t struct. |
71 */ | 79 */ |
72 gboolean input_init(struct mad_info_t * info, const char *url) | 80 gboolean input_init(struct mad_info_t * info, const char *url) |
73 { | 81 { |
99 info->replaygain_track_peak_str = 0; | 107 info->replaygain_track_peak_str = 0; |
100 info->mp3gain_undo_str = 0; | 108 info->mp3gain_undo_str = 0; |
101 info->mp3gain_minmax_str = 0; | 109 info->mp3gain_minmax_str = 0; |
102 | 110 |
103 info->tuple = NULL; | 111 info->tuple = NULL; |
104 info->filename = g_strdup(url); | 112 |
113 input_parse_url(info); | |
105 | 114 |
106 info->infile = vfs_fopen(info->filename, "rb"); | 115 info->infile = vfs_fopen(info->filename, "rb"); |
107 if (info->infile == NULL) | 116 if (info->infile == NULL) { |
108 return FALSE; | 117 return FALSE; |
109 | 118 } |
110 // obtain file size | 119 // obtain file size |
111 vfs_fseek(info->infile, 0, SEEK_END); | 120 vfs_fseek(info->infile, 0, SEEK_END); |
112 info->size = vfs_ftell(info->infile); | 121 info->size = vfs_ftell(info->infile); |
113 vfs_fseek(info->infile, 0, SEEK_SET); | 122 vfs_fseek(info->infile, 0, SEEK_SET); |
114 info->remote = info->size == 0 ? TRUE : FALSE; | 123 info->remote = info->size == 0 ? TRUE : FALSE; |
115 | 124 |
116 #ifdef DEBUG | 125 #ifdef DEBUG |
117 g_message("i: info->size == %lu", info->size); | |
118 g_message("e: input_init"); | 126 g_message("e: input_init"); |
119 #endif | 127 #endif |
120 return TRUE; | 128 return TRUE; |
121 } | 129 } |
122 | 130 |
157 size_t tmp_len = 0; | 165 size_t tmp_len = 0; |
158 gboolean is_num = TRUE; | 166 gboolean is_num = TRUE; |
159 | 167 |
160 tail = (id3_ucs4_t *)string + mad_ucs4len((id3_ucs4_t *)string); | 168 tail = (id3_ucs4_t *)string + mad_ucs4len((id3_ucs4_t *)string); |
161 | 169 |
162 ret = g_malloc0(1024); // realloc() is too picky | 170 ret = g_malloc0(1024); |
163 | 171 |
164 for(ptr = (id3_ucs4_t *)string; *ptr != 0 && ptr <= tail; ptr++) { | 172 for(ptr = (id3_ucs4_t *)string; *ptr != 0 && ptr <= tail; ptr++) { |
165 if(*ptr == '(') { | 173 if(*ptr == '(') { |
166 if(*(++ptr) == '(') { // escaped text like: ((something) | 174 if(*(++ptr) == '(') { // escaped text like: ((something) |
167 for(end = ptr; *end != ')' && *end != 0;) { // copy "(something)" | 175 for(end = ptr; *end != ')' && *end != 0;) { // copy "(something)" |
168 end++; | 176 end++; |
169 } | 177 } |
170 end++; //include trailing ')' | 178 end++; //include trailing ')' |
171 // ret = g_realloc(ret, BYTES(end - ptr + 1)); | |
172 memcpy(ret, ptr, BYTES(end - ptr)); | 179 memcpy(ret, ptr, BYTES(end - ptr)); |
173 ret_len += (end - ptr); | 180 ret_len += (end - ptr); |
174 *(ret + ret_len) = 0; //terminate | 181 *(ret + ret_len) = 0; //terminate |
175 ptr = end + 1; | 182 ptr = end + 1; |
176 } | 183 } |
190 g_free(tmp); | 197 g_free(tmp); |
191 tmp = NULL; | 198 tmp = NULL; |
192 | 199 |
193 tmp_len = mad_ucs4len(genre); | 200 tmp_len = mad_ucs4len(genre); |
194 | 201 |
195 // ret = g_realloc(ret, BYTES(ret_len + tmp_len + 1)); | |
196 memcpy(ret + BYTES(ret_len), genre, BYTES(tmp_len)); | 202 memcpy(ret + BYTES(ret_len), genre, BYTES(tmp_len)); |
197 | 203 |
198 ret_len += tmp_len; | 204 ret_len += tmp_len; |
199 *(ret + ret_len) = 0; //terminate | 205 *(ret + ret_len) = 0; //terminate |
200 } | 206 } |
229 g_free(tmp); | 235 g_free(tmp); |
230 tmp = NULL; | 236 tmp = NULL; |
231 | 237 |
232 tmp_len = mad_ucs4len(genre); | 238 tmp_len = mad_ucs4len(genre); |
233 | 239 |
234 // ret = g_realloc(ret, BYTES(ret_len + tmp_len + 1)); | |
235 memcpy(ret + BYTES(ret_len), genre, BYTES(tmp_len)); | 240 memcpy(ret + BYTES(ret_len), genre, BYTES(tmp_len)); |
236 | 241 |
237 ret_len += tmp_len; | 242 ret_len += tmp_len; |
238 *(ret + ret_len) = 0; //terminate | 243 *(ret + ret_len) = 0; //terminate |
239 } | 244 } |
240 else { // plain text | 245 else { // plain text |
241 // ret = g_realloc(ret, BYTES(end - ptr + 1)); | |
242 #ifdef DEBUG | 246 #ifdef DEBUG |
243 printf("plain!\n"); | 247 printf("plain!\n"); |
244 printf("ret_len = %d\n", ret_len); | 248 printf("ret_len = %d\n", ret_len); |
245 #endif | 249 #endif |
246 memcpy(ret + BYTES(ret_len), ptr, BYTES(end - ptr)); | 250 memcpy(ret + BYTES(ret_len), ptr, BYTES(end - ptr)); |
255 | 259 |
256 | 260 |
257 gchar *input_id3_get_string(struct id3_tag * tag, char *frame_name) | 261 gchar *input_id3_get_string(struct id3_tag * tag, char *frame_name) |
258 { | 262 { |
259 gchar *rtn; | 263 gchar *rtn; |
264 gchar *rtn2; | |
260 const id3_ucs4_t *string_const; | 265 const id3_ucs4_t *string_const; |
261 id3_ucs4_t *string; | 266 id3_ucs4_t *string; |
267 id3_ucs4_t *ucsptr; | |
262 struct id3_frame *frame; | 268 struct id3_frame *frame; |
263 union id3_field *field; | 269 union id3_field *field; |
270 gboolean flagutf = FALSE; | |
264 | 271 |
265 frame = id3_tag_findframe(tag, frame_name, 0); | 272 frame = id3_tag_findframe(tag, frame_name, 0); |
266 if (!frame) | 273 if (!frame) |
267 return NULL; | 274 return NULL; |
268 | 275 |
269 if (frame_name == ID3_FRAME_COMMENT) | 276 if (!strcmp(frame_name, ID3_FRAME_COMMENT)) |
270 field = id3_frame_field(frame, 3); | 277 field = id3_frame_field(frame, 3); |
271 else | 278 else |
272 field = id3_frame_field(frame, 1); | 279 field = id3_frame_field(frame, 1); |
273 | 280 |
274 if (!field) | 281 if (!field) |
275 return NULL; | 282 return NULL; |
276 | 283 |
277 if (frame_name == ID3_FRAME_COMMENT) | 284 if (!strcmp(frame_name, ID3_FRAME_COMMENT)) |
278 string_const = id3_field_getfullstring(field); | 285 string_const = id3_field_getfullstring(field); |
279 else | 286 else |
280 string_const = id3_field_getstrings(field, 0); | 287 string_const = id3_field_getstrings(field, 0); |
281 | 288 |
282 if (!string_const) | 289 if (!string_const) |
283 return NULL; | 290 return NULL; |
284 | 291 |
285 string = mad_ucs4dup((id3_ucs4_t *)string_const); | 292 string = mad_ucs4dup((id3_ucs4_t *)string_const); |
286 | 293 |
287 if (frame_name == ID3_FRAME_GENRE) { | 294 if (!strcmp(frame_name, ID3_FRAME_GENRE)) { |
288 id3_ucs4_t *string2 = NULL; | 295 id3_ucs4_t *string2 = NULL; |
289 string2 = mad_parse_genre(string); | 296 string2 = mad_parse_genre(string); |
290 g_free((void *)string); | 297 g_free((void *)string); |
291 string = string2; | 298 string = string2; |
292 } | 299 } |
293 | 300 |
294 { | 301 ucsptr = (id3_ucs4_t *)string; |
295 id3_utf8_t *string2 = id3_ucs4_utf8duplicate(string); | 302 while (*ucsptr) { |
296 rtn = str_to_utf8(string2); | 303 if (*ucsptr > 0x000000ffL) { |
297 g_free(string2); | 304 flagutf = TRUE; |
298 } | 305 break; |
299 | 306 } |
300 #ifdef DEBUG | 307 ucsptr++; |
301 g_print("i: string = %s\n", rtn); | 308 } |
309 | |
310 if (flagutf) { | |
311 #ifdef DEBUG | |
312 g_print("aud-mad: flagutf!\n"); | |
313 #endif | |
314 rtn = (gchar *)id3_ucs4_utf8duplicate(string); | |
315 } | |
316 else { | |
317 rtn = (gchar *)id3_ucs4_latin1duplicate(string); | |
318 rtn2 = str_to_utf8(rtn); | |
319 free(rtn); | |
320 rtn = rtn2; | |
321 } | |
322 g_free(string); | |
323 string = NULL; | |
324 #ifdef DEBUG | |
325 g_print("string = %s\n", rtn); | |
302 #endif | 326 #endif |
303 return rtn; | 327 return rtn; |
304 } | 328 } |
305 | 329 |
306 /** | 330 /** |
377 #endif /* DEBUG */ | 401 #endif /* DEBUG */ |
378 input_read_tag(info); | 402 input_read_tag(info); |
379 input_read_replaygain(info); | 403 input_read_replaygain(info); |
380 | 404 |
381 /* scan mp3 file, decoding headers unless fast_scan is set */ | 405 /* scan mp3 file, decoding headers unless fast_scan is set */ |
382 if (scan_file(info, fast_scan) == FALSE) | 406 if (scan_file(info, fast_scan) == FALSE) { |
383 return FALSE; | 407 return FALSE; |
384 | 408 } |
385 /* reset the input file to the start */ | 409 /* reset the input file to the start */ |
386 vfs_rewind(info->infile); | 410 vfs_fseek(info->infile, 0, SEEK_SET); |
387 info->offset = 0; | 411 info->offset = 0; |
388 | 412 |
389 if (info->remote) | 413 if(info->remote){ |
390 { | |
391 gchar *stream_name = vfs_get_metadata(info->infile, "stream-name"); | 414 gchar *stream_name = vfs_get_metadata(info->infile, "stream-name"); |
392 gchar *track_name = vfs_get_metadata(info->infile, "track-name"); | 415 gchar *track_name = vfs_get_metadata(info->infile, "track-name"); |
393 gchar *tmp = NULL; | 416 gchar *tmp = NULL; |
394 | 417 |
395 g_free(info->title); | 418 g_free(info->title); |
405 info->bitrate, info->freq, info->channels); | 428 info->bitrate, info->freq, info->channels); |
406 g_free(tmp); g_free(stream_name); g_free(track_name); | 429 g_free(tmp); g_free(stream_name); g_free(track_name); |
407 } | 430 } |
408 | 431 |
409 /* use the filename for the title as a last resort */ | 432 /* use the filename for the title as a last resort */ |
410 if (!info->title) | 433 if (!info->title) { |
411 { | |
412 char *pos = strrchr(info->filename, DIR_SEPARATOR); | 434 char *pos = strrchr(info->filename, DIR_SEPARATOR); |
413 if (pos) | 435 if (pos) |
414 info->title = g_strdup(pos + 1); | 436 info->title = g_strdup(pos + 1); |
415 else | 437 else |
416 info->title = g_strdup(info->filename); | 438 info->title = g_strdup(info->filename); |
419 #ifdef DEBUG | 441 #ifdef DEBUG |
420 g_message("e: input_get_info"); | 442 g_message("e: input_get_info"); |
421 #endif /* DEBUG */ | 443 #endif /* DEBUG */ |
422 return TRUE; | 444 return TRUE; |
423 } | 445 } |
446 | |
424 | 447 |
425 | 448 |
426 /** | 449 /** |
427 * Read data from the source given my madinfo into the buffer | 450 * Read data from the source given my madinfo into the buffer |
428 * provided. Return the number of bytes read. | 451 * provided. Return the number of bytes read. |
429 * @return 0 on EOF | 452 * @return 0 on EOF |
430 * @return -1 on error | 453 * @return -1 on error |
431 */ | 454 */ |
455 // this function may be called before info->playback initialized. | |
432 int | 456 int |
433 input_get_data(struct mad_info_t *madinfo, guchar * buffer, | 457 input_get_data(struct mad_info_t *madinfo, guchar * buffer, |
434 int buffer_size) | 458 int buffer_size) |
435 { | 459 { |
436 int len = 0; | 460 int len = 0; |
437 #ifdef DEBUG | 461 #ifdef DEBUG |
438 // g_message ("f: input_get_data: %d", buffer_size); | 462 #ifdef DEBUG_INTENSIVELY |
439 #endif | 463 g_message ("f: input_get_data: %d", buffer_size); |
440 | 464 #endif |
465 #endif | |
441 /* simply read to data from the file */ | 466 /* simply read to data from the file */ |
442 len = vfs_fread(buffer, 1, buffer_size, madinfo->infile); | 467 len = vfs_fread(buffer, 1, buffer_size, madinfo->infile); //vfs_fread returns num of element. |
443 | 468 |
444 if (len == 0 && madinfo->playback) | 469 if(len == 0){ |
445 madinfo->playback->eof = TRUE; | 470 if(madinfo->playback) |
446 | 471 madinfo->playback->eof = TRUE; |
447 if (madinfo->remote) | 472 } |
448 { | 473 |
474 if(madinfo->remote) { | |
449 gchar *stream_name = vfs_get_metadata(madinfo->infile, "stream-name"); | 475 gchar *stream_name = vfs_get_metadata(madinfo->infile, "stream-name"); |
450 gchar *track_name = vfs_get_metadata(madinfo->infile, "track-name"); | 476 gchar *track_name = vfs_get_metadata(madinfo->infile, "track-name"); |
451 gchar *tmp = NULL; | 477 gchar *tmp = NULL; |
452 | 478 |
453 g_free(madinfo->title); | 479 g_free(madinfo->title); |
457 madinfo->title = g_strdup(track_name); | 483 madinfo->title = g_strdup(track_name); |
458 madinfo->tuple->track_name = g_strdup(track_name); | 484 madinfo->tuple->track_name = g_strdup(track_name); |
459 madinfo->tuple->album_name = g_strdup(stream_name); | 485 madinfo->tuple->album_name = g_strdup(stream_name); |
460 tmp = g_strdup_printf("%s (%s)", track_name, stream_name); | 486 tmp = g_strdup_printf("%s (%s)", track_name, stream_name); |
461 mad_plugin->set_info(tmp, | 487 mad_plugin->set_info(tmp, |
462 -1, // indicates the stream is unseekable | 488 -1, // indicate the stream is unseekable |
463 madinfo->bitrate, madinfo->freq, madinfo->channels); | 489 madinfo->bitrate, madinfo->freq, madinfo->channels); |
464 g_free(tmp); g_free(stream_name); g_free(track_name); | 490 g_free(tmp); g_free(stream_name); g_free(track_name); |
465 } | 491 } |
466 | 492 |
467 #ifdef DEBUG | 493 #ifdef DEBUG |
468 // g_message ("e: input_get_data: size=%d offset=%d", len, madinfo->offset); | 494 #ifdef DEBUG_INTENSIVELY |
495 g_message ("e: input_get_data: size=%d offset=%d", len, madinfo->offset); | |
496 #endif | |
469 #endif | 497 #endif |
470 madinfo->offset += len; | 498 madinfo->offset += len; |
471 return len; | 499 return len; |
472 } | 500 } |
473 | 501 |