File indexing completed on 2024-05-12 16:23:35
0001 /*************************************************************************** 0002 * Copyright (C) 2005-2008 by Bjoern Erik Nilsen & Fredrik Berg Kjoelstad* 0003 * bjoern.nilsen@bjoernen.com & fredrikbk@hotmail.com * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 * * 0010 * This program is distributed in the hope that it will be useful, * 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0013 * GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License * 0016 * along with this program; if not, write to the * 0017 * Free Software Foundation, Inc., * 0018 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 0019 ***************************************************************************/ 0020 #include "oggvorbis.h" 0021 0022 #include <assert.h> 0023 #include <stdio.h> 0024 #include <stdlib.h> 0025 #include <cerrno> 0026 #include <new> 0027 0028 #include <vorbis/codec.h> 0029 0030 #include "errorhandler.h" 0031 #include "workspacefile.h" 0032 #include "src/foundation/logger.h" 0033 #include "src/foundation/uiexception.h" 0034 0035 0036 class FileCloser { 0037 FILE* h; 0038 public: 0039 FileCloser(FILE* fh) : h(fh) { 0040 } 0041 FILE* release() { 0042 FILE* r = h; 0043 h = 0; 0044 return r; 0045 } 0046 ~FileCloser() { 0047 if (h) { 0048 fclose(h); 0049 } 0050 } 0051 }; 0052 0053 OggVorbis::OggVorbis() { 0054 oggFile = NULL; 0055 } 0056 0057 0058 OggVorbis::~OggVorbis() { 0059 close(); 0060 } 0061 0062 0063 void OggVorbis::setFilename(WorkspaceFile& file, ErrorHandler& e) { 0064 assert(file.path() != NULL); 0065 0066 // Opens the file and tests for vorbis-ness 0067 FILE *f = fopen(file.path(), "r"); 0068 FileCloser fcloser(f); 0069 if (f) { 0070 close(); 0071 oggFile = (OggVorbis_File*)malloc( sizeof(OggVorbis_File) ); 0072 if (oggFile == NULL) { 0073 throw std::bad_alloc(); 0074 } 0075 0076 if ( ov_test(f, oggFile, NULL, 0) < 0 ) { 0077 Logger::get().logDebug("Not a valid oggfile"); 0078 free(oggFile); 0079 oggFile = NULL; 0080 e.error( UiException(UiException::invalidAudioFormat) ); 0081 return; 0082 } 0083 // For some reason, ov_test does not necessarily take 0084 // ownership of our file handle. We must only release 0085 // ownership if oggFile has taken it. 0086 if (oggFile->datasource == f) 0087 fcloser.release(); 0088 this->filename.swap(file); 0089 } else { 0090 int err = errno; 0091 if (err == ENOMEM) { 0092 throw std::bad_alloc(); 0093 } 0094 Logger::get().logDebug("Cannot open file '%s' for reading", file.path()); 0095 e.error( UiException(UiException::couldNotOpenFile) ); 0096 } 0097 } 0098 0099 0100 int OggVorbis::open() { 0101 FILE *f = fopen(filename.path(), "r"); 0102 FileCloser fcloser(f); 0103 if (f) { 0104 close(); 0105 oggFile = (OggVorbis_File*)malloc( sizeof(OggVorbis_File) ); 0106 if (oggFile == NULL) { 0107 throw std::bad_alloc(); 0108 } 0109 if ( ov_open(f, oggFile, NULL, 0) == 0 ) { 0110 fcloser.release(); 0111 return 0; 0112 } 0113 free(oggFile); 0114 oggFile = NULL; 0115 } 0116 return -1; 0117 } 0118 0119 0120 void OggVorbis::reset() { 0121 if (oggFile) { 0122 ov_raw_seek(oggFile, 0); 0123 } 0124 } 0125 0126 0127 int OggVorbis::close() { 0128 if (oggFile) { 0129 ov_clear(oggFile); 0130 free(oggFile); 0131 oggFile = NULL; 0132 return 0; 0133 } 0134 return -1; 0135 } 0136 0137 0138 int OggVorbis::fillBuffer(char *audioBuffer, int numBytes) { 0139 assert(audioBuffer != NULL); 0140 if (oggFile) { 0141 int dummy; 0142 int ret = ov_read(oggFile, audioBuffer, numBytes, 0143 littleEndian, wordsAre16Bit, wordsAreSigned, &dummy); 0144 if (ret < 0) { 0145 Logger logger = Logger::get(); 0146 switch (ret) { 0147 case OV_HOLE: 0148 logger.logWarning("Hole in the vorbis audio data"); 0149 break; 0150 case OV_EBADLINK: 0151 logger.logWarning("Invalid link or stream section in vorbis audio data"); 0152 break; 0153 case OV_EINVAL: 0154 logger.logWarning("Corrupt initial headers for vorbis audio data"); 0155 break; 0156 default: 0157 logger.logWarning("Unknown error in vorbis audio data"); 0158 break; 0159 } 0160 return 0; 0161 } 0162 return ret; 0163 } 0164 return 0; 0165 } 0166 0167 0168 int OggVorbis::add16bit(int16_t* audioBuffer, int) { 0169 assert(audioBuffer); 0170 return 0; 0171 } 0172 0173 0174 const char* OggVorbis::getSoundPath() const { 0175 return filename.path(); 0176 } 0177 0178 const char* OggVorbis::getBasename() const { 0179 return filename.basename(); 0180 } 0181