|
CLAM-Development
1.3
|
00001 /* 00002 * Copyright (c) 2004 MUSIC TECHNOLOGY GROUP (MTG) 00003 * UNIVERSITAT POMPEU FABRA 00004 * 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00019 * 00020 */ 00021 00022 #if USE_OGGVORBIS != 1 00023 #error USE_OGGVORBIS was not set to 1 in your settings.cfg file, but you are including files that require this. Please fix your settings.cfg 00024 #endif 00025 00026 #include <cstdio> 00027 #include <cstring> 00028 #include <string> 00029 #include <algorithm> 00030 #include <vorbis/vorbisfile.h> 00031 #include <iostream> 00032 #include "AudioFileFormats.hxx" 00033 #include "AudioFile.hxx" 00034 #include "OggVorbisCodec.hxx" 00035 #include "OggVorbisAudioStream.hxx" 00036 00037 namespace CLAM 00038 { 00039 00040 namespace AudioCodecs 00041 { 00042 OggVorbisCodec::OggVorbisCodec() 00043 { 00044 } 00045 00046 OggVorbisCodec::~OggVorbisCodec() 00047 { 00048 } 00049 00050 OggVorbisCodec& OggVorbisCodec::Instantiate() 00051 { 00052 static OggVorbisCodec theInstance; 00053 00054 return theInstance; 00055 } 00056 00057 bool OggVorbisCodec::IsReadable( std::string uri ) const 00058 { 00059 FILE* fileHandle; 00060 OggVorbis_File vorbisFile; 00061 00062 memset( &vorbisFile, 0, sizeof(OggVorbis_File) ); 00063 00064 fileHandle = fopen( uri.c_str(), "rb" ); 00065 00066 if ( !fileHandle || ferror(fileHandle) != 0 ) 00067 { 00068 //:TODO: possible exception throwing 00069 //std::cerr << uri << std::endl; 00070 //std::cerr << "Open failed! " << strerror( errno ) << std::endl; 00071 return false; 00072 } 00073 00074 int retval = ov_open( fileHandle, &vorbisFile, NULL, 0 ); 00075 00076 if ( retval < 0 ) 00077 { 00078 fclose( fileHandle ); 00079 00080 return false; 00081 } 00082 00083 // MRJ: No need to close the fileHandle since libvorbisfile takes 00084 // its ownership if the ov_open call is successful 00085 ov_clear( &vorbisFile ); 00086 00087 return true; 00088 00089 } 00090 00091 bool OggVorbisCodec::IsWritable( std::string uri, const AudioFileHeader& hdr ) const 00092 { 00093 // MRJ: These values were documented ( sort of ) in 00094 // the Vorbis I specification document 00095 00096 if ( (hdr.GetChannels() < 0) || ( hdr.GetChannels() > 255) ) 00097 return false; 00098 if ( (hdr.GetSampleRate() < 8000.) || ( hdr.GetSampleRate() > 192000.) ) 00099 return false; 00100 00101 return true; 00102 } 00103 00104 Stream* OggVorbisCodec::GetStreamFor( const AudioFile& file ) 00105 { 00106 return new OggVorbisAudioStream(file); 00107 } 00108 00109 void OggVorbisCodec::RetrieveHeaderData( std::string uri, AudioFileHeader& hdr ) 00110 { 00111 FILE* fileHandle; 00112 OggVorbis_File vorbisFile; 00113 00114 if ( ( fileHandle = fopen( uri.c_str(), "rb" ) ) == NULL ) 00115 return; 00116 00117 if ( ov_open( fileHandle, &vorbisFile, NULL, 0 ) < 0 ) 00118 { 00119 fclose( fileHandle ); 00120 return; 00121 } 00122 00123 vorbis_info* fileInfo = ov_info( &vorbisFile, -1 ); 00124 00125 if ( !fileInfo ) // File was encoded improperly 00126 return; 00127 00128 hdr.AddSampleRate(); 00129 hdr.AddChannels(); 00130 hdr.AddSamples(); 00131 hdr.AddFormat(); 00132 hdr.AddEncoding(); 00133 hdr.AddEndianess(); 00134 hdr.AddLength(); 00135 hdr.UpdateData(); 00136 00137 hdr.SetSampleRate( (TData)fileInfo->rate ); 00138 hdr.SetChannels( (TSize)fileInfo->channels ); 00139 hdr.SetLength( (TTime)ov_time_total( &vorbisFile, -1) * 1000. ); 00140 hdr.SetFormat( EAudioFileFormat::eVorbisMk1 ); 00141 hdr.SetEncoding( EAudioFileEncoding::eDefault ); 00142 hdr.SetEndianess( EAudioFileEndianess::eDefault ); 00143 00144 double duration = hdr.GetLength()/1000.; 00145 hdr.SetSamples( TSize(duration*hdr.GetSampleRate()) ); 00146 00147 // MRJ: No need to close the fileHandle since libvorbisfile takes 00148 // its ownership if the ov_open call is successful 00149 ov_clear( &vorbisFile ); 00150 } 00151 00152 void OggVorbisCodec::RetrieveTextDescriptors( std::string uri, AudioTextDescriptors& txtDesc ) 00153 { 00154 FILE* fileHandle; 00155 OggVorbis_File vorbisFile; 00156 00157 if ( ( fileHandle = fopen( uri.c_str(), "rb" ) ) == NULL ) 00158 return; 00159 00160 if ( ov_open( fileHandle, &vorbisFile, NULL, 0 ) < 0 ) 00161 { 00162 fclose( fileHandle ); 00163 return; 00164 } 00165 00166 vorbis_info* fileInfo = ov_info( &vorbisFile, -1 ); 00167 00168 if ( !fileInfo ) // File was encoded improperly 00169 return; 00170 00171 00172 vorbis_comment* fileComments = ov_comment( &vorbisFile, -1 ); 00173 00174 if ( !fileComments ) // there were no comments in the file! 00175 { 00176 return; 00177 } 00178 00179 int nComments = fileComments->comments; 00180 char** commentVector = fileComments->user_comments; 00181 int* commentLenVector = fileComments->comment_lengths; 00182 00183 for ( int i = 0; i < nComments; i++ ) 00184 { 00185 // convert the current comment string into a std::string 00186 std::string currentComment; 00187 currentComment.assign( commentVector[i], 00188 commentVector[i]+commentLenVector[i] ); 00189 00190 std::string::iterator eqPos = std::find( currentComment.begin(), 00191 currentComment.end(), '=' ); 00192 00193 if ( eqPos < currentComment.end() ) 00194 { 00195 std::string fieldName; 00196 fieldName.assign( currentComment.begin(), eqPos ); 00197 00198 if( fieldName == "ARTIST" ) 00199 { 00200 txtDesc.AddArtist(); 00201 txtDesc.UpdateData(); 00202 txtDesc.GetArtist().assign( eqPos+1, currentComment.end() ); 00203 } 00204 else if ( fieldName == "TITLE" ) 00205 { 00206 txtDesc.AddTitle(); 00207 txtDesc.UpdateData(); 00208 txtDesc.GetTitle().assign( eqPos+1, currentComment.end() ); 00209 } 00210 else if ( fieldName == "ALBUM" ) 00211 { 00212 txtDesc.AddAlbum(); 00213 txtDesc.UpdateData(); 00214 txtDesc.GetAlbum().assign( eqPos+1, currentComment.end() ); 00215 } 00216 else if ( fieldName == "TRACKNUMBER" ) 00217 { 00218 txtDesc.AddTrackNumber(); 00219 txtDesc.UpdateData(); 00220 txtDesc.GetTrackNumber().assign( eqPos+1, currentComment.end() ); 00221 } 00222 else if ( fieldName == "PERFORMER" ) 00223 { 00224 txtDesc.AddPerformer(); 00225 txtDesc.UpdateData(); 00226 txtDesc.GetPerformer().assign( eqPos+1, currentComment.end() ); 00227 } 00228 else if ( fieldName == "COMPOSER" ) 00229 { 00230 txtDesc.AddComposer(); 00231 txtDesc.UpdateData(); 00232 txtDesc.GetComposer().assign( eqPos+1, currentComment.end() ); 00233 } 00234 else 00235 { 00236 std::string msg = fieldName; 00237 msg+= ": Ignored comment field!"; 00238 //CLAM_WARNING( false, msg.c_str() ); 00239 } 00240 } 00241 00242 } 00243 00244 ov_clear( &vorbisFile ); 00245 } 00246 } 00247 00248 } 00249
1.7.6.1