1 /* 2 3 Boost Software License - Version 1.0 - August 17th, 2003 4 5 Permission is hereby granted, free of charge, to any person or organization 6 obtaining a copy of the software and accompanying documentation covered by 7 this license (the "Software") to use, reproduce, display, distribute, 8 execute, and transmit the Software, and to prepare derivative works of the 9 Software, and to permit third-parties to whom the Software is furnished to 10 do so, all subject to the following: 11 12 The copyright notices in the Software and this entire statement, including 13 the above license grant, this restriction and the following disclaimer, 14 must be included in all copies of the Software, in whole or in part, and 15 all derivative works of the Software, unless such copies or derivative 16 works are solely in the form of machine-executable object code generated by 17 a source language processor. 18 19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 22 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 23 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 24 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 DEALINGS IN THE SOFTWARE. 26 27 */ 28 module derelict.vorbis.file; 29 30 private { 31 import core.stdc.config; 32 import std.stdio; 33 import derelict.util.loader; 34 import derelict.util.system; 35 import derelict.ogg.ogg; 36 import derelict.vorbis.codec; 37 38 static if(Derelict_OS_Windows) 39 enum libNames = "vorbisfile.dll, libvorbisfile-3.dll, libvorbisfile.dll"; 40 else static if(Derelict_OS_Mac) 41 enum libNames = "libvorbisfile.dylib, libvorbisfile.0.dylib"; 42 else static if(Derelict_OS_Posix) 43 enum libNames = "libvorbisfile.so, libvorbisfile.so.3, libvorbisfile.so.3.1.0"; 44 else 45 static assert(0, "Need to implement libvorbisfile libnames for this operating system."); 46 } 47 48 struct ov_callbacks { 49 extern(C) nothrow { 50 size_t function(void*, size_t, size_t, void*) read_func; 51 int function(void*, ogg_int64_t, int) seek_func; 52 int function(void*) close_func; 53 c_long function(void*) tell_func; 54 } 55 } 56 57 enum { 58 NOTOPEN =0, 59 PARTOPEN =1, 60 OPENED =2, 61 STREAMSET =3, 62 INITSET =4, 63 } 64 65 struct OggVorbis_File { 66 void* datasource; 67 int seekable; 68 ogg_int64_t offset; 69 ogg_int64_t end; 70 ogg_sync_state oy; 71 int links; 72 ogg_int64_t* offsets; 73 ogg_int64_t* dataoffsets; 74 c_long* serialnos; 75 ogg_int64_t* pcmlengths; 76 vorbis_info* vi; 77 vorbis_comment* vc; 78 ogg_int64_t pcm_offset; 79 int ready_state; 80 c_long current_serialno; 81 int current_link; 82 double bittrack; 83 double samptrack; 84 ogg_stream_state os; 85 vorbis_dsp_state vd; 86 vorbis_block vb; 87 ov_callbacks callbacks; 88 } 89 90 extern(C) @nogc nothrow { 91 alias da_ov_clear = int function(OggVorbis_File*); 92 alias da_ov_fopen = int function(const(char)*, OggVorbis_File*); 93 alias da_ov_open_callbacks = int function(void* datasource, OggVorbis_File*, const(char)*, c_long, ov_callbacks); 94 alias da_ov_test_callbacks = int function(void*, OggVorbis_File*, const(char)*, c_long, ov_callbacks); 95 alias da_ov_test_open = int function(OggVorbis_File*); 96 alias da_ov_bitrate = c_long function(OggVorbis_File*, int); 97 alias da_ov_bitrate_instant = c_long function(OggVorbis_File*); 98 alias da_ov_streams = c_long function(OggVorbis_File*); 99 alias da_ov_seekable = c_long function(OggVorbis_File*); 100 alias da_ov_serialnumber = c_long function(OggVorbis_File*, int); 101 alias da_ov_raw_total = ogg_int64_t function(OggVorbis_File*, int); 102 alias da_ov_pcm_total = ogg_int64_t function(OggVorbis_File*, int); 103 alias da_ov_time_total = double function(OggVorbis_File*, int); 104 alias da_ov_raw_seek = int function(OggVorbis_File*, ogg_int64_t); 105 alias da_ov_pcm_seek = int function(OggVorbis_File*, ogg_int64_t); 106 alias da_ov_pcm_seek_page = int function(OggVorbis_File*, ogg_int64_t); 107 alias da_ov_time_seek = int function(OggVorbis_File*, double); 108 alias da_ov_time_seek_page = int function(OggVorbis_File*, double); 109 alias da_ov_raw_seek_lap = int function(OggVorbis_File*, ogg_int64_t); 110 alias da_ov_pcm_seek_lap = int function(OggVorbis_File*, ogg_int64_t); 111 alias da_ov_pcm_seek_page_lap = int function(OggVorbis_File*, ogg_int64_t); 112 alias da_ov_time_seek_lap = int function(OggVorbis_File*, double); 113 alias da_ov_time_seek_page_lap = int function(OggVorbis_File*, double); 114 alias da_ov_raw_tell = ogg_int64_t function(OggVorbis_File*); 115 alias da_ov_pcm_tell = ogg_int64_t function(OggVorbis_File*); 116 alias da_ov_time_tell = double function(OggVorbis_File*); 117 alias da_ov_info = vorbis_info* function(OggVorbis_File*, int); 118 alias da_ov_comment = vorbis_comment* function(OggVorbis_File*, int); 119 alias da_ov_read_float = c_long function(OggVorbis_File*, float***, int, int*); 120 alias da_ov_read = c_long function(OggVorbis_File*, byte*, int, int, int, int, int*); 121 alias da_ov_crosslap = int function(OggVorbis_File*, OggVorbis_File*); 122 alias da_ov_halfrate = int function(OggVorbis_File*, int); 123 alias da_ov_halfrate_p = int function(OggVorbis_File*); 124 } 125 126 private extern (C) nothrow { 127 size_t Derelict_VorbisRead(void* ptr, size_t byteSize, size_t sizeToRead, void* datasource) { 128 return fread(ptr, byteSize, sizeToRead, cast(FILE*)datasource); 129 } 130 131 int Derelict_VorbisSeek(void* datasource, ogg_int64_t offset, int whence) { 132 return fseek(cast(FILE*)datasource, cast(int)offset, whence); 133 } 134 135 int Derelict_VorbisClose(void* datasource) { 136 return fclose(cast(FILE*)datasource); 137 } 138 139 c_long Derelict_VorbisTell(void* datasource) { 140 return cast(c_long)ftell(cast(FILE*)datasource); 141 } 142 } 143 144 // ov_open is rewritten below because of incompatibility between compilers with FILE struct 145 // Using this wrapper, it *should* work exactly as it would in c++. --JoeCoder 146 int ov_open(FILE* f, OggVorbis_File* vf, const(char)* initial, c_long ibytes) 147 { 148 // Fill the ov_callbacks structure 149 ov_callbacks vorbisCallbacks; // Structure to hold pointers to callback functions 150 vorbisCallbacks.read_func = &Derelict_VorbisRead; 151 vorbisCallbacks.close_func = &Derelict_VorbisClose; 152 vorbisCallbacks.seek_func = &Derelict_VorbisSeek; 153 vorbisCallbacks.tell_func = &Derelict_VorbisTell; 154 155 return ov_open_callbacks(cast(void*)f, vf, initial, cast(int)ibytes, vorbisCallbacks); 156 } 157 158 // ditto for ov_test 159 int ov_test(FILE* f, OggVorbis_File* vf, const(char)* initial, c_long ibytes) 160 { 161 // Fill the ov_callbacks structure 162 ov_callbacks vorbisCallbacks; // Structure to hold pointers to callback functions 163 vorbisCallbacks.read_func = &Derelict_VorbisRead; 164 vorbisCallbacks.close_func = &Derelict_VorbisClose; 165 vorbisCallbacks.seek_func = &Derelict_VorbisSeek; 166 vorbisCallbacks.tell_func = &Derelict_VorbisTell; 167 168 return ov_test_callbacks(cast(void*)f, vf, initial, cast(int)ibytes, vorbisCallbacks); 169 } 170 171 __gshared { 172 da_ov_clear ov_clear; 173 da_ov_fopen ov_fopen; 174 da_ov_open_callbacks ov_open_callbacks; 175 da_ov_test_callbacks ov_test_callbacks; 176 da_ov_test_open ov_test_open; 177 da_ov_bitrate ov_bitrate; 178 da_ov_bitrate_instant ov_bitrate_instant; 179 da_ov_streams ov_streams; 180 da_ov_seekable ov_seekable; 181 da_ov_serialnumber ov_serialnumber; 182 da_ov_raw_total ov_raw_total; 183 da_ov_pcm_total ov_pcm_total; 184 da_ov_time_total ov_time_total; 185 da_ov_raw_seek ov_raw_seek; 186 da_ov_pcm_seek ov_pcm_seek; 187 da_ov_pcm_seek_page ov_pcm_seek_page; 188 da_ov_time_seek ov_time_seek; 189 da_ov_time_seek_page ov_time_seek_page; 190 da_ov_raw_seek_lap ov_raw_seek_lap; 191 da_ov_pcm_seek_lap ov_pcm_seek_lap; 192 da_ov_pcm_seek_page_lap ov_pcm_seek_page_lap; 193 da_ov_time_seek_lap ov_time_seek_lap; 194 da_ov_time_seek_page_lap ov_time_seek_page_lap; 195 da_ov_raw_tell ov_raw_tell; 196 da_ov_pcm_tell ov_pcm_tell; 197 da_ov_time_tell ov_time_tell; 198 da_ov_info ov_info; 199 da_ov_comment ov_comment; 200 da_ov_read_float ov_read_float; 201 da_ov_read ov_read; 202 da_ov_crosslap ov_crosslap; 203 da_ov_halfrate ov_halfrate; 204 da_ov_halfrate_p ov_halfrate_p; 205 } 206 207 class DerelictVorbisFileLoader : SharedLibLoader { 208 public this() { 209 super(libNames); 210 } 211 212 protected override void loadSymbols() { 213 bindFunc(cast(void**)&ov_clear, "ov_clear"); 214 bindFunc(cast(void**)&ov_fopen, "ov_fopen"); 215 bindFunc(cast(void**)&ov_open_callbacks, "ov_open_callbacks"); 216 bindFunc(cast(void**)&ov_test_callbacks, "ov_test_callbacks"); 217 bindFunc(cast(void**)&ov_test_open, "ov_test_open"); 218 bindFunc(cast(void**)&ov_bitrate, "ov_bitrate"); 219 bindFunc(cast(void**)&ov_bitrate_instant, "ov_bitrate_instant"); 220 bindFunc(cast(void**)&ov_streams, "ov_streams"); 221 bindFunc(cast(void**)&ov_seekable, "ov_seekable"); 222 bindFunc(cast(void**)&ov_serialnumber, "ov_serialnumber"); 223 bindFunc(cast(void**)&ov_raw_total, "ov_raw_total"); 224 bindFunc(cast(void**)&ov_pcm_total, "ov_pcm_total"); 225 bindFunc(cast(void**)&ov_time_total, "ov_time_total"); 226 bindFunc(cast(void**)&ov_raw_seek, "ov_raw_seek"); 227 bindFunc(cast(void**)&ov_pcm_seek, "ov_pcm_seek"); 228 bindFunc(cast(void**)&ov_pcm_seek_page, "ov_pcm_seek_page"); 229 bindFunc(cast(void**)&ov_time_seek, "ov_time_seek"); 230 bindFunc(cast(void**)&ov_time_seek_page, "ov_time_seek_page"); 231 bindFunc(cast(void**)&ov_raw_seek_lap, "ov_raw_seek_lap"); 232 bindFunc(cast(void**)&ov_pcm_seek_lap, "ov_pcm_seek_lap"); 233 bindFunc(cast(void**)&ov_pcm_seek_page_lap, "ov_pcm_seek_page_lap"); 234 bindFunc(cast(void**)&ov_time_seek_lap, "ov_time_seek_lap"); 235 bindFunc(cast(void**)&ov_time_seek_page_lap, "ov_time_seek_page_lap"); 236 bindFunc(cast(void**)&ov_raw_tell, "ov_raw_tell"); 237 bindFunc(cast(void**)&ov_pcm_tell, "ov_pcm_tell"); 238 bindFunc(cast(void**)&ov_time_tell, "ov_time_tell"); 239 bindFunc(cast(void**)&ov_info, "ov_info"); 240 bindFunc(cast(void**)&ov_comment, "ov_comment"); 241 bindFunc(cast(void**)&ov_read_float, "ov_read_float"); 242 bindFunc(cast(void**)&ov_read, "ov_read"); 243 bindFunc(cast(void**)&ov_crosslap, "ov_crosslap"); 244 bindFunc(cast(void**)&ov_halfrate, "ov_halfrate"); 245 bindFunc(cast(void**)&ov_halfrate_p, "ov_halfrate_p"); 246 } 247 } 248 249 __gshared DerelictVorbisFileLoader DerelictVorbisFile; 250 251 shared static this() { 252 DerelictVorbisFile = new DerelictVorbisFileLoader(); 253 }