int playback(FILE * streamfd, int pipefd) { killed = 0; signal(SIGUSR1, sighand); #ifndef EXTERN_ONLY if(!haskey(& rc, "extern")) { const char * freetrack = NULL; struct stream data; struct mad_decoder dec; #ifdef LIBAO static int ao_initialized = 0; if(!ao_initialized) { ao_initialize(); ao_initialized = !0; } #else unsigned arg; int fd; #endif memset(& data, 0, sizeof(struct stream)); /* Check if there's a stream timeout configured and set it up for timed reads later. */ data.timeout = -1; if(haskey(& rc, "stream-timeout")) { const char * timeout = value(& rc, "stream-timeout"); data.timeout = atoi(timeout); if(data.timeout <= 0) { if(data.timeout < 0) fputs("Invalid stream-timeout.\n", stderr); data.timeout = -1; } } data.streamfd = streamfd; data.parent = getppid(); data.pipefd = pipefd; fcntl(pipefd, F_SETFL, O_NONBLOCK); #ifdef LIBAO data.driver_id = ao_default_driver_id(); if(-1 == data.driver_id) { fputs("Unable to find any usable output device!\n", stderr); return 0; } data.fmt.bits = 16; data.fmt.rate = 44100; data.fmt.channels = 2; data.fmt.byte_format = AO_FMT_NATIVE; data.device = ao_open_live(data.driver_id,&data.fmt,NULL); if(NULL == data.device) { fprintf(stderr, "Unable to open device. %s.\n", strerror(errno)); return 0; } #else data.audiofd = fd = open(value(& rc, "device"), O_WRONLY); if(-1 == data.audiofd) { fprintf( stderr, "Couldn't open %s! %s.\n", value(& rc, "device"), strerror(errno) ); return 0; } arg = 16; /* 16 bits */ ioctl(data.audiofd, SOUND_PCM_WRITE_BITS, & arg); #endif freetrack = value(& track, "freeTrackURL"); if(haskey(& rc, "download")) { char * dnam; int rv; data.finpath = strdup(meta(value(& rc, "download"), M_RELAXPATH, & track)); assert(data.finpath != NULL); data.tmppath = strjoin("", data.finpath, ".streaming", NULL); assert(data.tmppath != NULL); dnam = strdup(data.tmppath); rv = dnam ? mkpath(dirname(dnam)) : -1; free(dnam); if(access(data.tmppath, R_OK) == -1) { data.dump = (rv == 0) ? fopen(data.tmppath, "w") : NULL; if(!data.dump) fprintf(stderr, "Can't write download to %s.\n", data.tmppath); } else { data.dump = NULL; } } mad_decoder_init(& dec, & data, input, NULL, NULL, output, NULL, NULL); mad_decoder_run(& dec, MAD_DECODER_MODE_SYNC); #ifndef LIBAO close(fd); #endif mad_decoder_finish(& dec); if(data.dump) { fclose(data.dump); if(killed) { unlink(data.tmppath); } else { int rv; #ifdef TAGLIB TagLib_File *tagme = taglib_file_new_type(data.tmppath, TagLib_File_MPEG); if(tagme != NULL) { TagLib_Tag *tag = taglib_file_tag(tagme); taglib_tag_set_title(tag, value(&track, "title")); taglib_tag_set_artist(tag, value(&track, "creator")); taglib_tag_set_album(tag, value(&track, "album")); taglib_file_save(tagme); taglib_file_free(tagme); } #endif if(haskey(& rc, "pp-cmd")) { const char *ppcmd = value(& rc, "pp-cmd"); size_t ppcmdlen = strlen(ppcmd); char *path = shellescape(data.tmppath); assert(path != NULL); size_t pathlen = strlen(path); char *command = malloc(ppcmdlen + pathlen + 2); assert(command != NULL); memcpy(command, ppcmd, ppcmdlen); command[ppcmdlen] = ' '; memcpy(command + ppcmdlen + 1, path, pathlen); command[ppcmdlen + 1 + pathlen] = 0; run(command); free(path); free(command); } rv = rename(data.tmppath, data.finpath); if (rv == -1) fprintf(stderr, "Can't rename %s to %s\n", data.tmppath, data.finpath); } free(data.tmppath); free(data.finpath); } } else #endif { pid_t ppid = getppid(), cpid = 0; const char * cmd = meta(value(& rc, "extern"), M_SHELLESC, & track); FILE * ext = openpipe(cmd, & cpid); unsigned char * buf; if(!ext) { fprintf(stderr, "Failed to execute external player (%s). %s.\n", cmd, strerror(errno)); return 0; } if(!(buf = calloc(BUFSIZE + 1, sizeof(unsigned char)))) { fputs("Couldn't allocate enough memory for input buffer.\n", stderr); fclose(ext); return 0; } while(!feof(streamfd)) { signed nbyte = fread(buf, sizeof(unsigned char), BUFSIZE, streamfd); if(nbyte > 0) { fwrite(buf, sizeof(unsigned char), nbyte, ext); fflush(ext); } if(kill(ppid, 0) == -1 && errno == ESRCH) break; if(killed) break; } free(buf); fclose(ext); waitpid(cpid, NULL, 0); } return !0; }
static int get_track_info(char *fullPath, mps_library_track_info_t *track_info) { int rv = MPS_LIBRARYDBD_SUCCESS; TagLib_File *tagLibFile; TagLib_Tag *tagLibTag; TagLib_File_Type tagLibType; mps_library_element_type_t mpsFileType; const TagLib_AudioProperties *tagLibProp; char *tmpString; MPS_DBG_PRINT("Entering %s(0x%08x)\n", __func__, (unsigned int) track_info); taglib_set_strings_unicode(true); mpsFileType = track_info->file_type; tagLibType = (mpsFileType==MPS_LIBRARY_MP3_FILE?TagLib_File_MPEG: mpsFileType==MPS_LIBRARY_FLAC_FILE?TagLib_File_FLAC: mpsFileType==MPS_LIBRARY_OGG_FILE?TagLib_File_OggVorbis: mpsFileType==MPS_LIBRARY_AAC_FILE?TagLib_File_MP4: mpsFileType==MPS_LIBRARY_APPLE_LOSSLESS_FILE?TagLib_File_MP4: mpsFileType==MPS_LIBRARY_WMA_FILE?TagLib_File_ASF: mpsFileType==MPS_LIBRARY_AIF_FILE?TagLib_File_AIFF: mpsFileType==MPS_LIBRARY_WAV_FILE?TagLib_File_WAV: 0); tagLibFile = taglib_file_new_type(fullPath, tagLibType); if(tagLibFile == NULL) { MPS_DBG_PRINT("Call to taglib_file_new(%s) failed.\n", fullPath); rv = MPS_LIBRARYDBD_FAILURE; goto ERR_OUT; } tagLibTag = taglib_file_tag(tagLibFile); tagLibProp = taglib_file_audioproperties(tagLibFile); /* TODO: need to go one step further to determine whether a file with an "m4a", etc. header is actually an apple lossless */ track_info->file_type = mpsFileType; tmpString = taglib_tag_title(tagLibTag); if (tmpString != NULL) { copy_string_without_edge_whitespace(track_info->title, tmpString, MPS_MAX_TRACK_INFO_FIELD_LENGTH); MPS_DBG_PRINT("Copied \"%s\" into track_title->title\n", track_info->title); } tmpString = taglib_tag_album(tagLibTag); if (tmpString != NULL) { copy_string_without_edge_whitespace(track_info->album, tmpString, MPS_MAX_TRACK_INFO_FIELD_LENGTH); MPS_DBG_PRINT("Copied \"%s\" into track_title->album\n", track_info->album); } tmpString = taglib_tag_artist(tagLibTag); if (tmpString != NULL) { copy_string_without_edge_whitespace(track_info->artist, tmpString, MPS_MAX_TRACK_INFO_FIELD_LENGTH); MPS_DBG_PRINT("Copied \"%s\" into track_title->artist\n", track_info->artist); } track_info->year = taglib_tag_year(tagLibTag); MPS_DBG_PRINT("Copied \"%d\" into track_title->year\n", track_info->year); tmpString = taglib_tag_genre(tagLibTag); if (tmpString != NULL) { copy_string_without_edge_whitespace(track_info->genre, tmpString, MPS_MAX_TRACK_INFO_FIELD_LENGTH); MPS_DBG_PRINT("Copied \"%s\" into track_title->genre\n", track_info->genre); } track_info->ordinal_track_number = taglib_tag_track(tagLibTag); MPS_DBG_PRINT("Copied \"%d\" into track_title->ordinal_track_number\n", track_info->ordinal_track_number); if (tagLibProp != NULL) { MPS_DBG_PRINT("Setting bitrate, etc.\n"); track_info->bitrate = taglib_audioproperties_bitrate(tagLibProp); track_info->sampling_rate = taglib_audioproperties_samplerate(tagLibProp); track_info->channel_mode = (taglib_audioproperties_channels(tagLibProp) < 2 ? MPS_CHANNEL_MODE_MONO: MPS_CHANNEL_MODE_STEREO); track_info->vbr_mode = MPS_VBR_MODE_UNKNOWN; track_info->time_length = taglib_audioproperties_length(tagLibProp); #if 0 track_info->channel_mode = ((finfo.mode==MPG123_M_STEREO)?MPS_CHANNEL_MODE_STEREO: ((finfo.mode==MPG123_M_JOINT)?MPS_CHANNEL_MODE_JOINT_STEREO: ((finfo.mode==MPG123_M_DUAL)?MPS_CHANNEL_MODE_DUAL_CHANNEL: ((finfo.mode==MPG123_M_MONO)?MPS_CHANNEL_MODE_MONO: MPS_CHANNEL_MODE_UNKNOWN)))); track_info->vbr_mode = ((finfo.vbr==MPG123_CBR)?MPS_VBR_MODE_CONSTANT: ((finfo.vbr==MPG123_VBR)?MPS_VBR_MODE_VARIABLE: ((finfo.vbr==MPG123_ABR)?MPS_VBR_MODE_AVERAGE: MPS_VBR_MODE_UNKNOWN))); if (track_info->sampling_rate > 0) { total_samples = mpg123_length_64(m); track_info->time_length = total_samples/track_info->sampling_rate; } #endif } else { MPS_LOG("taglib_file_audioproperties() returned NULL"); } ERR_OUT: taglib_tag_free_strings(); taglib_file_free(tagLibFile); MPS_DBG_PRINT("Leaving %s() - return value %d\n", __func__, rv); return rv; }
/* * Mp4_Tag_Read_File_Tag: * * Read tag data into an Mp4 file. * * Note: * - for string fields, //if field is found but contains no info (strlen(str)==0), we don't read it * - for track numbers, if they are zero, then we don't read it */ gboolean Mp4tag_Read_File_Tag (gchar *filename, File_Tag *FileTag) { FILE *file; TagLib_File *mp4file; TagLib_Tag *tag; guint track; if (!filename || !FileTag) return FALSE; if ( (file=fopen(filename,"r"))==NULL ) { gchar *filename_utf8 = filename_to_display(filename); Log_Print(LOG_ERROR,_("ERROR while opening file: '%s' (%s)."),filename_utf8,g_strerror(errno)); g_free(filename_utf8); return FALSE; } fclose(file); // We close it cause mp4 opens/closes file itself /* Get data from tag */ mp4file = taglib_file_new_type(filename,TagLib_File_MP4); if (mp4file == NULL) { gchar *filename_utf8 = filename_to_display(filename); Log_Print(LOG_ERROR,_("ERROR while opening file: '%s' (%s)."),filename_utf8,_("MP4 format invalid")); g_free(filename_utf8); return FALSE; } /* TODO Add error detection */ tag = taglib_file_tag(mp4file); /********* * Title * *********/ FileTag->title = g_strdup(taglib_tag_title(tag)); /********** * Artist * **********/ FileTag->artist = g_strdup(taglib_tag_artist(tag)); /********* * Album * *********/ FileTag->album = g_strdup(taglib_tag_album(tag)); /**************** * Album Artist * ****************/ /* TODO: No album artist or disc number support in the TagLib C API! */ /******** * Year * ********/ FileTag->year = g_strdup_printf("%u", taglib_tag_year(tag)); /************************* * Track and Total Track * *************************/ track = taglib_tag_track(tag); if (track != 0) FileTag->track = NUMBER_TRACK_FORMATED ? g_strdup_printf("%.*d",NUMBER_TRACK_FORMATED_SPIN_BUTTON,(gint)track) : g_strdup_printf("%d",(gint)track); /* TODO: No total track support in the TagLib C API! */ /********* * Genre * *********/ FileTag->genre = g_strdup(taglib_tag_genre(tag)); /*********** * Comment * ***********/ FileTag->comment = g_strdup(taglib_tag_comment(tag)); /********************** * Composer or Writer * **********************/ /* TODO: No composer support in the TagLib C API! */ /***************** * Encoding Tool * *****************/ /* TODO: No encode_by support in the TagLib C API! */ /*********** * Picture * ***********/ /* TODO: No encode_by support in the TagLib C API! */ /* Free allocated data */ taglib_tag_free_strings(); taglib_file_free(mp4file); return TRUE; }
/** * scan a musepack file for metainfo. * * @param filename file to read metainfo for * @param pmp3 MP3FILE structure to fill * @returns TRUE if file should be added to DB, FALSE otherwise */ int scan_get_mpcinfo(char *filename, MP3FILE *pmp3) { TagLib_File *file; TagLib_Tag *tag; const TagLib_AudioProperties *properties; char *val; int len; unsigned int i; /* open file with taglib */ if ((file = taglib_file_new_type(filename, TagLib_File_MPC)) == NULL) { DPRINTF(E_WARN,L_SCAN,"Could not open %s with taglib\n", filename); return FALSE; } /* retrieve all tags */ if ((tag = taglib_file_tag(file)) == NULL) { DPRINTF(E_WARN,L_SCAN,"Could not retrieve tags of %s\n", filename); taglib_file_free(file); return FALSE; } /* fill the MP3FILE structure with the tags */ if ((val = taglib_tag_title(tag)) != NULL) { len = strlen(val); if ((pmp3->title = calloc(len + 1, 1)) != NULL) strncpy(pmp3->title, val, len); taglib_tag_free_strings(); } if ((val = taglib_tag_artist(tag)) != NULL) { len = strlen(val); if ((pmp3->artist = calloc(len + 1, 1)) != NULL) strncpy(pmp3->artist, val, len); taglib_tag_free_strings(); } if ((val = taglib_tag_album(tag)) != NULL) { len = strlen(val); if ((pmp3->album = calloc(len + 1, 1)) != NULL) strncpy(pmp3->album, val, len); taglib_tag_free_strings(); } if ((val = taglib_tag_comment(tag)) != NULL) { len = strlen(val); if ((pmp3->comment = calloc(len + 1, 1)) != NULL) strncpy(pmp3->comment, val, len); taglib_tag_free_strings(); } if ((val = taglib_tag_genre(tag)) != NULL) { len = strlen(val); if ((pmp3->genre = calloc(len + 1, 1)) != NULL) strncpy(pmp3->genre, val, len); taglib_tag_free_strings(); } if ((i = taglib_tag_year(tag)) != 0) pmp3->year = i; if ((i = taglib_tag_track(tag)) != 0) pmp3->track = i; /* load the properties (like bitrate) from the file */ if ((properties = taglib_file_audioproperties(file)) == NULL) { DPRINTF(E_WARN,L_SCAN,"Could not retrieve properties of %s\n", filename); return FALSE; } /* fill the properties in the MP3FILE structure */ pmp3->song_length = taglib_audioproperties_length(properties) * 1000; pmp3->bitrate = taglib_audioproperties_bitrate(properties); pmp3->samplerate = taglib_audioproperties_samplerate(properties); taglib_file_free(file); return TRUE; }
/* * Mp4_Tag_Write_File_Tag: * * Write tag data into an Mp4 file. * * Note: * - for track numbers, we write 0's if one or the other is blank */ gboolean Mp4tag_Write_File_Tag (ET_File *ETFile) { File_Tag *FileTag; gchar *filename; gchar *filename_utf8; FILE *file; TagLib_File *mp4file = NULL; TagLib_Tag *tag; gint error = 0; if (!ETFile || !ETFile->FileTag) return FALSE; FileTag = (File_Tag *)ETFile->FileTag->data; filename = ((File_Name *)ETFile->FileNameCur->data)->value; filename_utf8 = ((File_Name *)ETFile->FileNameCur->data)->value_utf8; /* Test to know if we can write into the file */ if ( (file=fopen(filename,"r+"))==NULL ) { Log_Print(LOG_ERROR,_("ERROR while opening file: '%s' (%s)."),filename_utf8,g_strerror(errno)); return FALSE; } fclose(file); /* Open file for writing */ mp4file = taglib_file_new_type(filename, TagLib_File_MP4); if (mp4file == NULL) { Log_Print(LOG_ERROR,_("ERROR while opening file: '%s' (%s)."),filename_utf8,_("MP4 format invalid")); return FALSE; } tag = taglib_file_tag(mp4file); /********* * Title * *********/ if (FileTag->title && g_utf8_strlen(FileTag->title, -1) > 0) { taglib_tag_set_title(tag, FileTag->title); }else { taglib_tag_set_title(tag,""); } /********** * Artist * **********/ if (FileTag->artist && g_utf8_strlen(FileTag->artist, -1) > 0) { taglib_tag_set_artist(tag,FileTag->artist); }else { taglib_tag_set_artist(tag,""); } /********* * Album * *********/ if (FileTag->album && g_utf8_strlen(FileTag->album, -1) > 0) { taglib_tag_set_album(tag,FileTag->album); }else { taglib_tag_set_album(tag,""); } /******** * Year * ********/ if (FileTag->year && g_utf8_strlen(FileTag->year, -1) > 0) { taglib_tag_set_year(tag,atoi(FileTag->year)); }else { taglib_tag_set_year(tag,0); } /************************* * Track and Total Track * *************************/ if ( FileTag->track && g_utf8_strlen(FileTag->track, -1) > 0 ) { taglib_tag_set_track(tag,atoi(FileTag->track)); }else { taglib_tag_set_track(tag,0); } /********* * Genre * *********/ if (FileTag->genre && g_utf8_strlen(FileTag->genre, -1) > 0 ) { taglib_tag_set_genre(tag,FileTag->genre); }else { taglib_tag_set_genre(tag,""); } /*********** * Comment * ***********/ if (FileTag->comment && g_utf8_strlen(FileTag->comment, -1) > 0) { taglib_tag_set_comment(tag,FileTag->comment); }else { taglib_tag_set_comment(tag,""); } /********************** * Composer or Writer * **********************/ /***************** * Encoding Tool * *****************/ /*********** * Picture * ***********/ taglib_file_save(mp4file); taglib_file_free(mp4file); if (error) return FALSE; else return TRUE; }