├── .gitignore ├── COPYING ├── MANIFEST ├── Makefile ├── README ├── examples ├── encoder.py ├── flac123.py ├── metaflac.py └── tagedit.py ├── flac ├── __init__.py ├── decoder.i ├── encoder.i ├── format.i ├── metadata.py └── sw_metadata.i └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | flac/*.c 3 | flac/decoder.py 4 | flac/encoder.py 5 | flac/format.py 6 | flac/sw_metadata.py 7 | 8 | # Vim 9 | *.swp 10 | *.swo 11 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 309 | 310 | 311 | Also add information on how to contact you by electronic and paper mail. 312 | 313 | If the program is interactive, make it output a short notice like this 314 | when it starts in an interactive mode: 315 | 316 | Gnomovision version 69, Copyright (C) year name of author 317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 318 | This is free software, and you are welcome to redistribute it 319 | under certain conditions; type `show c' for details. 320 | 321 | The hypothetical commands `show w' and `show c' should show the appropriate 322 | parts of the General Public License. Of course, the commands you use may 323 | be called something other than `show w' and `show c'; they could even be 324 | mouse-clicks or menu items--whatever suits your program. 325 | 326 | You should also get your employer (if you work as a programmer) or your 327 | school, if any, to sign a "copyright disclaimer" for the program, if 328 | necessary. Here is a sample; alter the names: 329 | 330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 331 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 332 | 333 | , 1 April 1989 334 | Ty Coon, President of Vice 335 | 336 | This General Public License does not permit incorporating your program into 337 | proprietary programs. If your program is a subroutine library, you may 338 | consider it more useful to permit linking proprietary applications with the 339 | library. If this is what you want to do, use the GNU Library General 340 | Public License instead of this License. 341 | -------------------------------------------------------------------------------- /MANIFEST: -------------------------------------------------------------------------------- 1 | COPYING 2 | README 3 | Makefile 4 | examples/encoder.py 5 | examples/flac123.py 6 | examples/metaflac.py 7 | examples/tagedit.py 8 | setup.py 9 | flac/__init__.py 10 | flac/metadata.py 11 | flac/decoder.i 12 | flac/encoder.i 13 | flac/format.i 14 | flac/sw_metadata.i 15 | flac/decoder_wrap.c 16 | flac/encoder_wrap.c 17 | flac/sw_metadata_wrap.c 18 | flac/decoder.py 19 | flac/encoder.py 20 | flac/sw_metadata.py 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: build 2 | 3 | build: flac/sw_metadata_wrap.c flac/decoder_wrap.c flac/encoder_wrap.c 4 | ./setup.py build 5 | 6 | %_wrap.c: %.i flac/format.i 7 | swig -python -Wall $< 8 | 9 | clean: 10 | rm -f flac/*_wrap.c 11 | rm -f flac/sw_metadata.py flac/decoder.py flac/encoder.py 12 | rm -rf build dist pyflac.egg-info 13 | 14 | distclean: clean 15 | rm -f */*~ *~ */*.pyc 16 | 17 | install: 18 | ./setup.py install 19 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | pyflac - FLAC in Python 2 | ----------------------- 3 | This is a simple wrapper for some of libFLAC, namely the file decoder, file 4 | encoder, and metadata interfaces. Most of the functions of these interfaces 5 | are working. 6 | 7 | The wrappers are mostly generated by SWIG. Using them should be intuitive 8 | for those already familiar with the C FLAC interfaces (n.b. where the 9 | FLAC documentation uses 64 bit integers you should use a Python long). 10 | Fairly complete sample code testing most of the functionality can be 11 | found in the examples directory. 12 | 13 | Building / Installation: 14 | ------------------------ 15 | To build pyflac you must have the SWIG, libFLAC (>= 1.1.3), and Python 16 | development files installed (these are swig1.3, python-dev, and libflac-dev on 17 | Debian systems). 18 | 19 | Some of the examples also require python-pyao. 20 | 21 | $ make && make install 22 | 23 | Have fun, please report any bugs or incomplete features. 24 | 25 | Contact: 26 | -------- 27 | Dan Sully maintains (this version of) pyflac, as both Joe & David have abanonded it. 28 | 29 | Now hosted on GitHub. Pull requests welcome! 30 | 31 | ----------------------------------------------------------------------- 32 | Joe Wreschnig maintains (this version of) pyflac, 33 | being unable to contact David anymore. 34 | 35 | David Collett is the original author of 36 | pyflac but his email address now bounces and his pyflac download 37 | disappeared. 38 | -------------------------------------------------------------------------------- /examples/encoder.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import flac.encoder as encoder 4 | import flac.metadata as metadata 5 | import wave 6 | import sys 7 | 8 | oldprog = 0 9 | 10 | # progress callback 11 | def progress(enc, bytes_written, samples_written, frames_written, total_frames_estimate): 12 | global oldprog 13 | prog = int((float(frames_written)/float(total_frames_estimate)) * 100) 14 | if prog != oldprog or prog == 0: 15 | sys.stdout.write('\b\b\b\b\b\b\b\b\b\b\b\b\b') 16 | sys.stdout.write("%3d%% Complete" % prog) 17 | sys.stdout.flush() 18 | oldprog = prog 19 | 20 | infile = sys.argv[1] 21 | outfile = sys.argv[1] + '.flac' 22 | 23 | wav = wave.open(infile, 'rb') 24 | 25 | # setup the encoder ... 26 | enc = encoder.StreamEncoder() 27 | enc.set_channels(wav.getnchannels()) 28 | enc.set_bits_per_sample(wav.getsampwidth()*8) 29 | enc.set_sample_rate(wav.getframerate()) 30 | enc.set_blocksize(4608) 31 | enc.set_do_mid_side_stereo(True) 32 | enc.set_total_samples_estimate(wav.getnframes()) 33 | 34 | # create a vorbis block 35 | vorbis = metadata.VorbisComment() 36 | vorbis.vendor_string = 'python-flac' # reset to default anyway I think... 37 | vorbis.comments['TITLE'] = "My Title" 38 | vorbis.comments['ARTIST'] = 'Me' 39 | 40 | # a seektable with 100 points 41 | seektbl = metadata.SeekTable() 42 | seektbl.template_append_spaced_points(100, enc.get_total_samples_estimate()) 43 | seektbl.template_sort(True) 44 | 45 | # add the metadata blocks 46 | enc.set_metadata((seektbl.block, vorbis.block), 2) 47 | 48 | # initialise 49 | if enc.init_file(outfile, progress) != encoder.FLAC__STREAM_ENCODER_OK: 50 | print "Error" 51 | sys.exit() 52 | 53 | # start encoding ! 54 | nsamples = 1024 55 | while 1: 56 | data = wav.readframes(nsamples) 57 | if not data: 58 | enc.finish() 59 | break 60 | enc.process(data, nsamples) 61 | -------------------------------------------------------------------------------- /examples/flac123.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Very simple FLAC player using the FLAC FileDecoder and libao 4 | 5 | import flac.decoder as decoder 6 | import flac.metadata as metadata 7 | import ao 8 | import sys 9 | 10 | # setup libao audio device 11 | #ao = ao.AudioDevice('esd') 12 | #ao = ao.AudioDevice('alsa09') 13 | #ao = ao.AudioDevice('wav', filename='out.wav') 14 | ao = ao.AudioDevice('oss') 15 | 16 | # write our callbacks (in Python!!) 17 | def metadata_callback(dec, block): 18 | if block.type == metadata.VORBIS_COMMENT: 19 | # use flac.metadata to access vorbis comments! 20 | vc = metadata.VorbisComment(block) 21 | print vc.vendor_string 22 | for k in vc.comments: 23 | print '%s=%s' % (k, vc.comments[k]) 24 | 25 | def error_callback(dec, status): 26 | pass 27 | 28 | def write_callback(dec, buff, size): 29 | # print dec.get_decode_position() 30 | ao.play(buff, size) 31 | return decoder.FLAC__STREAM_DECODER_OK 32 | 33 | if len(sys.argv) < 2: 34 | sys.exit("Usage: %s " % sys.argv[0]) 35 | 36 | # create a new file decoder 37 | mydec = decoder.StreamDecoder() 38 | 39 | # set some properties 40 | mydec.set_md5_checking(False); 41 | mydec.set_metadata_respond_all() 42 | 43 | # initialise, process metadata 44 | mydec.init(sys.argv[1], write_callback, metadata_callback, error_callback) 45 | mydec.process_until_end_of_metadata() 46 | 47 | # print out some stats, have to decode some data first 48 | mydec.process_single() 49 | print 'Channels: %d' % mydec.get_channels() 50 | print 'Bits Per Sample: %d' % mydec.get_bits_per_sample() 51 | print 'Sample Rate: %d' % mydec.get_sample_rate() 52 | print 'BlockSize: %d' % mydec.get_blocksize() 53 | 54 | # play the rest of the stream 55 | mydec.process_until_end_of_stream() 56 | 57 | # cleanup 58 | mydec.finish() 59 | -------------------------------------------------------------------------------- /examples/metaflac.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Example of using the flac.metadata python bindings. 3 | # It is designed to me somewhat like the 'metaflac' command. 4 | 5 | import sys 6 | import flac.metadata as metadata 7 | 8 | try: 9 | fname = sys.argv[1] 10 | except IndexError: 11 | sys.exit("Please provide a FLAC filename.") 12 | 13 | # create a chain 14 | chain = metadata.Chain() 15 | chain.read(fname) 16 | 17 | # get iterator, initialise 18 | it = metadata.Iterator() 19 | it.init(chain) 20 | 21 | cur_block = 0; 22 | while 1: 23 | block = it.get_block() 24 | # print some common fields 25 | print 'METADATA BLOCK #%d' % cur_block 26 | print ' type: %d (%s)' % (block.type, metadata.TypeString(block.type)) 27 | print ' is_last: %d' % block.is_last 28 | print ' length: %d' % block.length 29 | cur_block += 1 30 | 31 | if block.type == metadata.STREAMINFO: 32 | # print STREAMINFO fields 33 | streaminfo = block.data.stream_info 34 | print ' minimum blocksize: %d' % streaminfo.min_blocksize 35 | print ' maximum blocksize: %d' % streaminfo.max_blocksize 36 | print ' minimum framesize: %d' % streaminfo.min_framesize 37 | print ' maximum framesize: %d' % streaminfo.max_framesize 38 | print ' sample_rate: %d' % streaminfo.sample_rate 39 | print ' channels: %d' % streaminfo.channels 40 | print ' bits-per-sample: %d' % streaminfo.bits_per_sample 41 | print ' total samples: %d' % streaminfo.total_samples 42 | #print ' md5sum: %s' % streaminfo.md5sum 43 | 44 | elif block.type == metadata.SEEKTABLE: 45 | # print SEEKTABLE fields 46 | seektable = block.data.seek_table 47 | print ' seek points: %d' % seektable.num_points 48 | for i in range(seektable.num_points): 49 | pt = seektable.points[i] 50 | print ' point %d: sample_number=%d, stream_offset=%d, frame_samples=%d' % (i, pt.sample_number, pt.stream_offset, pt.frame_samples) 51 | 52 | elif block.type == metadata.CUESHEET: 53 | # print CUESHEET 54 | cuesheet = block.data.cue_sheet 55 | print ' media catalog number: %s' % cuesheet.media_catalog_number 56 | print ' lead-in: %d' % cuesheet.lead_in 57 | print ' is CD: %d' % cuesheet.is_cd 58 | print ' number of tracks: %d' % cuesheet.num_tracks 59 | for i in range(cuesheet.num_tracks): 60 | tr = cuesheet.tracks[i] 61 | print ' track[%d]' % i 62 | print ' offset: %d' % tr.offset 63 | print ' number: %d' % ord(tr.number) 64 | print ' ISRC: %s' % tr.isrc 65 | if tr.type == 0: 66 | print ' type: AUDIO' 67 | else: 68 | print ' type: NON-AUDIO' 69 | if tr.pre_emphasis == 1: 70 | print ' pre-emphasis: true' 71 | else: 72 | print ' pre-emphasis: false' 73 | print ' number of index points: %d' % ord(tr.num_indices) 74 | for j in range(ord(tr.num_indices)): 75 | print ' index[%d]' % j 76 | print ' offset: %d' % tr.indices[j].offset 77 | print ' number: %d' % ord(tr.indices[j].number) 78 | 79 | elif block.type == metadata.VORBIS_COMMENT: 80 | # print vorbis tags 81 | comment = block.data.vorbis_comment 82 | print ' vendor string: %s' % comment.vendor_string 83 | print ' comments: %d' % comment.num_comments 84 | for i in range(comment.num_comments): 85 | print ' comment[%d]: %s' % (i, comment.comments[i]) 86 | 87 | if not it.next(): 88 | break 89 | -------------------------------------------------------------------------------- /examples/tagedit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # heres an example of using some python magic to 3 | # easily view and modify vorbis comments 4 | 5 | import flac.metadata as metadata 6 | import sys 7 | 8 | # create a chain 9 | chain = metadata.Chain() 10 | chain.read(sys.argv[1]) 11 | 12 | # get iterator, init 13 | it = metadata.Iterator() 14 | it.init(chain) 15 | 16 | while 1: 17 | if it.get_block_type() == metadata.VORBIS_COMMENT: 18 | block = it.get_block() 19 | vc = metadata.VorbisComment(block) 20 | break 21 | if not it.next(): 22 | break 23 | 24 | if vc: 25 | # print num_comments, vendor string 26 | print 'num_comments: %d' % vc.num_comments 27 | print 'vendor string: %s' % vc.vendor_string 28 | # print an existing comment by field name 29 | try: 30 | print vc.comments['TTITLE1'] 31 | except KeyError: 32 | pass 33 | 34 | # print all comments 35 | for c in vc.comments: 36 | print c 37 | 38 | # change vendor string 39 | vc.vendor_string = 'Added by pyflac!' 40 | 41 | # insert/modify/delete comments 42 | # if a tag doesnt already exist, it will be added 43 | vc.comments['ARTIST'] = 'My Artist' 44 | del vc.comments['DISCID'] 45 | vc.comments['MYTEST'] = 'blah' 46 | 47 | # print again 48 | for c in vc.comments: 49 | print c 50 | 51 | # write chain back to disk 52 | print chain.write(True, True) 53 | -------------------------------------------------------------------------------- /flac/__init__.py: -------------------------------------------------------------------------------- 1 | # ****************************************************** 2 | # Copyright 2004: David Collett 3 | # David Collett 4 | # 5 | # * This program is free software; you can redistribute it and/or 6 | # * modify it under the terms of the GNU General Public License 7 | # * as published by the Free Software Foundation; either version 2 8 | # * of the License, or (at your option) any later version. 9 | # * 10 | # * This program is distributed in the hope that it will be useful, 11 | # * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # * GNU General Public License for more details. 14 | # * 15 | # * You should have received a copy of the GNU General Public License 16 | # * along with this program; if not, write to the Free Software 17 | # * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 | # ****************************************************** 19 | #!/usr/bin/python 20 | -------------------------------------------------------------------------------- /flac/decoder.i: -------------------------------------------------------------------------------- 1 | /* 2 | # ****************************************************** 3 | # Copyright 2004: David Collett 4 | # David Collett 5 | # 6 | # * This program is free software; you can redistribute it and/or 7 | # * modify it under the terms of the GNU General Public License 8 | # * as published by the Free Software Foundation; either version 2 9 | # * of the License, or (at your option) any later version. 10 | # * 11 | # * This program is distributed in the hope that it will be useful, 12 | # * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # * GNU General Public License for more details. 15 | # * 16 | # * You should have received a copy of the GNU General Public License 17 | # * along with this program; if not, write to the Free Software 18 | # * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | # ****************************************************** 20 | */ 21 | %module decoder 22 | 23 | %{ 24 | 25 | #include 26 | #include 27 | 28 | // Python Callback Functions Stuff 29 | PyObject *callbacks[3]; 30 | 31 | FLAC__StreamDecoderWriteStatus PythonWriteCallBack( 32 | const FLAC__StreamDecoder *decoder, 33 | const FLAC__Frame *frame, 34 | const FLAC__int32 *const buffer[], 35 | void *client_data) { 36 | 37 | // Interleave the audio and return a single buffer object to python 38 | FLAC__uint32 data_size = frame->header.blocksize * frame->header.channels * (frame->header.bits_per_sample / 8); 39 | 40 | FLAC__uint16 ldb[frame->header.blocksize * frame->header.channels]; 41 | int c_samp, c_chan, d_samp; 42 | 43 | for (c_samp = d_samp = 0; c_samp < frame->header.blocksize; c_samp++) { 44 | for(c_chan = 0; c_chan < frame->header.channels; c_chan++, d_samp++) { 45 | ldb[d_samp] = buffer[c_chan][c_samp]; 46 | } 47 | } 48 | 49 | PyObject *arglist; 50 | PyObject *result; 51 | PyObject *dec, *buf; 52 | FLAC__StreamDecoderWriteStatus res; 53 | 54 | dec = SWIG_NewPointerObj((void *) decoder, SWIGTYPE_p_FLAC__StreamDecoder, 0); 55 | buf = PyBuffer_FromMemory((void *) ldb, data_size); 56 | arglist = Py_BuildValue("(OOl)", dec, buf, data_size); 57 | result = PyEval_CallObject(callbacks[0], arglist); 58 | 59 | Py_DECREF(buf); 60 | Py_DECREF(dec); 61 | Py_DECREF(arglist); 62 | 63 | if (result) { 64 | res = PyInt_AsLong(result); 65 | } else { 66 | res = FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; 67 | } 68 | 69 | Py_XDECREF(result); 70 | return res; 71 | } 72 | 73 | void PythonMetadataCallBack(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) { 74 | PyObject *arglist; 75 | PyObject *dec, *meta; 76 | 77 | dec = SWIG_NewPointerObj((void *) decoder, SWIGTYPE_p_FLAC__StreamDecoder, 0); 78 | meta = SWIG_NewPointerObj((void *) metadata, SWIGTYPE_p_FLAC__StreamMetadata, 0); 79 | arglist = Py_BuildValue("(OO)", dec, meta); 80 | 81 | PyEval_CallObject(callbacks[2], arglist); 82 | 83 | Py_DECREF(dec); 84 | Py_DECREF(meta); 85 | Py_DECREF(arglist); 86 | } 87 | 88 | void PythonErrorCallBack(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) { 89 | PyObject *arglist; 90 | PyObject *dec, *stat; 91 | 92 | dec = SWIG_NewPointerObj((void *) decoder, SWIGTYPE_p_FLAC__StreamDecoder, 0); 93 | stat = PyCObject_FromVoidPtr((void *)status, NULL); 94 | arglist = Py_BuildValue("(OO)", dec, stat); 95 | 96 | PyEval_CallObject(callbacks[1], arglist); 97 | 98 | Py_DECREF(dec); 99 | Py_DECREF(stat); 100 | Py_DECREF(arglist); 101 | } 102 | 103 | // Simple Callbacks (for testing etc) 104 | FLAC__StreamDecoderWriteStatus NullWriteCallBack( 105 | const FLAC__StreamDecoder *decoder, 106 | const FLAC__Frame *frame, 107 | const FLAC__int32 *const buffer[], 108 | void *client_data) { 109 | 110 | //printf("Inside C write cb\n"); 111 | return FLAC__STREAM_DECODER_INIT_STATUS_OK; 112 | } 113 | 114 | void NullMetadataCallBack(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) { 115 | //printf("Inside C metadata cb\n"); 116 | } 117 | 118 | void NullErrorCallBack(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) { 119 | //printf("Inside C error cb\n"); 120 | } 121 | 122 | %} 123 | 124 | %include "flac/format.i" 125 | 126 | PyObject *callbacks[3]; 127 | 128 | %extend FLAC__StreamDecoder { 129 | FLAC__StreamDecoder() { 130 | return FLAC__stream_decoder_new(); 131 | } 132 | 133 | ~FLAC__StreamDecoder() { 134 | // SWIG/Python will automatically garbage collect us. 135 | // FLAC__stream_decoder_delete(self); 136 | } 137 | 138 | FLAC__bool set_md5_checking(FLAC__bool value) { 139 | return FLAC__stream_decoder_set_md5_checking(self, value); 140 | } 141 | 142 | FLAC__bool set_metadata_respond_all() { 143 | return FLAC__stream_decoder_set_metadata_respond_all(self); 144 | } 145 | 146 | FLAC__bool set_metadata_respond(FLAC__MetadataType type) { 147 | return FLAC__stream_decoder_set_metadata_respond(self, type); 148 | } 149 | 150 | FLAC__bool set_metadata_respond_application(const FLAC__byte id[4]) { 151 | return FLAC__stream_decoder_set_metadata_respond_application(self, id); 152 | } 153 | 154 | FLAC__bool set_metadata_ignore_all() { 155 | return FLAC__stream_decoder_set_metadata_ignore_all(self); 156 | } 157 | 158 | FLAC__bool set_metadata_ignore(FLAC__MetadataType type) { 159 | return FLAC__stream_decoder_set_metadata_ignore(self, type); 160 | } 161 | 162 | FLAC__bool set_metadata_ignore_application(const FLAC__byte id[4]) { 163 | return FLAC__stream_decoder_set_metadata_ignore_application(self, id); 164 | } 165 | 166 | FLAC__StreamDecoderState get_state() { 167 | return FLAC__stream_decoder_get_state(self); 168 | } 169 | 170 | const char *get_resolved_state_string() { 171 | return FLAC__stream_decoder_get_resolved_state_string(self); 172 | } 173 | 174 | FLAC__bool get_md5_checking() { 175 | return FLAC__stream_decoder_get_md5_checking(self); 176 | } 177 | 178 | FLAC__ChannelAssignment get_channel_assignment() { 179 | return FLAC__stream_decoder_get_channel_assignment(self); 180 | } 181 | 182 | unsigned get_channels() { 183 | return FLAC__stream_decoder_get_channels (self); 184 | } 185 | 186 | unsigned get_bits_per_sample() { 187 | return FLAC__stream_decoder_get_bits_per_sample(self); 188 | } 189 | 190 | unsigned get_sample_rate() { 191 | return FLAC__stream_decoder_get_sample_rate(self); 192 | } 193 | 194 | unsigned get_blocksize() { 195 | return FLAC__stream_decoder_get_blocksize(self); 196 | } 197 | 198 | FLAC__uint64 get_decode_position() { 199 | FLAC__uint64 tmp; 200 | FLAC__stream_decoder_get_decode_position(self, &tmp); 201 | return tmp; 202 | } 203 | 204 | FLAC__StreamDecoderState init(const char *filename, PyObject *write_cb, PyObject *metadata_cb, PyObject *error_cb) { 205 | callbacks[0] = write_cb; 206 | callbacks[1] = error_cb; 207 | callbacks[2] = metadata_cb; 208 | 209 | Py_INCREF(write_cb); 210 | Py_INCREF(metadata_cb); 211 | Py_INCREF(error_cb); 212 | 213 | return FLAC__stream_decoder_init_file(self, filename, PythonWriteCallBack, PythonMetadataCallBack, PythonErrorCallBack, NULL); 214 | } 215 | 216 | FLAC__bool finish() { 217 | return FLAC__stream_decoder_finish(self); 218 | } 219 | 220 | FLAC__bool process_single() { 221 | return FLAC__stream_decoder_process_single(self); 222 | } 223 | 224 | FLAC__bool process_until_end_of_metadata() { 225 | return FLAC__stream_decoder_process_until_end_of_metadata (self); 226 | } 227 | 228 | FLAC__bool process_until_end_of_stream() { 229 | return FLAC__stream_decoder_process_until_end_of_stream(self); 230 | } 231 | 232 | FLAC__bool skip_single_frame() { 233 | return FLAC__stream_decoder_skip_single_frame(self); 234 | } 235 | 236 | FLAC__bool seek_absolute(FLAC__uint64 sample) { 237 | return FLAC__stream_decoder_seek_absolute(self, sample); 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /flac/encoder.i: -------------------------------------------------------------------------------- 1 | /* 2 | # ****************************************************** 3 | # Copyright 2004: David Collett 4 | # David Collett 5 | # 6 | # * This program is free software; you can redistribute it and/or 7 | # * modify it under the terms of the GNU General Public License 8 | # * as published by the Free Software Foundation; either version 2 9 | # * of the License, or (at your option) any later version. 10 | # * 11 | # * This program is distributed in the hope that it will be useful, 12 | # * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # * GNU General Public License for more details. 15 | # * 16 | # * You should have received a copy of the GNU General Public License 17 | # * along with this program; if not, write to the Free Software 18 | # * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | # ****************************************************** 20 | */ 21 | %module encoder 22 | 23 | %typemap(check) PyObject *pyfunc { 24 | 25 | if (!PyCallable_Check($1)) { 26 | PyErr_SetString(PyExc_TypeError, "Need a callable object"); 27 | return NULL; 28 | } 29 | } 30 | 31 | %typemap(in) FLAC__StreamMetadata **metadata { 32 | int i, size; 33 | FLAC__StreamMetadata *tmp_blk; 34 | PyObject *tmp_obj; 35 | 36 | if (!PyTuple_Check($input)) { 37 | PyErr_SetString(PyExc_TypeError, "Expected a Tuple"); 38 | return NULL; 39 | } 40 | 41 | // extract the tuple and create a FLAC__StreamMetadata ** 42 | size = PyTuple_Size($input); 43 | FLAC__StreamMetadata **meta = calloc(sizeof(FLAC__StreamMetadata *), size); 44 | 45 | for (i = 0; i < size; i++) { 46 | tmp_obj = PyTuple_GetItem($input, i); 47 | if ((SWIG_ConvertPtr(tmp_obj,(void **) &tmp_blk, SWIGTYPE_p_FLAC__StreamMetadata,SWIG_POINTER_EXCEPTION | 0 )) == -1) SWIG_fail; 48 | meta[i] = tmp_blk; 49 | } 50 | 51 | $1 = meta; 52 | } 53 | 54 | %{ 55 | #include 56 | #include 57 | 58 | void PythonProgressCallBack(const FLAC__StreamEncoder *encoder, 59 | FLAC__uint64 bytes_written, 60 | FLAC__uint64 samples_written, 61 | unsigned frames_written, 62 | unsigned total_frames_estimate, 63 | void *client_data) { 64 | 65 | PyObject *arglist; 66 | PyObject *enc; 67 | PyObject *func; 68 | 69 | func = (PyObject *) client_data; 70 | enc = SWIG_NewPointerObj((void *) encoder, SWIGTYPE_p_FLAC__StreamEncoder, 0); 71 | arglist = Py_BuildValue("(Ollii)", enc, (long)bytes_written, (long)samples_written, (int)frames_written, (int)total_frames_estimate); 72 | 73 | PyEval_CallObject(func, arglist); 74 | Py_DECREF(enc); 75 | Py_DECREF(arglist); 76 | } 77 | 78 | FLAC__StreamEncoderWriteStatus PythonWriteCallBack( 79 | const FLAC__StreamEncoder* encoder, 80 | const FLAC__byte buffer[], 81 | size_t bytes, 82 | unsigned samples, 83 | unsigned current_frame, 84 | void* client_data) { 85 | 86 | PyObject *arglist; 87 | PyObject *enc; 88 | PyObject *func; 89 | PyObject *result; 90 | 91 | func = (PyObject *) client_data; 92 | enc = SWIG_NewPointerObj((void *) encoder, SWIGTYPE_p_FLAC__StreamEncoder, 0); 93 | arglist = Py_BuildValue("(Os#ii)", enc, (char*)buffer, bytes, (int)samples, (int)current_frame); 94 | 95 | result = PyEval_CallObject(func, arglist); 96 | 97 | Py_DECREF(enc); 98 | Py_DECREF(arglist); 99 | 100 | if (result == NULL) 101 | return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; 102 | 103 | Py_DECREF(result); 104 | return FLAC__STREAM_ENCODER_WRITE_STATUS_OK; 105 | } 106 | 107 | %} 108 | 109 | %include "flac/format.i" 110 | 111 | %extend FLAC__StreamEncoder { 112 | 113 | FLAC__StreamEncoder() { 114 | return FLAC__stream_encoder_new(); 115 | } 116 | 117 | ~FLAC__StreamEncoder() { 118 | // SWIG/Python will automatically garbage collect us. 119 | // return FLAC__stream_encoder_delete(self); 120 | } 121 | 122 | FLAC__bool set_verify(FLAC__bool value) { 123 | return FLAC__stream_encoder_set_verify(self, value); 124 | } 125 | 126 | FLAC__bool set_streamable_subset(FLAC__bool value) { 127 | return FLAC__stream_encoder_set_streamable_subset(self, value); 128 | } 129 | 130 | FLAC__bool set_do_mid_side_stereo(FLAC__bool value) { 131 | return FLAC__stream_encoder_set_do_mid_side_stereo(self, value); 132 | } 133 | 134 | FLAC__bool set_loose_mid_side_stereo(FLAC__bool value) { 135 | return FLAC__stream_encoder_set_loose_mid_side_stereo(self, value); 136 | } 137 | 138 | FLAC__bool set_channels(unsigned value) { 139 | return FLAC__stream_encoder_set_channels(self, value); 140 | } 141 | 142 | FLAC__bool set_bits_per_sample(unsigned value) { 143 | return FLAC__stream_encoder_set_bits_per_sample(self, value); 144 | } 145 | 146 | FLAC__bool set_sample_rate(unsigned value) { 147 | return FLAC__stream_encoder_set_sample_rate(self, value); 148 | } 149 | 150 | FLAC__bool set_compression_level(unsigned value) { 151 | return FLAC__stream_encoder_set_compression_level(self, value); 152 | } 153 | 154 | FLAC__bool set_blocksize(unsigned value) { 155 | return FLAC__stream_encoder_set_blocksize(self, value); 156 | } 157 | 158 | FLAC__bool set_max_lpc_order(unsigned value) { 159 | return FLAC__stream_encoder_set_max_lpc_order(self, value); 160 | } 161 | 162 | FLAC__bool set_qlp_coeff_precision(unsigned value) { 163 | return FLAC__stream_encoder_set_qlp_coeff_precision(self, value); 164 | } 165 | 166 | FLAC__bool set_do_qlp_coeff_prec_search(FLAC__bool value) { 167 | return FLAC__stream_encoder_set_do_qlp_coeff_prec_search(self, value); 168 | } 169 | 170 | FLAC__bool set_do_escape_coding(FLAC__bool value) { 171 | return FLAC__stream_encoder_set_do_escape_coding(self, value); 172 | } 173 | 174 | FLAC__bool set_do_exhaustive_model_search(FLAC__bool value) { 175 | return FLAC__stream_encoder_set_do_exhaustive_model_search(self, value); 176 | } 177 | 178 | FLAC__bool set_min_residual_partition_order(unsigned value) { 179 | return FLAC__stream_encoder_set_min_residual_partition_order(self, value); 180 | } 181 | 182 | FLAC__bool set_max_residual_partition_order(unsigned value) { 183 | return FLAC__stream_encoder_set_max_residual_partition_order(self, value); 184 | } 185 | 186 | FLAC__bool set_rice_parameter_search_dist(unsigned value) { 187 | return FLAC__stream_encoder_set_rice_parameter_search_dist(self, value); 188 | } 189 | 190 | FLAC__bool set_total_samples_estimate(FLAC__int64 value) { 191 | return FLAC__stream_encoder_set_total_samples_estimate(self, value); 192 | } 193 | 194 | FLAC__bool set_metadata(FLAC__StreamMetadata **metadata, unsigned num_blocks) { 195 | return FLAC__stream_encoder_set_metadata(self, metadata, num_blocks); 196 | } 197 | 198 | FLAC__StreamEncoderState get_state() { 199 | return FLAC__stream_encoder_get_state(self); 200 | } 201 | 202 | FLAC__StreamDecoderState get_verify_decoder_state() { 203 | return FLAC__stream_encoder_get_verify_decoder_state(self); 204 | } 205 | 206 | const char *get_resolved_state_string() { 207 | return FLAC__stream_encoder_get_resolved_state_string(self); 208 | } 209 | 210 | void get_verify_decoder_error_stats(FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got) { 211 | return FLAC__stream_encoder_get_verify_decoder_error_stats(self, absolute_sample, frame_number, channel, sample, expected, got); 212 | } 213 | 214 | FLAC__bool get_verify() { 215 | return FLAC__stream_encoder_get_verify(self); 216 | } 217 | 218 | FLAC__bool get_streamable_subset() { 219 | return FLAC__stream_encoder_get_streamable_subset(self); 220 | } 221 | 222 | FLAC__bool get_do_mid_side_stereo() { 223 | return FLAC__stream_encoder_get_do_mid_side_stereo(self); 224 | } 225 | 226 | FLAC__bool get_loose_mid_side_stereo() { 227 | return FLAC__stream_encoder_get_loose_mid_side_stereo(self); 228 | } 229 | 230 | unsigned get_channels() { 231 | return FLAC__stream_encoder_get_channels(self); 232 | } 233 | 234 | unsigned get_bits_per_sample() { 235 | return FLAC__stream_encoder_get_bits_per_sample(self); 236 | } 237 | 238 | unsigned get_sample_rate() { 239 | return FLAC__stream_encoder_get_sample_rate(self); 240 | } 241 | 242 | unsigned get_blocksize() { 243 | return FLAC__stream_encoder_get_blocksize(self); 244 | } 245 | 246 | unsigned get_max_lpc_order() { 247 | return FLAC__stream_encoder_get_max_lpc_order(self); 248 | } 249 | 250 | unsigned get_qlp_coeff_precision() { 251 | return FLAC__stream_encoder_get_qlp_coeff_precision(self); 252 | } 253 | 254 | FLAC__bool get_do_qlp_coeff_prec_search() { 255 | return FLAC__stream_encoder_get_do_qlp_coeff_prec_search(self); 256 | } 257 | 258 | FLAC__bool get_do_escape_coding() { 259 | return FLAC__stream_encoder_get_do_escape_coding(self); 260 | } 261 | 262 | FLAC__bool get_do_exhaustive_model_search() { 263 | return FLAC__stream_encoder_get_do_exhaustive_model_search(self); 264 | } 265 | 266 | unsigned get_min_residual_partition_order() { 267 | return FLAC__stream_encoder_get_min_residual_partition_order(self); 268 | } 269 | 270 | unsigned get_max_residual_partition_order() { 271 | return FLAC__stream_encoder_get_max_residual_partition_order(self); 272 | } 273 | 274 | unsigned get_rice_parameter_search_dist() { 275 | return FLAC__stream_encoder_get_rice_parameter_search_dist(self); 276 | } 277 | 278 | FLAC__uint64 get_total_samples_estimate() { 279 | return FLAC__stream_encoder_get_total_samples_estimate(self); 280 | } 281 | 282 | FLAC__StreamEncoderState init_file(const char *filename, PyObject *pyfunc) { 283 | Py_INCREF(pyfunc); 284 | 285 | return FLAC__stream_encoder_init_file(self, filename, PythonProgressCallBack, (void*)pyfunc); 286 | } 287 | 288 | FLAC__StreamEncoderState init_stream(PyObject *pyfunc) { 289 | Py_INCREF(pyfunc); 290 | 291 | return FLAC__stream_encoder_init_stream(self, PythonWriteCallBack, NULL, NULL, NULL, (void*)pyfunc); 292 | } 293 | 294 | void finish() { 295 | FLAC__stream_encoder_finish(self); 296 | } 297 | 298 | FLAC__bool process(const char *byte_data, unsigned samples) { 299 | FLAC__bool retval; 300 | int i,j; 301 | int channels = FLAC__stream_encoder_get_channels(self); 302 | int width = FLAC__stream_encoder_get_bits_per_sample(self); 303 | FLAC__int32 *buff = calloc(channels * samples, sizeof(FLAC__int32)); 304 | 305 | // convert from input sample size to FLAC__int32 306 | if (width == 8) { 307 | 308 | FLAC__int8 *data = (FLAC__int8 *) byte_data; 309 | 310 | for(i = 0; i < samples*channels; i++) { 311 | buff[i] = data[i]; 312 | } 313 | 314 | } else if(width == 16) { 315 | 316 | FLAC__int16 *data = (FLAC__int16 *) byte_data; 317 | 318 | for (i = 0; i < samples*channels; i++) { 319 | buff[i] = data[i]; 320 | } 321 | 322 | } else if (width == 24) { 323 | 324 | FLAC__int8 *data = (FLAC__int8 *) byte_data; 325 | 326 | for (i = j = 0; i < samples*channels; i++) { 327 | buff[i] = data[j++]; buff[i] <<= 8; 328 | buff[i] |= data[j++]; buff[i] <<= 8; 329 | buff[i] |= data[j++]; 330 | } 331 | 332 | } else { 333 | fprintf(stderr, "Unsupported sample size.\n"); 334 | free(buff); 335 | return false; 336 | } 337 | 338 | retval = FLAC__stream_encoder_process_interleaved(self, buff, samples); 339 | free(buff); 340 | return retval; 341 | } 342 | 343 | FLAC__bool process_interleaved(const FLAC__int32 buffer[], unsigned samples) { 344 | return FLAC__stream_encoder_process_interleaved(self, buffer, samples); 345 | } 346 | } 347 | -------------------------------------------------------------------------------- /flac/format.i: -------------------------------------------------------------------------------- 1 | /* 2 | # ****************************************************** 3 | # Copyright 2004: David Collett 4 | # David Collett 5 | # 6 | # * This program is free software; you can redistribute it and/or 7 | # * modify it under the terms of the GNU General Public License 8 | # * as published by the Free Software Foundation; either version 2 9 | # * of the License, or (at your option) any later version. 10 | # * 11 | # * This program is distributed in the hope that it will be useful, 12 | # * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # * GNU General Public License for more details. 15 | # * 16 | # * You should have received a copy of the GNU General Public License 17 | # * along with this program; if not, write to the Free Software 18 | # * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | # ****************************************************** 20 | */ 21 | // do some renaming 22 | %rename (StreamDecoder) FLAC__StreamDecoder; 23 | %rename (StreamEncoder) FLAC__StreamEncoder; 24 | 25 | %rename (Metadata) FLAC__StreamMetadata; 26 | %rename (StreamInfo) FLAC__StreamMetadata_StreamInfo; 27 | %rename (Padding) FLAC__StreamMetadata_Padding; 28 | %rename (Application) FLAC__StreamMetadata_Application; 29 | %rename (SeekTable) FLAC__StreamMetadata_SeekTable; 30 | %rename (VorbisComment) FLAC__StreamMetadata_VorbisComment; 31 | %rename (CueSheet) FLAC__StreamMetadata_CueSheet; 32 | %rename (Unknown) FLAC__StreamMetadata_Unknown; 33 | %rename (VorbisCommentEntry) FLAC__StreamMetadata_VorbisComment_Entry; 34 | %rename (SeekPoint) FLAC__StreamMetadata_SeekPoint; 35 | %rename (Picture) FLAC__StreamMetadata_Picture; 36 | %rename (CueSheetTrack) FLAC__StreamMetadata_CueSheet_Track; 37 | %rename (CueSheetIndex) FLAC__StreamMetadata_CueSheet_Index; 38 | 39 | %rename (STREAMINFO) FLAC__METADATA_TYPE_STREAMINFO; 40 | %rename (PADDING) FLAC__METADATA_TYPE_PADDING; 41 | %rename (APPLICATION) FLAC__METADATA_TYPE_APPLICATION; 42 | %rename (SEEKTABLE) FLAC__METADATA_TYPE_SEEKTABLE; 43 | %rename (VORBIS_COMMENT) FLAC__METADATA_TYPE_VORBIS_COMMENT; 44 | %rename (CUESHEET) FLAC__METADATA_TYPE_CUESHEET; 45 | %rename (PICTURE) FLAC__METADATA_TYPE_PICTURE; 46 | %rename (UNDEFINED) FLAC__METADATA_TYPE_UNDEFINED; 47 | /* 48 | typedef enum FLAC__Metadata_ChainStatus { 49 | FLAC__METADATA_CHAIN_STATUS_OK = 0, 50 | FLAC__METADATA_CHAIN_STATUS_ILLEGAL_INPUT, 51 | FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE, 52 | FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE, 53 | FLAC__METADATA_CHAIN_STATUS_NOT_WRITABLE, 54 | FLAC__METADATA_CHAIN_STATUS_BAD_METADATA, 55 | FLAC__METADATA_CHAIN_STATUS_READ_ERROR, 56 | FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR, 57 | FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR, 58 | FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR, 59 | FLAC__METADATA_CHAIN_STATUS_UNLINK_ERROR, 60 | FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR, 61 | FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR 62 | */ 63 | 64 | %{ 65 | #include 66 | #include 67 | #include 68 | #include 69 | %} 70 | 71 | // common defs 72 | typedef int FLAC__bool; 73 | typedef signed char FLAC__int8; 74 | typedef unsigned char FLAC__uint8; 75 | typedef short FLAC__int16; 76 | typedef int FLAC__int32; 77 | typedef long long FLAC__int64; 78 | typedef unsigned short FLAC__uint16; 79 | typedef unsigned int FLAC__uint32; 80 | typedef unsigned long long FLAC__uint64; 81 | typedef FLAC__uint8 FLAC__byte; 82 | typedef float FLAC__real; 83 | 84 | // StreamDecoder defs 85 | 86 | typedef enum { 87 | FLAC__STREAM_DECODER_INIT_STATUS_OK = 0, 88 | FLAC__STREAM_DECODER_INIT_STATUS_UNSUPPORTED_CONTAINER, 89 | FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE, 90 | FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR, 91 | FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS, 92 | FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED 93 | } FLAC__StreamDecoderState; 94 | 95 | typedef struct FLAC__StreamDecoder { 96 | struct FLAC__StreamDecoderProtected *protected_; /* avoid the C++ keyword 'protected' */ 97 | struct FLAC__StreamDecoderPrivate *private_; /* avoid the C++ keyword 'private' */ 98 | } FLAC__StreamDecoder; 99 | 100 | // StreamEncoder defs 101 | 102 | typedef enum { 103 | FLAC__STREAM_ENCODER_OK = 0, 104 | FLAC__STREAM_ENCODER_UNINITIALIZED, 105 | FLAC__STREAM_ENCODER_OGG_ERROR, 106 | FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR, 107 | FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA, 108 | FLAC__STREAM_ENCODER_CLIENT_ERROR, 109 | FLAC__STREAM_ENCODER_IO_ERROR, 110 | FLAC__STREAM_ENCODER_FRAMING_ERROR, 111 | FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR 112 | } FLAC__StreamEncoderState; 113 | 114 | typedef struct FLAC__StreamEncoder { 115 | struct FLAC__StreamEncoderProtected *protected_; /* avoid the C++ keyword 'protected' */ 116 | struct FLAC__StreamEncoderPrivate *private_; /* avoid the C++ keyword 'private' */ 117 | } FLAC__StreamEncoder; 118 | 119 | // Metadata defs 120 | 121 | %typemap(in) FLAC__StreamMetadata_VorbisComment_Entry entry { 122 | 123 | if (!PyString_Check($input)) { 124 | PyErr_SetString(PyExc_TypeError, "Expecting a string object"); 125 | return NULL; 126 | } 127 | 128 | FLAC__StreamMetadata_VorbisComment_Entry entry; 129 | entry.length = (FLAC__uint32)PyString_Size($input); 130 | entry.entry = (FLAC__byte*)PyString_AsString($input); 131 | $1 = entry; 132 | } 133 | 134 | typedef struct FLAC__StreamMetadata { 135 | FLAC__MetadataType type; 136 | FLAC__bool is_last; 137 | unsigned length; 138 | 139 | union { 140 | FLAC__StreamMetadata_StreamInfo stream_info; 141 | FLAC__StreamMetadata_Padding padding; 142 | FLAC__StreamMetadata_Application application; 143 | FLAC__StreamMetadata_SeekTable seek_table; 144 | FLAC__StreamMetadata_VorbisComment vorbis_comment; 145 | FLAC__StreamMetadata_CueSheet cue_sheet; 146 | FLAC__StreamMetadata_Picture picture; 147 | FLAC__StreamMetadata_Unknown unknown; 148 | } data; 149 | } FLAC__StreamMetadata; 150 | 151 | typedef struct FLAC__StreamMetadata_StreamInfo { 152 | unsigned min_blocksize, max_blocksize; 153 | unsigned min_framesize, max_framesize; 154 | unsigned sample_rate; 155 | unsigned channels; 156 | unsigned bits_per_sample; 157 | FLAC__uint64 total_samples; 158 | FLAC__byte md5sum[16]; 159 | } FLAC__StreamMetadata_StreamInfo; 160 | 161 | typedef struct FLAC__StreamMetadata_Padding { 162 | int dummy; 163 | } FLAC__StreamMetadata_Padding; 164 | 165 | typedef struct FLAC__StreamMetadata_Application { 166 | FLAC__byte id[4]; 167 | FLAC__byte *data; 168 | } FLAC__StreamMetadata_Application; 169 | 170 | typedef struct FLAC__StreamMetadata_SeekPoint { 171 | FLAC__uint64 sample_number; 172 | FLAC__uint64 stream_offset; 173 | unsigned frame_samples; 174 | } FLAC__StreamMetadata_SeekPoint; 175 | 176 | typedef struct FLAC__StreamMetadata_SeekTable { 177 | unsigned num_points; 178 | FLAC__StreamMetadata_SeekPoint *points; 179 | } FLAC__StreamMetadata_SeekTable; 180 | 181 | // This typemap returns a python string instead of vc entry 182 | %typemap(out) FLAC__StreamMetadata_VorbisComment_Entry * { 183 | $result = PyString_FromStringAndSize((const char*)$1->entry, (int)$1->length); 184 | } 185 | 186 | typedef struct FLAC__StreamMetadata_VorbisComment_Entry { 187 | FLAC__uint32 length; 188 | FLAC__byte *entry; 189 | } FLAC__StreamMetadata_VorbisComment_Entry; 190 | 191 | 192 | typedef struct FLAC__StreamMetadata_VorbisComment { 193 | FLAC__StreamMetadata_VorbisComment_Entry vendor_string; 194 | FLAC__uint32 num_comments; 195 | %typemap(out) FLAC__StreamMetadata_VorbisComment_Entry *; 196 | FLAC__StreamMetadata_VorbisComment_Entry *comments; 197 | } FLAC__StreamMetadata_VorbisComment; 198 | 199 | typedef struct FLAC__StreamMetadata_CueSheet_Index { 200 | FLAC__uint64 offset; 201 | FLAC__byte number; 202 | } FLAC__StreamMetadata_CueSheet_Index; 203 | 204 | typedef struct FLAC__StreamMetadata_CueSheet_Track { 205 | FLAC__uint64 offset; 206 | FLAC__byte number; 207 | char isrc[13]; 208 | unsigned type:1; 209 | unsigned pre_emphasis:1; 210 | FLAC__byte num_indices; 211 | FLAC__StreamMetadata_CueSheet_Index *indices; 212 | } FLAC__StreamMetadata_CueSheet_Track; 213 | 214 | typedef struct FLAC__StreamMetadata_CueSheet { 215 | char media_catalog_number[129]; 216 | FLAC__uint64 lead_in; 217 | FLAC__bool is_cd; 218 | unsigned num_tracks; 219 | FLAC__StreamMetadata_CueSheet_Track *tracks; 220 | } FLAC__StreamMetadata_CueSheet; 221 | 222 | typedef struct FLAC__StreamMetadata_Unknown { 223 | FLAC__byte *data; 224 | } FLAC__StreamMetadata_Unknown; 225 | 226 | typedef enum FLAC__MetadataType { 227 | FLAC__METADATA_TYPE_STREAMINFO = 0, 228 | FLAC__METADATA_TYPE_PADDING = 1, 229 | FLAC__METADATA_TYPE_APPLICATION = 2, 230 | FLAC__METADATA_TYPE_SEEKTABLE = 3, 231 | FLAC__METADATA_TYPE_VORBIS_COMMENT = 4, 232 | FLAC__METADATA_TYPE_CUESHEET = 5, 233 | FLAC__METADATA_TYPE_PICTURE = 6, 234 | FLAC__METADATA_TYPE_UNDEFINED = 7 235 | } FLAC__MetadataType; 236 | 237 | typedef enum FLAC__Metadata_ChainStatus { 238 | FLAC__METADATA_CHAIN_STATUS_OK = 0, 239 | FLAC__METADATA_CHAIN_STATUS_ILLEGAL_INPUT, 240 | FLAC__METADATA_CHAIN_STATUS_ERROR_OPENING_FILE, 241 | FLAC__METADATA_CHAIN_STATUS_NOT_A_FLAC_FILE, 242 | FLAC__METADATA_CHAIN_STATUS_NOT_WRITABLE, 243 | FLAC__METADATA_CHAIN_STATUS_BAD_METADATA, 244 | FLAC__METADATA_CHAIN_STATUS_READ_ERROR, 245 | FLAC__METADATA_CHAIN_STATUS_SEEK_ERROR, 246 | FLAC__METADATA_CHAIN_STATUS_WRITE_ERROR, 247 | FLAC__METADATA_CHAIN_STATUS_RENAME_ERROR, 248 | FLAC__METADATA_CHAIN_STATUS_UNLINK_ERROR, 249 | FLAC__METADATA_CHAIN_STATUS_MEMORY_ALLOCATION_ERROR, 250 | FLAC__METADATA_CHAIN_STATUS_INTERNAL_ERROR 251 | } FLAC__Metadata_ChainStatus; 252 | -------------------------------------------------------------------------------- /flac/metadata.py: -------------------------------------------------------------------------------- 1 | # ****************************************************** 2 | # Copyright 2004: David Collett 3 | # David Collett 4 | # 5 | # * This program is free software; you can redistribute it and/or 6 | # * modify it under the terms of the GNU General Public License 7 | # * as published by the Free Software Foundation; either version 2 8 | # * of the License, or (at your option) any later version. 9 | # * 10 | # * This program is distributed in the hope that it will be useful, 11 | # * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # * GNU General Public License for more details. 14 | # * 15 | # * You should have received a copy of the GNU General Public License 16 | # * along with this program; if not, write to the Free Software 17 | # * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 | # ****************************************************** 19 | #!/usr/bin/python 20 | 21 | # import everything from metaflac 22 | from sw_metadata import * 23 | 24 | # override classes for nicer write access interface 25 | # this is backward compatable with plain metaflac module 26 | # when reading only 27 | class VorbisComment: 28 | 29 | class Comments: 30 | def __init__(self, block): 31 | self.block = block 32 | self.count = -1 33 | def __setitem__(self, name, value): 34 | if type(name) == int: 35 | self.block.vorbiscomment_set_comment(name, value, True) 36 | elif type(name) == str: 37 | self.block.vorbiscomment_insert_comment(self.block.data.vorbis_comment.num_comments, "%s=%s" % (name, value), True) 38 | def __delitem__(self, name): 39 | if type(name) == str: 40 | self.block.vorbiscomment_remove_entry_matching(name) 41 | elif type(name) == int: 42 | self.block.vorbiscomment_delete_comment(name) 43 | def __getitem__(self, name): 44 | if type(name) == int: 45 | if(name >= 0 and name < self.block.data.vorbis_comment.num_comments): 46 | return self.block.data.vorbis_comment.comments[name] 47 | else: 48 | raise IndexError, "Index %d out of range" % name 49 | elif type(name) == str: 50 | idx = self.block.vorbiscomment_find_entry_from(0, name) 51 | if idx != -1: 52 | return self.block.data.vorbis_comment.comments[idx].split('=',1)[1] 53 | else: 54 | raise KeyError, name 55 | def __iter__(self): 56 | return self 57 | def next(self): 58 | if self.count < self.block.data.vorbis_comment.num_comments - 1: 59 | self.count += 1 60 | return self.block.data.vorbis_comment.comments[self.count] 61 | else: 62 | self.count = -1 63 | raise StopIteration 64 | 65 | def __init__(self, block=None): 66 | if block: 67 | self.block = block 68 | else: 69 | self.block = Metadata(VORBIS_COMMENT) 70 | self.comments = VorbisComment.Comments(self.block) 71 | 72 | def __getattr__(self, name): 73 | try: 74 | return self.block.data.vorbis_comment.__getattr__(name) 75 | except AttributeError: 76 | return self.block.__getattr__(name) 77 | 78 | def __setattr__(self, name, value): 79 | # this is the only user-settable attribute... 80 | if name=='vendor_string': 81 | self.block.vorbiscomment_set_vendor_string(value, True); 82 | else: 83 | self.__dict__[name] = value 84 | 85 | class SeekTable: 86 | def __init__(self, block=None): 87 | if block: 88 | self.block = block 89 | else: 90 | self.block = Metadata(SEEKTABLE) 91 | # def template_append_spaced_points(self, num_points, total_samples): 92 | # return self.block.seektable_template_append_spaced_points(num_points, total_samples) 93 | def __getattr__(self, name): 94 | try: 95 | return eval("self.block.seektable_%s" % name) 96 | except AttributeError: 97 | try: 98 | return self.block.data.seektable.__getattr__(name) 99 | except AttributeError: 100 | return self.block.__getattr__(name) 101 | -------------------------------------------------------------------------------- /flac/sw_metadata.i: -------------------------------------------------------------------------------- 1 | /* 2 | # ****************************************************** 3 | # Copyright 2004: David Collett 4 | # David Collett 5 | # 6 | # * This program is free software; you can redistribute it and/or 7 | # * modify it under the terms of the GNU General Public License 8 | # * as published by the Free Software Foundation; either version 2 9 | # * of the License, or (at your option) any later version. 10 | # * 11 | # * This program is distributed in the hope that it will be useful, 12 | # * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # * GNU General Public License for more details. 15 | # * 16 | # * You should have received a copy of the GNU General Public License 17 | # * along with this program; if not, write to the Free Software 18 | # * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | # ****************************************************** 20 | */ 21 | %module sw_metadata 22 | 23 | %{ 24 | #include 25 | %} 26 | 27 | %inline %{ 28 | const char *TypeString(int index) { 29 | return FLAC__MetadataTypeString[index]; 30 | } 31 | %} 32 | 33 | // import common typedefs etc 34 | %include "flac/format.i" 35 | 36 | %rename (Chain) FLAC__Metadata_Chain; 37 | typedef struct FLAC__Metadata_Chain {} FLAC__Metadata_Chain; 38 | 39 | %extend FLAC__Metadata_Chain { 40 | FLAC__Metadata_Chain() { 41 | return FLAC__metadata_chain_new(); 42 | } 43 | 44 | ~FLAC__Metadata_Chain() { 45 | // SWIG/Python will automatically garbage collect us. 46 | // FLAC__metadata_chain_delete(self); 47 | } 48 | 49 | FLAC__Metadata_ChainStatus status() { 50 | return FLAC__metadata_chain_status(self); 51 | } 52 | 53 | FLAC__bool read(const char *filename) { 54 | return FLAC__metadata_chain_read(self, filename); 55 | } 56 | 57 | FLAC__bool write(FLAC__bool use_padding, FLAC__bool preserve_file_stats) { 58 | return FLAC__metadata_chain_write(self, use_padding, preserve_file_stats); 59 | } 60 | 61 | void merge_padding() { 62 | return FLAC__metadata_chain_merge_padding(self); 63 | } 64 | 65 | void sort_padding() { 66 | return FLAC__metadata_chain_sort_padding(self); 67 | } 68 | } 69 | 70 | %rename (Iterator) FLAC__Metadata_Iterator; 71 | typedef struct FLAC__Metadata_Iterator {} FLAC__Metadata_Iterator; 72 | 73 | %extend FLAC__Metadata_Iterator { 74 | FLAC__Metadata_Iterator() { 75 | return FLAC__metadata_iterator_new(); 76 | } 77 | 78 | ~FLAC__Metadata_Iterator() { 79 | // SWIG/Python will automatically garbage collect us. 80 | // FLAC__metadata_iterator_delete(self); 81 | } 82 | 83 | void init(FLAC__Metadata_Chain *chain) { 84 | FLAC__metadata_iterator_init(self, chain); 85 | } 86 | 87 | FLAC__bool next() { 88 | return FLAC__metadata_iterator_next(self); 89 | } 90 | 91 | FLAC__bool prev() { 92 | return FLAC__metadata_iterator_prev(self); 93 | } 94 | 95 | FLAC__MetadataType get_block_type() { 96 | return FLAC__metadata_iterator_get_block_type(self); 97 | } 98 | 99 | FLAC__StreamMetadata *get_block() { 100 | return FLAC__metadata_iterator_get_block(self); 101 | } 102 | 103 | FLAC__bool set_block(FLAC__StreamMetadata *block) { 104 | return FLAC__metadata_iterator_set_block(self, block); 105 | } 106 | 107 | FLAC__bool delete_block(FLAC__bool replace_with_padding) { 108 | return FLAC__metadata_iterator_delete_block(self, replace_with_padding); 109 | } 110 | 111 | FLAC__bool insert_block_before(FLAC__StreamMetadata *block) { 112 | return FLAC__metadata_iterator_insert_block_before(self, block); 113 | } 114 | 115 | FLAC__bool insert_block_after(FLAC__StreamMetadata *block) { 116 | return FLAC__metadata_iterator_insert_block_after(self, block); 117 | } 118 | } 119 | 120 | %extend FLAC__StreamMetadata { 121 | FLAC__StreamMetadata(FLAC__MetadataType type) { 122 | return FLAC__metadata_object_new(type); 123 | } 124 | 125 | ~FLAC__StreamMetadata() { 126 | // SWIG/Python will automatically garbage collect us. 127 | // FLAC__metadata_object_delete(self); 128 | } 129 | 130 | FLAC__StreamMetadata *clone() { 131 | return FLAC__metadata_object_clone(self); 132 | } 133 | 134 | FLAC__bool is_equal(const FLAC__StreamMetadata *block) { 135 | return FLAC__metadata_object_is_equal(self, block); 136 | } 137 | 138 | FLAC__bool application_set_data(FLAC__byte *data, unsigned length, FLAC__bool copy) { 139 | return FLAC__metadata_object_application_set_data(self, data, length, copy); 140 | } 141 | 142 | FLAC__bool seektable_resize_points(unsigned new_num_points) { 143 | return FLAC__metadata_object_seektable_resize_points(self, new_num_points); 144 | } 145 | 146 | void seektable_set_point(unsigned point_num, FLAC__StreamMetadata_SeekPoint point) { 147 | FLAC__metadata_object_seektable_set_point(self, point_num, point); 148 | } 149 | 150 | FLAC__bool seektable_insert_point(unsigned point_num, FLAC__StreamMetadata_SeekPoint point) { 151 | return FLAC__metadata_object_seektable_insert_point(self, point_num, point); 152 | } 153 | 154 | FLAC__bool seektable_delete_point(unsigned point_num) { 155 | return FLAC__metadata_object_seektable_delete_point(self, point_num); 156 | } 157 | 158 | FLAC__bool seektable_is_legal() { 159 | return FLAC__metadata_object_seektable_is_legal(self); 160 | } 161 | 162 | FLAC__bool seektable_template_append_placeholders(unsigned num) { 163 | return FLAC__metadata_object_seektable_template_append_placeholders(self, num); 164 | } 165 | 166 | FLAC__bool seektable_template_append_point(FLAC__uint64 sample_number) { 167 | return FLAC__metadata_object_seektable_template_append_point(self, sample_number); 168 | } 169 | 170 | FLAC__bool seektable_template_append_points(FLAC__uint64 sample_numbers[], unsigned num) { 171 | return FLAC__metadata_object_seektable_template_append_points(self, sample_numbers, num); 172 | } 173 | 174 | FLAC__bool seektable_template_append_spaced_points(unsigned num, FLAC__uint64 total_samples) { 175 | return FLAC__metadata_object_seektable_template_append_spaced_points(self, num, total_samples); 176 | } 177 | 178 | FLAC__bool seektable_template_sort(FLAC__bool compact) { 179 | return FLAC__metadata_object_seektable_template_sort(self, compact); 180 | } 181 | 182 | FLAC__bool vorbiscomment_set_vendor_string(FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy) { 183 | return FLAC__metadata_object_vorbiscomment_set_vendor_string(self, entry, copy); 184 | } 185 | 186 | FLAC__bool vorbiscomment_resize_comments(unsigned new_num_comments) { 187 | return FLAC__metadata_object_vorbiscomment_resize_comments(self, new_num_comments); 188 | } 189 | 190 | FLAC__bool vorbiscomment_set_comment(unsigned comment_num, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy) { 191 | return FLAC__metadata_object_vorbiscomment_set_comment(self, comment_num, entry, copy); 192 | } 193 | 194 | FLAC__bool vorbiscomment_insert_comment(unsigned comment_num, FLAC__StreamMetadata_VorbisComment_Entry entry, FLAC__bool copy) { 195 | return FLAC__metadata_object_vorbiscomment_insert_comment(self, comment_num, entry, copy); 196 | } 197 | 198 | FLAC__bool vorbiscomment_delete_comment(unsigned comment_num) { 199 | return FLAC__metadata_object_vorbiscomment_delete_comment(self, comment_num); 200 | } 201 | 202 | int vorbiscomment_find_entry_from(unsigned offset, const char *field_name) { 203 | return FLAC__metadata_object_vorbiscomment_find_entry_from(self, offset, field_name); 204 | } 205 | 206 | int vorbiscomment_remove_entry_matching(const char *field_name) { 207 | return FLAC__metadata_object_vorbiscomment_remove_entry_matching(self, field_name); 208 | } 209 | 210 | int vorbiscomment_remove_entries_matching(const char *field_name) { 211 | return FLAC__metadata_object_vorbiscomment_remove_entries_matching(self, field_name); 212 | } 213 | 214 | FLAC__bool cuesheet_track_resize_indices(unsigned track_num, unsigned new_num_indices) { 215 | return FLAC__metadata_object_cuesheet_track_resize_indices(self, track_num, new_num_indices); 216 | } 217 | 218 | FLAC__bool cuesheet_track_insert_index(unsigned track_num, unsigned index_num, FLAC__StreamMetadata_CueSheet_Index index) { 219 | return FLAC__metadata_object_cuesheet_track_insert_index(self, track_num, index_num, index); 220 | } 221 | 222 | FLAC__bool cuesheet_track_insert_blank_index(unsigned track_num, unsigned index_num) { 223 | return FLAC__metadata_object_cuesheet_track_insert_blank_index(self, track_num, index_num); 224 | } 225 | 226 | FLAC__bool cuesheet_track_delete_index(unsigned track_num, unsigned index_num) { 227 | return FLAC__metadata_object_cuesheet_track_delete_index(self, track_num, index_num); 228 | } 229 | 230 | FLAC__bool cuesheet_resize_tracks(unsigned new_num_tracks) { 231 | return FLAC__metadata_object_cuesheet_resize_tracks(self, new_num_tracks); 232 | } 233 | 234 | FLAC__bool cuesheet_insert_track(unsigned track_num, FLAC__StreamMetadata_CueSheet_Track *track, FLAC__bool copy) { 235 | return FLAC__metadata_object_cuesheet_insert_track(self, track_num, track, copy); 236 | } 237 | 238 | FLAC__bool cuesheet_insert_blank_track(unsigned track_num) { 239 | return FLAC__metadata_object_cuesheet_insert_blank_track(self, track_num); 240 | } 241 | 242 | FLAC__bool cuesheet_delete_track(unsigned track_num) { 243 | return FLAC__metadata_object_cuesheet_delete_track(self, track_num); 244 | } 245 | 246 | FLAC__bool cuesheet_is_legal(FLAC__bool check_cd_da_subset, const char **violation) { 247 | return FLAC__metadata_object_cuesheet_is_legal(self, check_cd_da_subset, violation); 248 | } 249 | } 250 | 251 | // note that there is a typemap defined in format.i (where the original declaration of this class is) 252 | // which makes the output into a python string of the correct length :) 253 | 254 | %extend FLAC__StreamMetadata_VorbisComment_Entry { 255 | 256 | FLAC__bool matches(const char *field_name, unsigned field_name_length) { 257 | return FLAC__metadata_object_vorbiscomment_entry_matches(*self, field_name, field_name_length); 258 | } 259 | 260 | FLAC__StreamMetadata_VorbisComment_Entry *__getitem__(int index) { 261 | return self+index; 262 | } 263 | } 264 | 265 | %extend FLAC__StreamMetadata_CueSheet_Track { 266 | 267 | FLAC__StreamMetadata_CueSheet_Track() { 268 | return FLAC__metadata_object_cuesheet_track_new(); 269 | } 270 | 271 | ~FLAC__StreamMetadata_CueSheet_Track() { 272 | // SWIG/Python will automatically garbage collect us. 273 | // FLAC__metadata_object_cuesheet_track_delete(self); 274 | } 275 | 276 | FLAC__StreamMetadata_CueSheet_Track *clone() { 277 | return FLAC__metadata_object_cuesheet_track_clone(self); 278 | } 279 | 280 | FLAC__StreamMetadata_CueSheet_Track *__getitem__(int index) { 281 | return self+index; 282 | } 283 | } 284 | 285 | %extend FLAC__StreamMetadata_CueSheet_Index { 286 | FLAC__StreamMetadata_CueSheet_Index *__getitem__(int index) { 287 | return self+index; 288 | } 289 | } 290 | 291 | %extend FLAC__StreamMetadata_SeekPoint { 292 | FLAC__StreamMetadata_SeekPoint *__getitem__(int index) { 293 | return self+index; 294 | } 295 | } 296 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from distutils.core import setup, Extension 4 | setup( 5 | name = "pyflac", version = "0.1", 6 | url="https://github.com/dsully/pyflac", 7 | description = "libFLAC wrapper", 8 | author = "David Collett, Joe Wreschnig, Dan Sully", 9 | author_email = "david.collett@dart.net.au", 10 | maintainer = "Dan Sully", 11 | license = "GNU GPL v2 or later", 12 | long_description = """ 13 | This is a simple wrapper for some of libFLAC, namely the file decoder, file 14 | encoder, and metadata interfaces. Most of the functions of these interfaces 15 | are working (I think).""", 16 | 17 | packages = ["flac"], 18 | ext_modules = [ 19 | Extension('flac/_%s' % i, ['flac/%s_wrap.c' % i], 20 | library_dirs=['/usr/local/lib'], 21 | libraries=['FLAC']) for i in ["encoder", "decoder", "sw_metadata"] 22 | ] 23 | ) 24 | --------------------------------------------------------------------------------