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