commit f2cfda2a54780868dfe0af7bd652fcd4906547da Author: tpearson Date: Mon Mar 1 19:09:31 2010 +0000 Added KDE3 version of SoundKonverter git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/soundkonverter@1097614 283d02a7-25f6-0310-bc7c-ecb5cbfe19da diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..6cff897 --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Daniel Faust diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..c13faf0 --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..a008b97 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,199 @@ +0.3.8: +-Fix: compile error with gcc 4.3 +-Fix: filenames containing some special characters including '?' work again +-Fix: files added by 'add directory' or via context menu from konqueror and containing special characters will work now +-Fix: vfat compatible output names won't contain '/' anymore + +0.3.7: +-Add: sox plugin for aiff (thanks to Ron Fischler) +-Add: toolame and twolame plugins for mp2 encoding +-Add: amr decoding with ffmpeg +-Add: Improved Polish translation (thanks to Michał Smoczyk) +-Add: Reading writing composer/disc number tags for tta files +-Add: A user script can be executed after each file has been converted (->config dialog->general->user script) +-Add: Hungarian and Italian translations (thanks to the language teams at launchpad) +-Fix: Flake plugin +-Fix: Wavpack encoding +-Fix: Dropping folders works again +-Fix: Use the current language's decimal symbol for oggenc +-Fix: Progress for lame abr/cbr encoding +-Fix: mp4v2 works now +-Fix: soundkonverter won't display wrong backends in the config dialog any more +-Fix: And a lot more ... +-Change: Use --vbr-new for lame +-Change: Use extension to determine file type if no mime type file was found + +0.3.6: +-Fix: Don't crash when using kio_audiocd +-Fix: Show progress when using kio_audiocd +-Fix: Show the soundkonverter window when started with --rip option +-Fix: Handle remote files properly (http, smb, etc.) + +0.3.5: +-Add: Portuguese translation (thanks to Equipa de Traduções 1 / www.portugal-a-programar.org) +-Add: Dutch translation (thanks to Sander Thijsen) +-Add: Improved Polish translation (thanks to Tomasz Argasiński) +-Add: Improved Russian translation (thanks to Ivan) +-Add: Support for flake (flac encoder) +-Add: Support for aften (ac3 encoder) +-Add: File format filter for adding a directory recursive +-Add: Tag reading/writing support for wavpack, optimfrog, trueaudio +-Add: Read Replay Gain tags for wavpack files +-Fix: Write m4a tags properly +-Fix: Some problems with the CD-Ripper dialog +-Fix: File filter for the Replay Gain tool +-Fix: Close soundKonverter faster +-Change: Use 'cp' for copying local files (hopefully fixes the 'get file bug') + +0.3.4: +-Add: Polish translation (thanks to qla) +-Add: Brazilian Portuguese translation (thanks to Leandro Santiago da Silva) +-Add: Spanish translation (thanks to Adrian Capel) +-Add: Support for ttaenc and bonk +-Add: Support for wvgain +-Fix: Show Replay Gain of flac files correctly +-Fix: Don't recalculate Replay Gain, if all files in an album show the same gain +-Fix: Some minor fixes +-Remove: Plugin update feature because my website is down + +0.3.3: +-Add: Russian translation (thanks to Ivan) +-Fix: Support autoconf >= 2.60 and automake >= 1.10 (thanks to Darwin Bautista) + +0.3.2: +-Add: French translation (thanks to Placisfos) +-Add: Support for TiMidity++ (decoding midi files) +-Fix: Display notification when a backend doesn't provide progress data +-Fix: Added audio/x-m4a mime type + +0.3.1: +-Add: Support for aacgain +-Add: Backend information in the readme file +-Fix: 2 Bugs where plugins couldn't be found + +0.3: +-Fix: Log viewer now gets updated correctly +-Fix: Replay Gain plugins in single file mode read output correctly +-Fix: File length is guessed, when tags can't be read (except remote files) +-Fix: Some special characters in file names were not supported: "?", "#", "/" +-Fix: Made english command line arguments work independent of the current language +-Fix: Made notification for new backends and plugin updates work +-Fix: Changing the output directory in simple mode would not be respected +-Fix: Some minor fixes + +0.3 rc1: +-Fix: Output names for CD tracks corrected +-Fix: Added 'hack' for writing id3v2 genre and year properly +-Fix: Reading backend output was improved +-Fix: Conversion of remote files +-Fix: Support for more kio slaves (system:/) +-Fix: Bug in service menu creation +-Fix: Improved the log viewer +-Fix: Previous options wouldn't be loaded properly +-Fix: Don't save last options, when started in invisible mode +-Fix: Detection of profiles wouldn't work properly +-Fix: Output directories sometimes got disarranged +-Fix: Using SIGKILL instead of SIGTERM solves a few problems +-Fix: Added check for cdparanoia in 'configure' (not tested) +-Fix: Some minor bugs +-Add: System tray icon, when starting soundKonverter in invisible mode +-Add: Amarok script works now (but it's very worthy of improvement) +-Add: German translation (plugin translations missing) + +0.3 beta1: +-Fix: Backends configuration page is rebuild properly and some general fixes +-Fix: Adding directories by dropping them, improved progress bar +-Fix: Code cleanups in the Replay Gain tool +-Fix: Always load the latest plugins available +-Fix: Make the tool bar work +-Add: Boyan Tabakov's patch for selecting cddb entries, if there were multiple found +-Add: Quality parameter preview as tool tip of the quality spin box +-Add: Force VFAT compatible output file names +-Add: Automaticly save file list when adding new items and converting items +-Change: The 'Copy directory structure' feature produces shorter paths +-Change: Removed the 'Default output directory', 'By meta data' is now default +-Change: Removed the about plugins dialog and added a plugins configuration page to the configuration dialog +-Change: The backends process priority has been moved to the config dialog + +0.3 alpha1: +Changed almost everything. The most important changes are: +-Add: CD ripping (including cddb and support for multiple devices and simultaneous ripping) +-Add: Converting multiple files at once +-Add: Editing of output options and tags +-Add: Support for discnumber and composer tags for ogg, mp3 and flac files +-Add: Tagging support for wma, ape, mp4, aac, aa and rm files +-Add: Support for Replay Gain in album mode including extended Replay Gain Tool +-Add: Custom profiles (including user defined commands) +-Add: Basic support for hybrid compression +-Add: KIO support (partly) +-Change: GUI cleanups +A big change is that soundKonverter now uses mime types. Unfortunately this causes a lot of problems. +Please report missing/wrong mime types! + +0.2: +Nothing done! + +0.2 rc2: +-Fix: Saving last options works now with different languages +-Fix: Calculation of remaining time corrected +-Fix: Replace / through \ when these characters are in tags that build the new file name +-Fix: When %[aAbBcCgGnNtTyY] is in a tag, it will not be replaced by the tag any longer. +-Fix: After a conversion is completed, the progress is calculated correct now. +Big thanks to Peter. + +0.2 rc1: +-Fix: Several bugs +-Add: Last options are saved now (Thx Angelo) +-Add: German Translation + +0.2 beta2: +-Fix: The output directory text box now isn't cleared after finishing a job. Thx Miguel +-Fix: The backend outputs are now read +-Fix: Setting the backend priority works now. For setting to a higher priority the root password is asked (kdesu) +-Fix: The toolbar works now correct +-Change: The menu can't be hidden now +-Change: The userinterface has been changed a bit. Thx Miguel +-Change: The Cue Editor now adds 0,5 sec. to each track +-Add: Spanish translation (partly) Thx Adrian Capel + +0.2 beta1: +-Fix: Moving the columns in the file list works now +-Change: You can now extend soundkonverter by plugins +-Change: We have now a menu and a (not complete working) toolbar +-Add: Support for ReplayGain +-Add: Convert the next file if an error happens +-Add: Load the last file list, if soundkonverter crashed +-Add: Scan for new backends and plugins on startup +-Add: A ReplayGain tool for tagging/untagging files +-Add: A cue-Editor - just a supplement to all these tag editors out there - documentation will follow +-Add: An amaroK-Script for easily accessing soundKonverter from out of amaroK +-Add: Support for creating output directories by the file's tags/copy the file's source directory structure + +0.1: +-Fix: Some spelling errors +-Fix: A compilation error +(Nothing really new, there is no need to upgrade) + +0.1 RC1: +-Fix: Installation of the servicemenu file +-Fix: Support for wma decoder if only mplayer was found +-Fix: 'Default' button in configuration Dialog +-Fix: Progressbar +-Change: Modifyed the userinterface a little bit +-Change: English handbook is now complete +-Add: German handbook + +0.1 beta2 update: +-Fix: Compilation error +-Fix: Scan for backends automatic + +0.1 beta2: +-Fix: KUniqueApplication works now +-Fix: A few irritations +-Add: Formats: ape, mpc +-Add: Translation: German +-Add: Handbook: English (not jet complete) +-Add: Some small features + +0.1 beta1: +Initial Release diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..02a4a07 --- /dev/null +++ b/INSTALL @@ -0,0 +1,167 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes a while. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Type `make install' to install the programs and any data files and + documentation. + + 4. You can remove the program binaries and object files from the + source code directory by typing `make clean'. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..8a2284f --- /dev/null +++ b/Makefile.am @@ -0,0 +1,22 @@ +SUBDIRS = $(TOPSUBDIRS) + +$(top_srcdir)/configure.in: configure.in.in $(top_srcdir)/subdirs + cd $(top_srcdir) && $(MAKE) -f admin/Makefile.common configure.in ; + +$(top_srcdir)/subdirs: + cd $(top_srcdir) && $(MAKE) -f admin/Makefile.common subdirs + +$(top_srcdir)/acinclude.m4: $(top_srcdir)/admin/acinclude.m4.in $(top_srcdir)/admin/libtool.m4.in + @cd $(top_srcdir) && cat admin/acinclude.m4.in admin/libtool.m4.in > acinclude.m4 + +MAINTAINERCLEANFILES = subdirs configure.in acinclude.m4 configure.files + +package-messages: + cd $(top_srcdir) && $(MAKE) -f admin/Makefile.common package-messages + $(MAKE) -C po merge + +EXTRA_DIST = admin COPYING configure.in.in + +dist-hook: + cd $(top_distdir) && perl admin/am_edit -padmin + cd $(top_distdir) && $(MAKE) -f admin/Makefile.common subdirs diff --git a/Makefile.cvs b/Makefile.cvs new file mode 100644 index 0000000..4c0afd1 --- /dev/null +++ b/Makefile.cvs @@ -0,0 +1,10 @@ +all: + @echo "This Makefile is only for the CVS repository" + @echo "This will be deleted before making the distribution" + @echo "" + $(MAKE) -f admin/Makefile.common cvs + +dist: + $(MAKE) -f admin/Makefile.common dist + +.SILENT: diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/README b/README new file mode 100644 index 0000000..f043066 --- /dev/null +++ b/README @@ -0,0 +1,160 @@ + +CONTENT +======= +1. About soundKonverter +2. Backends +3. Compile soundKonverter +4. Known bugs + + +1. About soundKonverter 0.3.8 +============================= + - Released by Daniel Faust (hessijames@gmail.com) under the terms of the GPL v2 - + +soundKonverter is frontend to various audio converters. + +The key features are: +- Audio conversion +- Replay Gain calculation +- CD ripping + +It is extendable by plugins and supports many backends: + En-/decoding: oggenc/oggdec, lame, gogo, faac/faad, mppenc/mppdec, flac, mac, mplayer, ffmpeg, shorten, ttaenc, bonk, ofr, ofs, wavpack, lac, lpac, speexenc/speexdec, timidity + Replay Gain: vorbisgain, mp3gain, aacgain, replaygain (MusePack), metaflac, wvgain + CD ripping: kio_audiocd, cdda2wav, cdparanoia +This way you can convert between various audio formats: + Decoding: ogg, mp3, mp2, m4a/mp4, aac, 3gp, mpc/mp+, flac, ape, wma, asf/asx, ra, rv, rm, avi, mpeg, wmv, qt/mov, flv, ac3, au/snd, shn, tta, bonk, ofr, ofs, wv, la, pac, spx, mid, mod/s3m/stm/ult/uni/xm/m15/mtm/669/it, wav + Encoing: ogg, mp3, mp2, m4a, aac, mpc, flac, ape, ra, ac3, au, shn, tta, bonk, ofr, ofs, wv, la, pac, spx, wav + +soundKonverter supports reading and writing tags for many formats, so the tags are preserved when converting files. +It comes with an Amarok script that allows you to easily transcode files when transfering to your media device. +And it is avalable in English, German, French, Spanish, Russian, Polish and Brazilian Portuguese. + +2. Backends +=========== + +110.oggvorbis.soundkonverter.xml + http://www.vorbis.com + +120.lame.soundkonverter.xml + http://lame.sf.net + +122.twolame.soundkonverter.xml + http://www.twolame.org + +123.toolame.soundkonverter.xml + http://toolame.sourceforge.net + +125.gogo.soundkonverter.xml + http://homepage2.nifty.com/kei-i/ + +127.faac.soundkonverter.xml + http://www.audiocoding.com + +130.musepack.soundkonverter.xml + http://www.musepack.net + +135.flac.soundkonverter.xml + http://flac.sourceforge.net + +137.mac.soundkonverter.xml + http://www.monkeysaudio.com + +140.mplayer.soundkonverter.xml + http://www.mplayerhq.hu + +145.ffmpeg.soundkonverter.xml + http://ffmpeg.mplayerhq.hu + +146.ffmpeg-lossless.soundkonverter.xml + Same as above, splitted just for internal use! + +150.shorten.soundkonverter.xml + http://www.hornig.net/shorten.html + +151.tta.soundkonverter.xml + http://tta.sourceforge.net + +153.bonk.soundkonverter.xml + http://www.logarithmic.net/pfh/bonk/ + +155.optimfrog.soundkonverter.xml + http://www.losslessaudio.org + +156.optimfrog-dualstream.soundkonverter.xml + http://www.losslessaudio.org + +158.wavpack.soundkonverter.xml + http://www.wavpack.com + +160.lac.soundkonverter.xml + Important: Rename the encoder "la" to "lac" because "la" is already used on linux! + http://www.lossless-audio.com + +165.lpac.soundkonverter.xml + http://www.nue.tu-berlin.de/wer/liebchen/lpac.html + +170.speex.soundkonverter.xml + http://www.speex.org + +180.timidity.soundkonverter.xml + http://timidity.sourceforge.net + +210.vorbisgain.soundkonverter.xml + http://sjeng.org/vorbisgain.html + +220.mp3gain.soundkonverter.xml + http://mp3gain.sourceforge.net + +225.aacgain.soundkonverter.xml + http://altosdesign.com/aacgain/ + +230.replaygain.soundkonverter.xml + This is the Replay Gain tool for musepack files! + http://www.musepack.net + +240.metaflac.soundkonverter.xml + http://flac.sourceforge.net + +250.wvgain.soundkonverter.xml + http://www.wavpack.com + +310.cdda2wav.soundkonverter.xml + http://www.cdda2wav.de + +320.cdparanoia.soundkonverter.xml + http://xiph.org/paranoia/ + + +3. Compile soundKonverter +========================= + +In order to compile soundKonverter, you need: +- taglib-devel 1.4.0 (libtaglib-devel on mandriva) +- cdparanoia (libcdda-devel on mandriva, cdparanoia-devel on fedora) + +On some operating systems, the cdda check (cdparanoia) in ./configure may fail. +This is because sometimes the header files are at another location (eg. /usr/include/cdda instead of /usr/include on ark linux). +In this case remove the cdparanoia check from the configure.in.in file. + + +4. Known bugs +============= + +- The options tabs get out of sync in some very rare cases +- taglib check in ./configure may fail + +Backends that's output cant't be read: +- The progress of some backends can't be read properly + +A big change is that soundKonverter now uses mime types. +If you find problems, please tell me about it. + + +Thanks to all Open Source programmers for their apps that I used to get some code. +Especially Kaffeine and Amarok. + +Have a lot of fun. + +Please send bug reports directly to hessijames@gmail.com + diff --git a/TODO b/TODO new file mode 100644 index 0000000..e69de29 diff --git a/acinclude.m4 b/acinclude.m4 new file mode 100644 index 0000000..207da05 --- /dev/null +++ b/acinclude.m4 @@ -0,0 +1,11810 @@ +## -*- autoconf -*- + +dnl This file is part of the KDE libraries/packages +dnl Copyright (C) 1997 Janos Farkas (chexum@shadow.banki.hu) +dnl (C) 1997,98,99 Stephan Kulow (coolo@kde.org) + +dnl This file is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Library General Public +dnl License as published by the Free Software Foundation; either +dnl version 2 of the License, or (at your option) any later version. + +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Library General Public License for more details. + +dnl You should have received a copy of the GNU Library General Public License +dnl along with this library; see the file COPYING.LIB. If not, write to +dnl the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +dnl Boston, MA 02110-1301, USA. + +dnl IMPORTANT NOTE: +dnl Please do not modify this file unless you expect your modifications to be +dnl carried into every other module in the repository. +dnl +dnl Single-module modifications are best placed in configure.in for kdelibs +dnl and kdebase or configure.in.in if present. + +# KDE_PATH_X_DIRECT +dnl Internal subroutine of AC_PATH_X. +dnl Set ac_x_includes and/or ac_x_libraries. +AC_DEFUN([KDE_PATH_X_DIRECT], +[ +AC_REQUIRE([KDE_CHECK_LIB64]) + +if test "$ac_x_includes" = NO; then + # Guess where to find include files, by looking for this one X11 .h file. + test -z "$x_direct_test_include" && x_direct_test_include=X11/Intrinsic.h + + # First, try using that file with no special directory specified. +AC_TRY_CPP([#include <$x_direct_test_include>], +[# We can compile using X headers with no special include directory. +ac_x_includes=], +[# Look for the header file in a standard set of common directories. +# Check X11 before X11Rn because it is often a symlink to the current release. + for ac_dir in \ + /usr/X11/include \ + /usr/X11R6/include \ + /usr/X11R5/include \ + /usr/X11R4/include \ + \ + /usr/include/X11 \ + /usr/include/X11R6 \ + /usr/include/X11R5 \ + /usr/include/X11R4 \ + \ + /usr/local/X11/include \ + /usr/local/X11R6/include \ + /usr/local/X11R5/include \ + /usr/local/X11R4/include \ + \ + /usr/local/include/X11 \ + /usr/local/include/X11R6 \ + /usr/local/include/X11R5 \ + /usr/local/include/X11R4 \ + \ + /usr/X386/include \ + /usr/x386/include \ + /usr/XFree86/include/X11 \ + \ + /usr/include \ + /usr/local/include \ + /usr/unsupported/include \ + /usr/athena/include \ + /usr/local/x11r5/include \ + /usr/lpp/Xamples/include \ + \ + /usr/openwin/include \ + /usr/openwin/share/include \ + ; \ + do + if test -r "$ac_dir/$x_direct_test_include"; then + ac_x_includes=$ac_dir + break + fi + done]) +fi # $ac_x_includes = NO + +if test "$ac_x_libraries" = NO; then + # Check for the libraries. + + test -z "$x_direct_test_library" && x_direct_test_library=Xt + test -z "$x_direct_test_function" && x_direct_test_function=XtMalloc + + # See if we find them without any special options. + # Don't add to $LIBS permanently. + ac_save_LIBS="$LIBS" + LIBS="-l$x_direct_test_library $LIBS" +AC_TRY_LINK([#include ], [${x_direct_test_function}(1)], +[LIBS="$ac_save_LIBS" +# We can link X programs with no special library path. +ac_x_libraries=], +[LIBS="$ac_save_LIBS" +# First see if replacing the include by lib works. +# Check X11 before X11Rn because it is often a symlink to the current release. +for ac_dir in `echo "$ac_x_includes" | sed s/include/lib${kdelibsuff}/` \ + /usr/X11/lib${kdelibsuff} \ + /usr/X11R6/lib${kdelibsuff} \ + /usr/X11R5/lib${kdelibsuff} \ + /usr/X11R4/lib${kdelibsuff} \ + \ + /usr/lib${kdelibsuff}/X11 \ + /usr/lib${kdelibsuff}/X11R6 \ + /usr/lib${kdelibsuff}/X11R5 \ + /usr/lib${kdelibsuff}/X11R4 \ + \ + /usr/local/X11/lib${kdelibsuff} \ + /usr/local/X11R6/lib${kdelibsuff} \ + /usr/local/X11R5/lib${kdelibsuff} \ + /usr/local/X11R4/lib${kdelibsuff} \ + \ + /usr/local/lib${kdelibsuff}/X11 \ + /usr/local/lib${kdelibsuff}/X11R6 \ + /usr/local/lib${kdelibsuff}/X11R5 \ + /usr/local/lib${kdelibsuff}/X11R4 \ + \ + /usr/X386/lib${kdelibsuff} \ + /usr/x386/lib${kdelibsuff} \ + /usr/XFree86/lib${kdelibsuff}/X11 \ + \ + /usr/lib${kdelibsuff} \ + /usr/local/lib${kdelibsuff} \ + /usr/unsupported/lib${kdelibsuff} \ + /usr/athena/lib${kdelibsuff} \ + /usr/local/x11r5/lib${kdelibsuff} \ + /usr/lpp/Xamples/lib${kdelibsuff} \ + /lib/usr/lib${kdelibsuff}/X11 \ + \ + /usr/openwin/lib${kdelibsuff} \ + /usr/openwin/share/lib${kdelibsuff} \ + ; \ +do +dnl Don't even attempt the hair of trying to link an X program! + for ac_extension in a so sl; do + if test -r $ac_dir/lib${x_direct_test_library}.$ac_extension; then + ac_x_libraries=$ac_dir + break 2 + fi + done +done]) +fi # $ac_x_libraries = NO +]) + + +dnl ------------------------------------------------------------------------ +dnl Find a file (or one of more files in a list of dirs) +dnl ------------------------------------------------------------------------ +dnl +AC_DEFUN([AC_FIND_FILE], +[ +$3=NO +for i in $2; +do + for j in $1; + do + echo "configure: __oline__: $i/$j" >&AC_FD_CC + if test -r "$i/$j"; then + echo "taking that" >&AC_FD_CC + $3=$i + break 2 + fi + done +done +]) + +dnl KDE_FIND_PATH(program-name, variable-name, list-of-dirs, +dnl if-not-found, test-parameter, prepend-path) +dnl +dnl Look for program-name in list-of-dirs+$PATH. +dnl If prepend-path is set, look in $PATH+list-of-dirs instead. +dnl If found, $variable-name is set. If not, if-not-found is evaluated. +dnl test-parameter: if set, the program is executed with this arg, +dnl and only a successful exit code is required. +AC_DEFUN([KDE_FIND_PATH], +[ + AC_MSG_CHECKING([for $1]) + if test -n "$$2"; then + kde_cv_path="$$2"; + else + kde_cache=`echo $1 | sed 'y%./+-%__p_%'` + + AC_CACHE_VAL(kde_cv_path_$kde_cache, + [ + kde_cv_path="NONE" + kde_save_IFS=$IFS + IFS=':' + dirs="" + for dir in $PATH; do + dirs="$dirs $dir" + done + if test -z "$6"; then dnl Append dirs in PATH (default) + dirs="$3 $dirs" + else dnl Prepend dirs in PATH (if 6th arg is set) + dirs="$dirs $3" + fi + IFS=$kde_save_IFS + + for dir in $dirs; do + if test -x "$dir/$1"; then + if test -n "$5" + then + evalstr="$dir/$1 $5 2>&1 " + if eval $evalstr; then + kde_cv_path="$dir/$1" + break + fi + else + kde_cv_path="$dir/$1" + break + fi + fi + done + + eval "kde_cv_path_$kde_cache=$kde_cv_path" + + ]) + + eval "kde_cv_path=\"`echo '$kde_cv_path_'$kde_cache`\"" + + fi + + if test -z "$kde_cv_path" || test "$kde_cv_path" = NONE; then + AC_MSG_RESULT(not found) + $4 + else + AC_MSG_RESULT($kde_cv_path) + $2=$kde_cv_path + + fi +]) + +AC_DEFUN([KDE_MOC_ERROR_MESSAGE], +[ + AC_MSG_ERROR([No Qt meta object compiler (moc) found! +Please check whether you installed Qt correctly. +You need to have a running moc binary. +configure tried to run $ac_cv_path_moc and the test didn't +succeed. If configure shouldn't have tried this one, set +the environment variable MOC to the right one before running +configure. +]) +]) + +AC_DEFUN([KDE_UIC_ERROR_MESSAGE], +[ + AC_MSG_WARN([No Qt ui compiler (uic) found! +Please check whether you installed Qt correctly. +You need to have a running uic binary. +configure tried to run $ac_cv_path_uic and the test didn't +succeed. If configure shouldn't have tried this one, set +the environment variable UIC to the right one before running +configure. +]) +]) + + +AC_DEFUN([KDE_CHECK_UIC_FLAG], +[ + AC_MSG_CHECKING([whether uic supports -$1 ]) + kde_cache=`echo $1 | sed 'y% .=/+-%____p_%'` + AC_CACHE_VAL(kde_cv_prog_uic_$kde_cache, + [ + cat >conftest.ui < +EOT + ac_uic_testrun="$UIC_PATH -$1 $2 conftest.ui >/dev/null" + if AC_TRY_EVAL(ac_uic_testrun); then + eval "kde_cv_prog_uic_$kde_cache=yes" + else + eval "kde_cv_prog_uic_$kde_cache=no" + fi + rm -f conftest* + ]) + + if eval "test \"`echo '$kde_cv_prog_uic_'$kde_cache`\" = yes"; then + AC_MSG_RESULT([yes]) + : + $3 + else + AC_MSG_RESULT([no]) + : + $4 + fi +]) + + +dnl ------------------------------------------------------------------------ +dnl Find the meta object compiler and the ui compiler in the PATH, +dnl in $QTDIR/bin, and some more usual places +dnl ------------------------------------------------------------------------ +dnl +AC_DEFUN([AC_PATH_QT_MOC_UIC], +[ + AC_REQUIRE([KDE_CHECK_PERL]) + qt_bindirs="" + for dir in $kde_qt_dirs; do + qt_bindirs="$qt_bindirs $dir/bin $dir/src/moc" + done + qt_bindirs="$qt_bindirs /usr/bin /usr/X11R6/bin /usr/local/qt/bin" + if test ! "$ac_qt_bindir" = "NO"; then + qt_bindirs="$ac_qt_bindir $qt_bindirs" + fi + + KDE_FIND_PATH(moc, MOC, [$qt_bindirs], [KDE_MOC_ERROR_MESSAGE]) + if test -z "$UIC_NOT_NEEDED"; then + KDE_FIND_PATH(uic, UIC_PATH, [$qt_bindirs], [UIC_PATH=""]) + if test -z "$UIC_PATH" ; then + KDE_UIC_ERROR_MESSAGE + exit 1 + else + UIC=$UIC_PATH + + if test $kde_qtver = 3; then + KDE_CHECK_UIC_FLAG(L,[/nonexistent],ac_uic_supports_libpath=yes,ac_uic_supports_libpath=no) + KDE_CHECK_UIC_FLAG(nounload,,ac_uic_supports_nounload=yes,ac_uic_supports_nounload=no) + + if test x$ac_uic_supports_libpath = xyes; then + UIC="$UIC -L \$(kde_widgetdir)" + fi + if test x$ac_uic_supports_nounload = xyes; then + UIC="$UIC -nounload" + fi + fi + fi + else + UIC="echo uic not available: " + fi + + AC_SUBST(MOC) + AC_SUBST(UIC) + + UIC_TR="i18n" + if test $kde_qtver = 3; then + UIC_TR="tr2i18n" + fi + + AC_SUBST(UIC_TR) +]) + +AC_DEFUN([KDE_1_CHECK_PATHS], +[ + KDE_1_CHECK_PATH_HEADERS + + KDE_TEST_RPATH= + + if test -n "$USE_RPATH"; then + + if test -n "$kde_libraries"; then + KDE_TEST_RPATH="-R $kde_libraries" + fi + + if test -n "$qt_libraries"; then + KDE_TEST_RPATH="$KDE_TEST_RPATH -R $qt_libraries" + fi + + if test -n "$x_libraries"; then + KDE_TEST_RPATH="$KDE_TEST_RPATH -R $x_libraries" + fi + + KDE_TEST_RPATH="$KDE_TEST_RPATH $KDE_EXTRA_RPATH" + fi + +AC_MSG_CHECKING([for KDE libraries installed]) +ac_link='$LIBTOOL_SHELL --silent --mode=link ${CXX-g++} -o conftest $CXXFLAGS $all_includes $CPPFLAGS $LDFLAGS $all_libraries conftest.$ac_ext $LIBS -lkdecore $LIBQT $KDE_TEST_RPATH 1>&5' + +if AC_TRY_EVAL(ac_link) && test -s conftest; then + AC_MSG_RESULT(yes) +else + AC_MSG_ERROR([your system fails at linking a small KDE application! +Check, if your compiler is installed correctly and if you have used the +same compiler to compile Qt and kdelibs as you did use now. +For more details about this problem, look at the end of config.log.]) +fi + +if eval `KDEDIR= ./conftest 2>&5`; then + kde_result=done +else + kde_result=problems +fi + +KDEDIR= ./conftest 2> /dev/null >&5 # make an echo for config.log +kde_have_all_paths=yes + +KDE_SET_PATHS($kde_result) + +]) + +AC_DEFUN([KDE_SET_PATHS], +[ + kde_cv_all_paths="kde_have_all_paths=\"yes\" \ + kde_htmldir=\"$kde_htmldir\" \ + kde_appsdir=\"$kde_appsdir\" \ + kde_icondir=\"$kde_icondir\" \ + kde_sounddir=\"$kde_sounddir\" \ + kde_datadir=\"$kde_datadir\" \ + kde_locale=\"$kde_locale\" \ + kde_cgidir=\"$kde_cgidir\" \ + kde_confdir=\"$kde_confdir\" \ + kde_kcfgdir=\"$kde_kcfgdir\" \ + kde_mimedir=\"$kde_mimedir\" \ + kde_toolbardir=\"$kde_toolbardir\" \ + kde_wallpaperdir=\"$kde_wallpaperdir\" \ + kde_templatesdir=\"$kde_templatesdir\" \ + kde_bindir=\"$kde_bindir\" \ + kde_servicesdir=\"$kde_servicesdir\" \ + kde_servicetypesdir=\"$kde_servicetypesdir\" \ + kde_moduledir=\"$kde_moduledir\" \ + kde_styledir=\"$kde_styledir\" \ + kde_widgetdir=\"$kde_widgetdir\" \ + xdg_appsdir=\"$xdg_appsdir\" \ + xdg_menudir=\"$xdg_menudir\" \ + xdg_directorydir=\"$xdg_directorydir\" \ + kde_result=$1" +]) + +AC_DEFUN([KDE_SET_DEFAULT_PATHS], +[ +if test "$1" = "default"; then + + if test -z "$kde_htmldir"; then + kde_htmldir='\${datadir}/doc/HTML' + fi + if test -z "$kde_appsdir"; then + kde_appsdir='\${datadir}/applnk' + fi + if test -z "$kde_icondir"; then + kde_icondir='\${datadir}/icons' + fi + if test -z "$kde_sounddir"; then + kde_sounddir='\${datadir}/sounds' + fi + if test -z "$kde_datadir"; then + kde_datadir='\${datadir}/apps' + fi + if test -z "$kde_locale"; then + kde_locale='\${datadir}/locale' + fi + if test -z "$kde_cgidir"; then + kde_cgidir='\${exec_prefix}/cgi-bin' + fi + if test -z "$kde_confdir"; then + kde_confdir='\${datadir}/config' + fi + if test -z "$kde_kcfgdir"; then + kde_kcfgdir='\${datadir}/config.kcfg' + fi + if test -z "$kde_mimedir"; then + kde_mimedir='\${datadir}/mimelnk' + fi + if test -z "$kde_toolbardir"; then + kde_toolbardir='\${datadir}/toolbar' + fi + if test -z "$kde_wallpaperdir"; then + kde_wallpaperdir='\${datadir}/wallpapers' + fi + if test -z "$kde_templatesdir"; then + kde_templatesdir='\${datadir}/templates' + fi + if test -z "$kde_bindir"; then + kde_bindir='\${exec_prefix}/bin' + fi + if test -z "$kde_servicesdir"; then + kde_servicesdir='\${datadir}/services' + fi + if test -z "$kde_servicetypesdir"; then + kde_servicetypesdir='\${datadir}/servicetypes' + fi + if test -z "$kde_moduledir"; then + if test "$kde_qtver" = "2"; then + kde_moduledir='\${libdir}/kde2' + else + kde_moduledir='\${libdir}/kde3' + fi + fi + if test -z "$kde_styledir"; then + kde_styledir='\${libdir}/kde3/plugins/styles' + fi + if test -z "$kde_widgetdir"; then + kde_widgetdir='\${libdir}/kde3/plugins/designer' + fi + if test -z "$xdg_appsdir"; then + xdg_appsdir='\${datadir}/applications/kde' + fi + if test -z "$xdg_menudir"; then + xdg_menudir='\${sysconfdir}/xdg/menus' + fi + if test -z "$xdg_directorydir"; then + xdg_directorydir='\${datadir}/desktop-directories' + fi + + KDE_SET_PATHS(defaults) + +else + + if test $kde_qtver = 1; then + AC_MSG_RESULT([compiling]) + KDE_1_CHECK_PATHS + else + AC_MSG_ERROR([path checking not yet supported for KDE 2]) + fi + +fi +]) + +AC_DEFUN([KDE_CHECK_PATHS_FOR_COMPLETENESS], +[ if test -z "$kde_htmldir" || test -z "$kde_appsdir" || + test -z "$kde_icondir" || test -z "$kde_sounddir" || + test -z "$kde_datadir" || test -z "$kde_locale" || + test -z "$kde_cgidir" || test -z "$kde_confdir" || + test -z "$kde_kcfgdir" || + test -z "$kde_mimedir" || test -z "$kde_toolbardir" || + test -z "$kde_wallpaperdir" || test -z "$kde_templatesdir" || + test -z "$kde_bindir" || test -z "$kde_servicesdir" || + test -z "$kde_servicetypesdir" || test -z "$kde_moduledir" || + test -z "$kde_styledir" || test -z "kde_widgetdir" || + test -z "$xdg_appsdir" || test -z "$xdg_menudir" || test -z "$xdg_directorydir" || + test "x$kde_have_all_paths" != "xyes"; then + kde_have_all_paths=no + fi +]) + +AC_DEFUN([KDE_MISSING_PROG_ERROR], +[ + AC_MSG_ERROR([The important program $1 was not found! +Please check whether you installed KDE correctly. +]) +]) + +AC_DEFUN([KDE_MISSING_ARTS_ERROR], +[ + AC_MSG_ERROR([The important program $1 was not found! +Please check whether you installed aRts correctly or use +--without-arts to compile without aRts support (this will remove functionality). +]) +]) + +AC_DEFUN([KDE_SET_DEFAULT_BINDIRS], +[ + kde_default_bindirs="/usr/bin /usr/local/bin /opt/local/bin /usr/X11R6/bin /opt/kde/bin /opt/kde3/bin /usr/kde/bin /usr/local/kde/bin" + test -n "$KDEDIR" && kde_default_bindirs="$KDEDIR/bin $kde_default_bindirs" + if test -n "$KDEDIRS"; then + kde_save_IFS=$IFS + IFS=: + for dir in $KDEDIRS; do + kde_default_bindirs="$dir/bin $kde_default_bindirs " + done + IFS=$kde_save_IFS + fi +]) + +AC_DEFUN([KDE_SUBST_PROGRAMS], +[ + AC_ARG_WITH(arts, + AC_HELP_STRING([--without-arts],[build without aRts [default=no]]), + [build_arts=$withval], + [build_arts=yes] + ) + AM_CONDITIONAL(include_ARTS, test "$build_arts" '!=' "no") + if test "$build_arts" = "no"; then + AC_DEFINE(WITHOUT_ARTS, 1, [Defined if compiling without arts]) + fi + + KDE_SET_DEFAULT_BINDIRS + kde_default_bindirs="$exec_prefix/bin $prefix/bin $kde_libs_prefix/bin $kde_default_bindirs" + KDE_FIND_PATH(dcopidl, DCOPIDL, [$kde_default_bindirs], [KDE_MISSING_PROG_ERROR(dcopidl)]) + KDE_FIND_PATH(dcopidl2cpp, DCOPIDL2CPP, [$kde_default_bindirs], [KDE_MISSING_PROG_ERROR(dcopidl2cpp)]) + if test "$build_arts" '!=' "no"; then + KDE_FIND_PATH(mcopidl, MCOPIDL, [$kde_default_bindirs], [KDE_MISSING_ARTS_ERROR(mcopidl)]) + KDE_FIND_PATH(artsc-config, ARTSCCONFIG, [$kde_default_bindirs], [KDE_MISSING_ARTS_ERROR(artsc-config)]) + fi + KDE_FIND_PATH(meinproc, MEINPROC, [$kde_default_bindirs]) + + kde32ornewer=1 + kde33ornewer=1 + if test -n "$kde_qtver" && test "$kde_qtver" -lt 3; then + kde32ornewer= + kde33ornewer= + else + if test "$kde_qtver" = "3"; then + if test "$kde_qtsubver" -le 1; then + kde32ornewer= + fi + if test "$kde_qtsubver" -le 2; then + kde33ornewer= + fi + if test "$KDECONFIG" != "compiled"; then + if test `$KDECONFIG --version | grep KDE | sed 's/KDE: \(...\).*/\1/'` = 3.2; then + kde33ornewer= + fi + fi + fi + fi + + if test -n "$kde32ornewer"; then + KDE_FIND_PATH(kconfig_compiler, KCONFIG_COMPILER, [$kde_default_bindirs], [KDE_MISSING_PROG_ERROR(kconfig_compiler)]) + KDE_FIND_PATH(dcopidlng, DCOPIDLNG, [$kde_default_bindirs], [KDE_MISSING_PROG_ERROR(dcopidlng)]) + fi + if test -n "$kde33ornewer"; then + KDE_FIND_PATH(makekdewidgets, MAKEKDEWIDGETS, [$kde_default_bindirs], [KDE_MISSING_PROG_ERROR(makekdewidgets)]) + AC_SUBST(MAKEKDEWIDGETS) + fi + KDE_FIND_PATH(xmllint, XMLLINT, [${prefix}/bin ${exec_prefix}/bin], [XMLLINT=""]) + + if test -n "$MEINPROC" -a "$MEINPROC" != "compiled"; then + kde_sharedirs="/usr/share/kde /usr/local/share /usr/share /opt/kde3/share /opt/kde/share $prefix/share" + test -n "$KDEDIR" && kde_sharedirs="$KDEDIR/share $kde_sharedirs" + AC_FIND_FILE(apps/ksgmltools2/customization/kde-chunk.xsl, $kde_sharedirs, KDE_XSL_STYLESHEET) + if test "$KDE_XSL_STYLESHEET" = "NO"; then + KDE_XSL_STYLESHEET="" + else + KDE_XSL_STYLESHEET="$KDE_XSL_STYLESHEET/apps/ksgmltools2/customization/kde-chunk.xsl" + fi + fi + + DCOP_DEPENDENCIES='$(DCOPIDL)' + if test -n "$kde32ornewer"; then + KCFG_DEPENDENCIES='$(KCONFIG_COMPILER)' + DCOP_DEPENDENCIES='$(DCOPIDL) $(DCOPIDLNG)' + AC_SUBST(KCONFIG_COMPILER) + AC_SUBST(KCFG_DEPENDENCIES) + AC_SUBST(DCOPIDLNG) + fi + AC_SUBST(DCOPIDL) + AC_SUBST(DCOPIDL2CPP) + AC_SUBST(DCOP_DEPENDENCIES) + AC_SUBST(MCOPIDL) + AC_SUBST(ARTSCCONFIG) + AC_SUBST(MEINPROC) + AC_SUBST(KDE_XSL_STYLESHEET) + AC_SUBST(XMLLINT) +])dnl + +AC_DEFUN([AC_CREATE_KFSSTND], +[ +AC_REQUIRE([AC_CHECK_RPATH]) + +AC_MSG_CHECKING([for KDE paths]) +kde_result="" +kde_cached_paths=yes +AC_CACHE_VAL(kde_cv_all_paths, +[ + KDE_SET_DEFAULT_PATHS($1) + kde_cached_paths=no +]) +eval "$kde_cv_all_paths" +KDE_CHECK_PATHS_FOR_COMPLETENESS +if test "$kde_have_all_paths" = "no" && test "$kde_cached_paths" = "yes"; then + # wrong values were cached, may be, we can set better ones + kde_result= + kde_htmldir= kde_appsdir= kde_icondir= kde_sounddir= + kde_datadir= kde_locale= kde_cgidir= kde_confdir= kde_kcfgdir= + kde_mimedir= kde_toolbardir= kde_wallpaperdir= kde_templatesdir= + kde_bindir= kde_servicesdir= kde_servicetypesdir= kde_moduledir= + kde_have_all_paths= + kde_styledir= + kde_widgetdir= + xdg_appsdir = xdg_menudir= xdg_directorydir= + KDE_SET_DEFAULT_PATHS($1) + eval "$kde_cv_all_paths" + KDE_CHECK_PATHS_FOR_COMPLETENESS + kde_result="$kde_result (cache overridden)" +fi +if test "$kde_have_all_paths" = "no"; then + AC_MSG_ERROR([configure could not run a little KDE program to test the environment. +Since it had compiled and linked before, it must be a strange problem on your system. +Look at config.log for details. If you are not able to fix this, look at +http://www.kde.org/faq/installation.html or any www.kde.org mirror. +(If you're using an egcs version on Linux, you may update binutils!) +]) +else + rm -f conftest* + AC_MSG_RESULT($kde_result) +fi + +bindir=$kde_bindir + +KDE_SUBST_PROGRAMS + +]) + +AC_DEFUN([AC_SUBST_KFSSTND], +[ +AC_SUBST(kde_htmldir) +AC_SUBST(kde_appsdir) +AC_SUBST(kde_icondir) +AC_SUBST(kde_sounddir) +AC_SUBST(kde_datadir) +AC_SUBST(kde_locale) +AC_SUBST(kde_confdir) +AC_SUBST(kde_kcfgdir) +AC_SUBST(kde_mimedir) +AC_SUBST(kde_wallpaperdir) +AC_SUBST(kde_bindir) +dnl X Desktop Group standards +AC_SUBST(xdg_appsdir) +AC_SUBST(xdg_menudir) +AC_SUBST(xdg_directorydir) +dnl for KDE 2 +AC_SUBST(kde_templatesdir) +AC_SUBST(kde_servicesdir) +AC_SUBST(kde_servicetypesdir) +AC_SUBST(kde_moduledir) +AC_SUBST(kdeinitdir, '$(kde_moduledir)') +AC_SUBST(kde_styledir) +AC_SUBST(kde_widgetdir) +if test "$kde_qtver" = 1; then + kde_minidir="$kde_icondir/mini" +else +# for KDE 1 - this breaks KDE2 apps using minidir, but +# that's the plan ;-/ + kde_minidir="/dev/null" +fi +dnl AC_SUBST(kde_minidir) +dnl AC_SUBST(kde_cgidir) +dnl AC_SUBST(kde_toolbardir) +]) + +AC_DEFUN([KDE_MISC_TESTS], +[ + dnl Checks for libraries. + AC_CHECK_LIB(util, main, [LIBUTIL="-lutil"]) dnl for *BSD + AC_SUBST(LIBUTIL) + AC_CHECK_LIB(compat, main, [LIBCOMPAT="-lcompat"]) dnl for *BSD + AC_SUBST(LIBCOMPAT) + kde_have_crypt= + AC_CHECK_LIB(crypt, crypt, [LIBCRYPT="-lcrypt"; kde_have_crypt=yes], + AC_CHECK_LIB(c, crypt, [kde_have_crypt=yes], [ + AC_MSG_WARN([you have no crypt in either libcrypt or libc. +You should install libcrypt from another source or configure with PAM +support]) + kde_have_crypt=no + ])) + AC_SUBST(LIBCRYPT) + if test $kde_have_crypt = yes; then + AC_DEFINE_UNQUOTED(HAVE_CRYPT, 1, [Defines if your system has the crypt function]) + fi + AC_CHECK_SOCKLEN_T + AC_CHECK_LIB(dnet, dnet_ntoa, [X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet"]) + if test $ac_cv_lib_dnet_dnet_ntoa = no; then + AC_CHECK_LIB(dnet_stub, dnet_ntoa, + [X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub"]) + fi + AC_CHECK_FUNC(inet_ntoa) + if test $ac_cv_func_inet_ntoa = no; then + AC_CHECK_LIB(nsl, inet_ntoa, X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl") + fi + AC_CHECK_FUNC(connect) + if test $ac_cv_func_connect = no; then + AC_CHECK_LIB(socket, connect, X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS", , + $X_EXTRA_LIBS) + fi + + AC_CHECK_FUNC(remove) + if test $ac_cv_func_remove = no; then + AC_CHECK_LIB(posix, remove, X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix") + fi + + # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. + AC_CHECK_FUNC(shmat, , + AC_CHECK_LIB(ipc, shmat, X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc")) + + # more headers that need to be explicitly included on darwin + AC_CHECK_HEADERS(sys/types.h stdint.h) + + # sys/bitypes.h is needed for uint32_t and friends on Tru64 + AC_CHECK_HEADERS(sys/bitypes.h) + + # darwin requires a poll emulation library + AC_CHECK_LIB(poll, poll, LIB_POLL="-lpoll") + + # for some image handling on Mac OS X + AC_CHECK_HEADERS(Carbon/Carbon.h) + + # CoreAudio framework + AC_CHECK_HEADER(CoreAudio/CoreAudio.h, [ + AC_DEFINE(HAVE_COREAUDIO, 1, [Define if you have the CoreAudio API]) + FRAMEWORK_COREAUDIO="-Xlinker -framework -Xlinker CoreAudio" + ]) + + AC_CHECK_RES_INIT + AC_SUBST(LIB_POLL) + AC_SUBST(FRAMEWORK_COREAUDIO) + LIBSOCKET="$X_EXTRA_LIBS" + AC_SUBST(LIBSOCKET) + AC_SUBST(X_EXTRA_LIBS) + AC_CHECK_LIB(ucb, killpg, [LIBUCB="-lucb"]) dnl for Solaris2.4 + AC_SUBST(LIBUCB) + + case $host in dnl this *is* LynxOS specific + *-*-lynxos* ) + AC_MSG_CHECKING([LynxOS header file wrappers]) + [CFLAGS="$CFLAGS -D__NO_INCLUDE_WARN__"] + AC_MSG_RESULT(disabled) + AC_CHECK_LIB(bsd, gethostbyname, [LIBSOCKET="-lbsd"]) dnl for LynxOS + ;; + esac + + KDE_CHECK_TYPES + KDE_CHECK_LIBDL + KDE_CHECK_STRLCPY + KDE_CHECK_PIE_SUPPORT + +# darwin needs this to initialize the environment +AC_CHECK_HEADERS(crt_externs.h) +AC_CHECK_FUNC(_NSGetEnviron, [AC_DEFINE(HAVE_NSGETENVIRON, 1, [Define if your system needs _NSGetEnviron to set up the environment])]) + +AH_VERBATIM(_DARWIN_ENVIRON, +[ +#if defined(HAVE_NSGETENVIRON) && defined(HAVE_CRT_EXTERNS_H) +# include +# include +# define environ (*_NSGetEnviron()) +#endif +]) + +AH_VERBATIM(_AIX_STRINGS_H_BZERO, +[ +/* + * AIX defines FD_SET in terms of bzero, but fails to include + * that defines bzero. + */ + +#if defined(_AIX) +#include +#endif +]) + +AC_CHECK_FUNCS([vsnprintf snprintf]) + +AH_VERBATIM(_TRU64,[ +/* + * On HP-UX, the declaration of vsnprintf() is needed every time ! + */ + +#if !defined(HAVE_VSNPRINTF) || defined(hpux) +#if __STDC__ +#include +#include +#else +#include +#endif +#ifdef __cplusplus +extern "C" +#endif +int vsnprintf(char *str, size_t n, char const *fmt, va_list ap); +#ifdef __cplusplus +extern "C" +#endif +int snprintf(char *str, size_t n, char const *fmt, ...); +#endif +]) + +]) + +dnl ------------------------------------------------------------------------ +dnl Find the header files and libraries for X-Windows. Extended the +dnl macro AC_PATH_X +dnl ------------------------------------------------------------------------ +dnl +AC_DEFUN([K_PATH_X], +[ +AC_REQUIRE([KDE_MISC_TESTS])dnl +AC_REQUIRE([KDE_CHECK_LIB64]) + +AC_ARG_ENABLE( + embedded, + AC_HELP_STRING([--enable-embedded],[link to Qt-embedded, don't use X]), + kde_use_qt_emb=$enableval, + kde_use_qt_emb=no +) + +AC_ARG_ENABLE( + qtopia, + AC_HELP_STRING([--enable-qtopia],[link to Qt-embedded, link to the Qtopia Environment]), + kde_use_qt_emb_palm=$enableval, + kde_use_qt_emb_palm=no +) + +AC_ARG_ENABLE( + mac, + AC_HELP_STRING([--enable-mac],[link to Qt/Mac (don't use X)]), + kde_use_qt_mac=$enableval, + kde_use_qt_mac=no +) + +# used to disable x11-specific stuff on special platforms +AM_CONDITIONAL(include_x11, test "$kde_use_qt_emb" = "no" && test "$kde_use_qt_mac" = "no") + +if test "$kde_use_qt_emb" = "no" && test "$kde_use_qt_mac" = "no"; then + +AC_MSG_CHECKING(for X) + +AC_CACHE_VAL(kde_cv_have_x, +[# One or both of the vars are not set, and there is no cached value. +if test "{$x_includes+set}" = set || test "$x_includes" = NONE; then + kde_x_includes=NO +else + kde_x_includes=$x_includes +fi +if test "{$x_libraries+set}" = set || test "$x_libraries" = NONE; then + kde_x_libraries=NO +else + kde_x_libraries=$x_libraries +fi + +# below we use the standard autoconf calls +ac_x_libraries=$kde_x_libraries +ac_x_includes=$kde_x_includes + +KDE_PATH_X_DIRECT +dnl AC_PATH_X_XMKMF picks /usr/lib as the path for the X libraries. +dnl Unfortunately, if compiling with the N32 ABI, this is not the correct +dnl location. The correct location is /usr/lib32 or an undefined value +dnl (the linker is smart enough to pick the correct default library). +dnl Things work just fine if you use just AC_PATH_X_DIRECT. +dnl Solaris has a similar problem. AC_PATH_X_XMKMF forces x_includes to +dnl /usr/openwin/include, which doesn't work. /usr/include does work, so +dnl x_includes should be left alone. +case "$host" in +mips-sgi-irix6*) + ;; +*-*-solaris*) + ;; +*) + _AC_PATH_X_XMKMF + if test -z "$ac_x_includes"; then + ac_x_includes="." + fi + if test -z "$ac_x_libraries"; then + ac_x_libraries="/usr/lib${kdelibsuff}" + fi +esac +#from now on we use our own again + +# when the user already gave --x-includes, we ignore +# what the standard autoconf macros told us. +if test "$kde_x_includes" = NO; then + kde_x_includes=$ac_x_includes +fi + +# for --x-libraries too +if test "$kde_x_libraries" = NO; then + kde_x_libraries=$ac_x_libraries +fi + +if test "$kde_x_includes" = NO; then + AC_MSG_ERROR([Can't find X includes. Please check your installation and add the correct paths!]) +fi + +if test "$kde_x_libraries" = NO; then + AC_MSG_ERROR([Can't find X libraries. Please check your installation and add the correct paths!]) +fi + +# Record where we found X for the cache. +kde_cv_have_x="have_x=yes \ + kde_x_includes=$kde_x_includes kde_x_libraries=$kde_x_libraries" +])dnl + +eval "$kde_cv_have_x" + +if test "$have_x" != yes; then + AC_MSG_RESULT($have_x) + no_x=yes +else + AC_MSG_RESULT([libraries $kde_x_libraries, headers $kde_x_includes]) +fi + +if test -z "$kde_x_includes" || test "x$kde_x_includes" = xNONE; then + X_INCLUDES="" + x_includes="."; dnl better than nothing :- + else + x_includes=$kde_x_includes + X_INCLUDES="-I$x_includes" +fi + +if test -z "$kde_x_libraries" || test "x$kde_x_libraries" = xNONE; then + X_LDFLAGS="" + x_libraries="/usr/lib"; dnl better than nothing :- + else + x_libraries=$kde_x_libraries + X_LDFLAGS="-L$x_libraries" +fi +all_includes="$X_INCLUDES" +all_libraries="$X_LDFLAGS $LDFLAGS_AS_NEEDED $LDFLAGS_NEW_DTAGS" + +# Check for libraries that X11R6 Xt/Xaw programs need. +ac_save_LDFLAGS="$LDFLAGS" +LDFLAGS="$LDFLAGS $X_LDFLAGS" +# SM needs ICE to (dynamically) link under SunOS 4.x (so we have to +# check for ICE first), but we must link in the order -lSM -lICE or +# we get undefined symbols. So assume we have SM if we have ICE. +# These have to be linked with before -lX11, unlike the other +# libraries we check for below, so use a different variable. +# --interran@uluru.Stanford.EDU, kb@cs.umb.edu. +AC_CHECK_LIB(ICE, IceConnectionNumber, + [LIBSM="-lSM -lICE"], , $X_EXTRA_LIBS) +LDFLAGS="$ac_save_LDFLAGS" + +LIB_X11='-lX11 $(LIBSOCKET)' + +AC_MSG_CHECKING(for libXext) +AC_CACHE_VAL(kde_cv_have_libXext, +[ +kde_ldflags_safe="$LDFLAGS" +kde_libs_safe="$LIBS" + +LDFLAGS="$LDFLAGS $X_LDFLAGS $USER_LDFLAGS" +LIBS="-lXext -lX11 $LIBSOCKET" + +AC_TRY_LINK([ +#include +#ifdef STDC_HEADERS +# include +#endif +], +[ +printf("hello Xext\n"); +], +kde_cv_have_libXext=yes, +kde_cv_have_libXext=no +) + +LDFLAGS=$kde_ldflags_safe +LIBS=$kde_libs_safe +]) + +AC_MSG_RESULT($kde_cv_have_libXext) + +if test "$kde_cv_have_libXext" = "no"; then + AC_MSG_ERROR([We need a working libXext to proceed. Since configure +can't find it itself, we stop here assuming that make wouldn't find +them either.]) +fi + +LIB_XEXT="-lXext" +QTE_NORTTI="" + +elif test "$kde_use_qt_emb" = "yes"; then + dnl We're using QT Embedded + CPPFLAGS=-DQWS + CXXFLAGS="$CXXFLAGS -fno-rtti" + QTE_NORTTI="-fno-rtti -DQWS" + X_PRE_LIBS="" + LIB_X11="" + LIB_XEXT="" + LIB_XRENDER="" + LIBSM="" + X_INCLUDES="" + X_LDFLAGS="" + x_includes="" + x_libraries="" +elif test "$kde_use_qt_mac" = "yes"; then + dnl We're using QT/Mac (I use QT_MAC so that qglobal.h doesn't *have* to + dnl be included to get the information) --Sam + CXXFLAGS="$CXXFLAGS -DQT_MAC -no-cpp-precomp" + CFLAGS="$CFLAGS -DQT_MAC -no-cpp-precomp" + X_PRE_LIBS="" + LIB_X11="" + LIB_XEXT="" + LIB_XRENDER="" + LIBSM="" + X_INCLUDES="" + X_LDFLAGS="" + x_includes="" + x_libraries="" +fi +AC_SUBST(X_PRE_LIBS) +AC_SUBST(LIB_X11) +AC_SUBST(LIB_XRENDER) +AC_SUBST(LIBSM) +AC_SUBST(X_INCLUDES) +AC_SUBST(X_LDFLAGS) +AC_SUBST(x_includes) +AC_SUBST(x_libraries) +AC_SUBST(QTE_NORTTI) +AC_SUBST(LIB_XEXT) + +]) + +AC_DEFUN([KDE_PRINT_QT_PROGRAM], +[ +AC_REQUIRE([KDE_USE_QT]) +cat > conftest.$ac_ext < +#include +EOF +if test "$kde_qtver" = "2"; then +cat >> conftest.$ac_ext < +#include +#include +EOF + +if test $kde_qtsubver -gt 0; then +cat >> conftest.$ac_ext <> conftest.$ac_ext < +#include +#include +EOF +fi + +echo "#if ! ($kde_qt_verstring)" >> conftest.$ac_ext +cat >> conftest.$ac_ext <> conftest.$ac_ext <> conftest.$ac_ext <> conftest.$ac_ext <> conftest.$ac_ext <&AC_FD_CC + cat conftest.$ac_ext >&AC_FD_CC +fi + +rm -f conftest* +CXXFLAGS="$ac_cxxflags_safe" +LDFLAGS="$ac_ldflags_safe" +LIBS="$ac_libs_safe" + +LD_LIBRARY_PATH="$ac_LD_LIBRARY_PATH_safe" +export LD_LIBRARY_PATH +LIBRARY_PATH="$ac_LIBRARY_PATH" +export LIBRARY_PATH +AC_LANG_RESTORE +]) + +if test "$kde_cv_qt_direct" = "yes"; then + AC_MSG_RESULT(yes) + $1 +else + AC_MSG_RESULT(no) + $2 +fi +]) + +dnl ------------------------------------------------------------------------ +dnl Try to find the Qt headers and libraries. +dnl $(QT_LDFLAGS) will be -Lqtliblocation (if needed) +dnl and $(QT_INCLUDES) will be -Iqthdrlocation (if needed) +dnl ------------------------------------------------------------------------ +dnl +AC_DEFUN([AC_PATH_QT_1_3], +[ +AC_REQUIRE([K_PATH_X]) +AC_REQUIRE([KDE_USE_QT]) +AC_REQUIRE([KDE_CHECK_LIB64]) + +dnl ------------------------------------------------------------------------ +dnl Add configure flag to enable linking to MT version of Qt library. +dnl ------------------------------------------------------------------------ + +AC_ARG_ENABLE( + mt, + AC_HELP_STRING([--disable-mt],[link to non-threaded Qt (deprecated)]), + kde_use_qt_mt=$enableval, + [ + if test $kde_qtver = 3; then + kde_use_qt_mt=yes + else + kde_use_qt_mt=no + fi + ] +) + +USING_QT_MT="" + +dnl ------------------------------------------------------------------------ +dnl If we not get --disable-qt-mt then adjust some vars for the host. +dnl ------------------------------------------------------------------------ + +KDE_MT_LDFLAGS= +KDE_MT_LIBS= +if test "x$kde_use_qt_mt" = "xyes"; then + KDE_CHECK_THREADING + if test "x$kde_use_threading" = "xyes"; then + CPPFLAGS="$USE_THREADS -DQT_THREAD_SUPPORT $CPPFLAGS" + KDE_MT_LDFLAGS="$USE_THREADS" + KDE_MT_LIBS="$LIBPTHREAD" + else + kde_use_qt_mt=no + fi +fi +AC_SUBST(KDE_MT_LDFLAGS) +AC_SUBST(KDE_MT_LIBS) + +kde_qt_was_given=yes + +dnl ------------------------------------------------------------------------ +dnl If we haven't been told how to link to Qt, we work it out for ourselves. +dnl ------------------------------------------------------------------------ +if test -z "$LIBQT_GLOB"; then + if test "x$kde_use_qt_emb" = "xyes"; then + LIBQT_GLOB="libqte.*" + else + LIBQT_GLOB="libqt.*" + fi +fi + +dnl ------------------------------------------------------------ +dnl If we got --enable-embedded then adjust the Qt library name. +dnl ------------------------------------------------------------ +if test "x$kde_use_qt_emb" = "xyes"; then + qtlib="qte" +else + qtlib="qt" +fi + +kde_int_qt="-l$qtlib" + +if test -z "$LIBQPE"; then +dnl ------------------------------------------------------------ +dnl If we got --enable-palmtop then add -lqpe to the link line +dnl ------------------------------------------------------------ + if test "x$kde_use_qt_emb" = "xyes"; then + if test "x$kde_use_qt_emb_palm" = "xyes"; then + LIB_QPE="-lqpe" + else + LIB_QPE="" + fi + else + LIB_QPE="" + fi +fi + +dnl ------------------------------------------------------------------------ +dnl If we got --enable-qt-mt then adjust the Qt library name for the host. +dnl ------------------------------------------------------------------------ + +if test "x$kde_use_qt_mt" = "xyes"; then + LIBQT="-l$qtlib-mt" + kde_int_qt="-l$qtlib-mt" + LIBQT_GLOB="lib$qtlib-mt.*" + USING_QT_MT="using -mt" +else + LIBQT="-l$qtlib" +fi + +if test $kde_qtver != 1; then + + AC_REQUIRE([AC_FIND_PNG]) + AC_REQUIRE([AC_FIND_JPEG]) + LIBQT="$LIBQT $LIBPNG $LIBJPEG" +fi + +if test $kde_qtver = 3; then + AC_REQUIRE([KDE_CHECK_LIBDL]) + LIBQT="$LIBQT $LIBDL" +fi + +AC_MSG_CHECKING([for Qt]) + +if test "x$kde_use_qt_emb" != "xyes" && test "x$kde_use_qt_mac" != "xyes"; then +LIBQT="$LIBQT $X_PRE_LIBS -lXext -lX11 $LIBSM $LIBSOCKET" +fi +ac_qt_includes=NO ac_qt_libraries=NO ac_qt_bindir=NO +qt_libraries="" +qt_includes="" +AC_ARG_WITH(qt-dir, + AC_HELP_STRING([--with-qt-dir=DIR],[where the root of Qt is installed ]), + [ ac_qt_includes="$withval"/include + ac_qt_libraries="$withval"/lib${kdelibsuff} + ac_qt_bindir="$withval"/bin + ]) + +AC_ARG_WITH(qt-includes, + AC_HELP_STRING([--with-qt-includes=DIR],[where the Qt includes are. ]), + [ + ac_qt_includes="$withval" + ]) + +kde_qt_libs_given=no + +AC_ARG_WITH(qt-libraries, + AC_HELP_STRING([--with-qt-libraries=DIR],[where the Qt library is installed.]), + [ ac_qt_libraries="$withval" + kde_qt_libs_given=yes + ]) + +AC_CACHE_VAL(ac_cv_have_qt, +[#try to guess Qt locations + +qt_incdirs="" +for dir in $kde_qt_dirs; do + qt_incdirs="$qt_incdirs $dir/include $dir" +done +qt_incdirs="$QTINC $qt_incdirs /usr/local/qt/include /usr/include/qt /usr/include /usr/X11R6/include/X11/qt /usr/X11R6/include/qt /usr/X11R6/include/qt2 /usr/include/qt3 $x_includes" +if test ! "$ac_qt_includes" = "NO"; then + qt_incdirs="$ac_qt_includes $qt_incdirs" +fi + +if test "$kde_qtver" != "1"; then + kde_qt_header=qstyle.h +else + kde_qt_header=qglobal.h +fi + +AC_FIND_FILE($kde_qt_header, $qt_incdirs, qt_incdir) +ac_qt_includes="$qt_incdir" + +qt_libdirs="" +for dir in $kde_qt_dirs; do + qt_libdirs="$qt_libdirs $dir/lib${kdelibsuff} $dir" +done +qt_libdirs="$QTLIB $qt_libdirs /usr/X11R6/lib /usr/lib /usr/local/qt/lib $x_libraries" +if test ! "$ac_qt_libraries" = "NO"; then + qt_libdir=$ac_qt_libraries +else + qt_libdirs="$ac_qt_libraries $qt_libdirs" + # if the Qt was given, the chance is too big that libqt.* doesn't exist + qt_libdir=NONE + for dir in $qt_libdirs; do + try="ls -1 $dir/${LIBQT_GLOB}" + if test -n "`$try 2> /dev/null`"; then qt_libdir=$dir; break; else echo "tried $dir" >&AC_FD_CC ; fi + done +fi +for a in $qt_libdir/lib`echo ${kde_int_qt} | sed 's,^-l,,'`_incremental.*; do + if test -e "$a"; then + LIBQT="$LIBQT ${kde_int_qt}_incremental" + break + fi +done + +ac_qt_libraries="$qt_libdir" + +AC_LANG_SAVE +AC_LANG_CPLUSPLUS + +ac_cxxflags_safe="$CXXFLAGS" +ac_ldflags_safe="$LDFLAGS" +ac_libs_safe="$LIBS" + +CXXFLAGS="$CXXFLAGS -I$qt_incdir $all_includes" +LDFLAGS="$LDFLAGS -L$qt_libdir $all_libraries $USER_LDFLAGS $KDE_MT_LDFLAGS" +LIBS="$LIBS $LIBQT $KDE_MT_LIBS" + +KDE_PRINT_QT_PROGRAM + +if AC_TRY_EVAL(ac_link) && test -s conftest; then + rm -f conftest* +else + echo "configure: failed program was:" >&AC_FD_CC + cat conftest.$ac_ext >&AC_FD_CC + ac_qt_libraries="NO" +fi +rm -f conftest* +CXXFLAGS="$ac_cxxflags_safe" +LDFLAGS="$ac_ldflags_safe" +LIBS="$ac_libs_safe" + +AC_LANG_RESTORE +if test "$ac_qt_includes" = NO || test "$ac_qt_libraries" = NO; then + ac_cv_have_qt="have_qt=no" + ac_qt_notfound="" + missing_qt_mt="" + if test "$ac_qt_includes" = NO; then + if test "$ac_qt_libraries" = NO; then + ac_qt_notfound="(headers and libraries)"; + else + ac_qt_notfound="(headers)"; + fi + else + if test "x$kde_use_qt_mt" = "xyes"; then + missing_qt_mt=" +Make sure that you have compiled Qt with thread support!" + ac_qt_notfound="(library $qtlib-mt)"; + else + ac_qt_notfound="(library $qtlib)"; + fi + fi + + AC_MSG_ERROR([Qt ($kde_qt_minversion) $ac_qt_notfound not found. Please check your installation! +For more details about this problem, look at the end of config.log.$missing_qt_mt]) +else + have_qt="yes" +fi +]) + +eval "$ac_cv_have_qt" + +if test "$have_qt" != yes; then + AC_MSG_RESULT([$have_qt]); +else + ac_cv_have_qt="have_qt=yes \ + ac_qt_includes=$ac_qt_includes ac_qt_libraries=$ac_qt_libraries" + AC_MSG_RESULT([libraries $ac_qt_libraries, headers $ac_qt_includes $USING_QT_MT]) + + qt_libraries="$ac_qt_libraries" + qt_includes="$ac_qt_includes" +fi + +if test ! "$kde_qt_libs_given" = "yes" && test ! "$kde_qtver" = 3; then + KDE_CHECK_QT_DIRECT(qt_libraries= ,[]) +fi + +AC_SUBST(qt_libraries) +AC_SUBST(qt_includes) + +if test "$qt_includes" = "$x_includes" || test -z "$qt_includes"; then + QT_INCLUDES="" +else + QT_INCLUDES="-I$qt_includes" + all_includes="$QT_INCLUDES $all_includes" +fi + +if test "$qt_libraries" = "$x_libraries" || test -z "$qt_libraries"; then + QT_LDFLAGS="" +else + QT_LDFLAGS="-L$qt_libraries" + all_libraries="$QT_LDFLAGS $all_libraries" +fi +test -z "$KDE_MT_LDFLAGS" || all_libraries="$all_libraries $KDE_MT_LDFLAGS" + +AC_SUBST(QT_INCLUDES) +AC_SUBST(QT_LDFLAGS) +AC_PATH_QT_MOC_UIC + +KDE_CHECK_QT_JPEG + +if test "x$kde_use_qt_emb" != "xyes" && test "x$kde_use_qt_mac" != "xyes"; then +LIB_QT="$kde_int_qt $LIBJPEG_QT "'$(LIBZ) $(LIBPNG) -lXext $(LIB_X11) $(LIBSM)' +else +LIB_QT="$kde_int_qt $LIBJPEG_QT "'$(LIBZ) $(LIBPNG)' +fi +test -z "$KDE_MT_LIBS" || LIB_QT="$LIB_QT $KDE_MT_LIBS" +for a in $qt_libdir/lib`echo ${kde_int_qt} | sed 's,^-l,,'`_incremental.*; do + if test -e "$a"; then + LIB_QT="$LIB_QT ${kde_int_qt}_incremental" + break + fi +done + +AC_SUBST(LIB_QT) +AC_SUBST(LIB_QPE) + +AC_SUBST(kde_qtver) +]) + +AC_DEFUN([AC_PATH_QT], +[ +AC_PATH_QT_1_3 +]) + +AC_DEFUN([KDE_CHECK_UIC_PLUGINS], +[ +AC_REQUIRE([AC_PATH_QT_MOC_UIC]) + +if test x$ac_uic_supports_libpath = xyes; then + +AC_MSG_CHECKING([if UIC has KDE plugins available]) +AC_CACHE_VAL(kde_cv_uic_plugins, +[ +cat > actest.ui << EOF + +NewConnectionDialog + + + + testInput + + + + +EOF + + + +kde_cv_uic_plugins=no +kde_line="$UIC_PATH -L $kde_widgetdir" +if test x$ac_uic_supports_nounload = xyes; then + kde_line="$kde_line -nounload" +fi +kde_line="$kde_line -impl actest.h actest.ui > actest.cpp" +if AC_TRY_EVAL(kde_line); then + # if you're trying to debug this check and think it's incorrect, + # better check your installation. The check _is_ correct - your + # installation is not. + if test -f actest.cpp && grep klineedit actest.cpp > /dev/null; then + kde_cv_uic_plugins=yes + fi +fi +rm -f actest.ui actest.cpp +]) + +AC_MSG_RESULT([$kde_cv_uic_plugins]) +if test "$kde_cv_uic_plugins" != yes; then + AC_MSG_ERROR([ +you need to install kdelibs first. + +If you did install kdelibs, then the Qt version that is picked up by +this configure is not the same version you used to compile kdelibs. +The Qt Plugin installed by kdelibs is *ONLY* loadable if it is the +_same Qt version_, compiled with the _same compiler_ and the same Qt +configuration settings. +]) +fi +fi +]) + +AC_DEFUN([KDE_CHECK_FINAL], +[ + AC_ARG_ENABLE(final, + AC_HELP_STRING([--enable-final], + [build size optimized apps (experimental - needs lots of memory)]), + kde_use_final=$enableval, kde_use_final=no) + + if test "x$kde_use_final" = "xyes"; then + KDE_USE_FINAL_TRUE="" + KDE_USE_FINAL_FALSE="#" + else + KDE_USE_FINAL_TRUE="#" + KDE_USE_FINAL_FALSE="" + fi + AC_SUBST(KDE_USE_FINAL_TRUE) + AC_SUBST(KDE_USE_FINAL_FALSE) +]) + +AC_DEFUN([KDE_CHECK_CLOSURE], +[ + AC_ARG_ENABLE(closure, + AC_HELP_STRING([--enable-closure],[delay template instantiation]), + kde_use_closure=$enableval, kde_use_closure=no) + + KDE_NO_UNDEFINED="" + if test "x$kde_use_closure" = "xyes"; then + KDE_USE_CLOSURE_TRUE="" + KDE_USE_CLOSURE_FALSE="#" +# CXXFLAGS="$CXXFLAGS $REPO" + else + KDE_USE_CLOSURE_TRUE="#" + KDE_USE_CLOSURE_FALSE="" + KDE_NO_UNDEFINED="" + case $host in + *-*-linux-gnu) + KDE_CHECK_COMPILER_FLAG([Wl,--no-undefined], + [KDE_CHECK_COMPILER_FLAG([Wl,--allow-shlib-undefined], + [KDE_NO_UNDEFINED="-Wl,--no-undefined -Wl,--allow-shlib-undefined"], + [KDE_NO_UNDEFINED=""])], + [KDE_NO_UNDEFINED=""]) + ;; + esac + fi + AC_SUBST(KDE_USE_CLOSURE_TRUE) + AC_SUBST(KDE_USE_CLOSURE_FALSE) + AC_SUBST(KDE_NO_UNDEFINED) +]) + +dnl Check if the linker supports --enable-new-dtags and --as-needed +AC_DEFUN([KDE_CHECK_NEW_LDFLAGS], +[ + AC_ARG_ENABLE(new_ldflags, + AC_HELP_STRING([--enable-new-ldflags], + [enable the new linker flags]), + kde_use_new_ldflags=$enableval, + kde_use_new_ldflags=no) + + LDFLAGS_AS_NEEDED="" + LDFLAGS_NEW_DTAGS="" + if test "x$kde_use_new_ldflags" = "xyes"; then + LDFLAGS_NEW_DTAGS="" + KDE_CHECK_COMPILER_FLAG([Wl,--enable-new-dtags], + [LDFLAGS_NEW_DTAGS="-Wl,--enable-new-dtags"],) + + KDE_CHECK_COMPILER_FLAG([Wl,--as-needed], + [LDFLAGS_AS_NEEDED="-Wl,--as-needed"],) + fi + AC_SUBST(LDFLAGS_AS_NEEDED) + AC_SUBST(LDFLAGS_NEW_DTAGS) +]) + +AC_DEFUN([KDE_CHECK_NMCHECK], +[ + AC_ARG_ENABLE(nmcheck,AC_HELP_STRING([--enable-nmcheck],[enable automatic namespace cleanness check]), + kde_use_nmcheck=$enableval, kde_use_nmcheck=no) + + if test "$kde_use_nmcheck" = "yes"; then + KDE_USE_NMCHECK_TRUE="" + KDE_USE_NMCHECK_FALSE="#" + else + KDE_USE_NMCHECK_TRUE="#" + KDE_USE_NMCHECK_FALSE="" + fi + AC_SUBST(KDE_USE_NMCHECK_TRUE) + AC_SUBST(KDE_USE_NMCHECK_FALSE) +]) + +AC_DEFUN([KDE_EXPAND_MAKEVAR], [ +savex=$exec_prefix +test "x$exec_prefix" = xNONE && exec_prefix=$prefix +tmp=$$2 +while $1=`eval echo "$tmp"`; test "x$$1" != "x$tmp"; do tmp=$$1; done +exec_prefix=$savex +]) + +dnl ------------------------------------------------------------------------ +dnl Now, the same with KDE +dnl $(KDE_LDFLAGS) will be the kdeliblocation (if needed) +dnl and $(kde_includes) will be the kdehdrlocation (if needed) +dnl ------------------------------------------------------------------------ +dnl +AC_DEFUN([AC_BASE_PATH_KDE], +[ +AC_REQUIRE([KDE_CHECK_STL]) +AC_REQUIRE([AC_PATH_QT])dnl +AC_REQUIRE([KDE_CHECK_LIB64]) + +AC_CHECK_RPATH +AC_MSG_CHECKING([for KDE]) + +if test "${prefix}" != NONE; then + kde_includes=${includedir} + KDE_EXPAND_MAKEVAR(ac_kde_includes, includedir) + + kde_libraries=${libdir} + KDE_EXPAND_MAKEVAR(ac_kde_libraries, libdir) + +else + ac_kde_includes= + ac_kde_libraries= + kde_libraries="" + kde_includes="" +fi + +AC_CACHE_VAL(ac_cv_have_kde, +[#try to guess kde locations + +if test "$kde_qtver" = 1; then + kde_check_header="ksock.h" + kde_check_lib="libkdecore.la" +else + kde_check_header="ksharedptr.h" + kde_check_lib="libkio.la" +fi + +if test -z "$1"; then + +kde_incdirs="$kde_libs_prefix/include /usr/lib/kde/include /usr/local/kde/include /usr/local/include /usr/kde/include /usr/include/kde /usr/include /opt/kde3/include /opt/kde/include $x_includes $qt_includes" +test -n "$KDEDIR" && kde_incdirs="$KDEDIR/include $KDEDIR/include/kde $KDEDIR $kde_incdirs" +kde_incdirs="$ac_kde_includes $kde_incdirs" +AC_FIND_FILE($kde_check_header, $kde_incdirs, kde_incdir) +ac_kde_includes="$kde_incdir" + +if test -n "$ac_kde_includes" && test ! -r "$ac_kde_includes/$kde_check_header"; then + AC_MSG_ERROR([ +in the prefix, you've chosen, are no KDE headers installed. This will fail. +So, check this please and use another prefix!]) +fi + +kde_libdirs="$kde_libs_prefix/lib${kdelibsuff} /usr/lib/kde/lib${kdelibsuff} /usr/local/kde/lib${kdelibsuff} /usr/kde/lib${kdelibsuff} /usr/lib${kdelibsuff}/kde /usr/lib${kdelibsuff}/kde3 /usr/lib${kdelibsuff} /usr/X11R6/lib${kdelibsuff} /usr/local/lib${kdelibsuff} /opt/kde3/lib${kdelibsuff} /opt/kde/lib${kdelibsuff} /usr/X11R6/kde/lib${kdelibsuff}" +test -n "$KDEDIR" && kde_libdirs="$KDEDIR/lib${kdelibsuff} $KDEDIR $kde_libdirs" +kde_libdirs="$ac_kde_libraries $libdir $kde_libdirs" +AC_FIND_FILE($kde_check_lib, $kde_libdirs, kde_libdir) +ac_kde_libraries="$kde_libdir" + +kde_widgetdir=NO +dnl this might be somewhere else +AC_FIND_FILE("kde3/plugins/designer/kdewidgets.la", $kde_libdirs, kde_widgetdir) + +if test -n "$ac_kde_libraries" && test ! -r "$ac_kde_libraries/$kde_check_lib"; then +AC_MSG_ERROR([ +in the prefix, you've chosen, are no KDE libraries installed. This will fail. +So, check this please and use another prefix!]) +fi + +if test -n "$kde_widgetdir" && test ! -r "$kde_widgetdir/kde3/plugins/designer/kdewidgets.la"; then +AC_MSG_ERROR([ +I can't find the designer plugins. These are required and should have been installed +by kdelibs]) +fi + +if test -n "$kde_widgetdir"; then + kde_widgetdir="$kde_widgetdir/kde3/plugins/designer" +fi + + +if test "$ac_kde_includes" = NO || test "$ac_kde_libraries" = NO || test "$kde_widgetdir" = NO; then + ac_cv_have_kde="have_kde=no" +else + ac_cv_have_kde="have_kde=yes \ + ac_kde_includes=$ac_kde_includes ac_kde_libraries=$ac_kde_libraries" +fi + +else dnl test -z $1, e.g. from kdelibs + + ac_cv_have_kde="have_kde=no" + +fi +])dnl + +eval "$ac_cv_have_kde" + +if test "$have_kde" != "yes"; then + if test "${prefix}" = NONE; then + ac_kde_prefix="$ac_default_prefix" + else + ac_kde_prefix="$prefix" + fi + if test "$exec_prefix" = NONE; then + ac_kde_exec_prefix="$ac_kde_prefix" + AC_MSG_RESULT([will be installed in $ac_kde_prefix]) + else + ac_kde_exec_prefix="$exec_prefix" + AC_MSG_RESULT([will be installed in $ac_kde_prefix and $ac_kde_exec_prefix]) + fi + + kde_libraries="${libdir}" + kde_includes="${includedir}" + +else + ac_cv_have_kde="have_kde=yes \ + ac_kde_includes=$ac_kde_includes ac_kde_libraries=$ac_kde_libraries" + AC_MSG_RESULT([libraries $ac_kde_libraries, headers $ac_kde_includes]) + + kde_libraries="$ac_kde_libraries" + kde_includes="$ac_kde_includes" +fi +AC_SUBST(kde_libraries) +AC_SUBST(kde_includes) + +if test "$kde_includes" = "$x_includes" || test "$kde_includes" = "$qt_includes" || test "$kde_includes" = "/usr/include"; then + KDE_INCLUDES="" +else + KDE_INCLUDES="-I$kde_includes" + all_includes="$KDE_INCLUDES $all_includes" +fi + +KDE_DEFAULT_CXXFLAGS="-DQT_CLEAN_NAMESPACE -DQT_NO_ASCII_CAST -DQT_NO_STL -DQT_NO_COMPAT -DQT_NO_TRANSLATION" + +KDE_LDFLAGS="-L$kde_libraries" +if test ! "$kde_libraries" = "$x_libraries" && test ! "$kde_libraries" = "$qt_libraries" ; then + all_libraries="$KDE_LDFLAGS $all_libraries" +fi + +AC_SUBST(KDE_LDFLAGS) +AC_SUBST(KDE_INCLUDES) + +AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) + +all_libraries="$all_libraries $USER_LDFLAGS" +all_includes="$all_includes $USER_INCLUDES" +AC_SUBST(all_includes) +AC_SUBST(all_libraries) + +if test -z "$1"; then +KDE_CHECK_UIC_PLUGINS +fi + +ac_kde_libraries="$kde_libdir" + +AC_SUBST(AUTODIRS) + + +]) + +AC_DEFUN([KDE_CHECK_EXTRA_LIBS], +[ +AC_MSG_CHECKING(for extra includes) +AC_ARG_WITH(extra-includes,AC_HELP_STRING([--with-extra-includes=DIR],[adds non standard include paths]), + kde_use_extra_includes="$withval", + kde_use_extra_includes=NONE +) +kde_extra_includes= +if test -n "$kde_use_extra_includes" && \ + test "$kde_use_extra_includes" != "NONE"; then + + ac_save_ifs=$IFS + IFS=':' + for dir in $kde_use_extra_includes; do + kde_extra_includes="$kde_extra_includes $dir" + USER_INCLUDES="$USER_INCLUDES -I$dir" + done + IFS=$ac_save_ifs + kde_use_extra_includes="added" +else + kde_use_extra_includes="no" +fi +AC_SUBST(USER_INCLUDES) + +AC_MSG_RESULT($kde_use_extra_includes) + +kde_extra_libs= +AC_MSG_CHECKING(for extra libs) +AC_ARG_WITH(extra-libs,AC_HELP_STRING([--with-extra-libs=DIR],[adds non standard library paths]), + kde_use_extra_libs=$withval, + kde_use_extra_libs=NONE +) +if test -n "$kde_use_extra_libs" && \ + test "$kde_use_extra_libs" != "NONE"; then + + ac_save_ifs=$IFS + IFS=':' + for dir in $kde_use_extra_libs; do + kde_extra_libs="$kde_extra_libs $dir" + KDE_EXTRA_RPATH="$KDE_EXTRA_RPATH -R $dir" + USER_LDFLAGS="$USER_LDFLAGS -L$dir" + done + IFS=$ac_save_ifs + kde_use_extra_libs="added" +else + kde_use_extra_libs="no" +fi + +AC_SUBST(USER_LDFLAGS) + +AC_MSG_RESULT($kde_use_extra_libs) + +]) + +AC_DEFUN([KDE_1_CHECK_PATH_HEADERS], +[ + AC_MSG_CHECKING([for KDE headers installed]) + AC_LANG_SAVE + AC_LANG_CPLUSPLUS +cat > conftest.$ac_ext < +#endif +#include +#include "confdefs.h" +#include + +int main() { + printf("kde_htmldir=\\"%s\\"\n", KApplication::kde_htmldir().data()); + printf("kde_appsdir=\\"%s\\"\n", KApplication::kde_appsdir().data()); + printf("kde_icondir=\\"%s\\"\n", KApplication::kde_icondir().data()); + printf("kde_sounddir=\\"%s\\"\n", KApplication::kde_sounddir().data()); + printf("kde_datadir=\\"%s\\"\n", KApplication::kde_datadir().data()); + printf("kde_locale=\\"%s\\"\n", KApplication::kde_localedir().data()); + printf("kde_cgidir=\\"%s\\"\n", KApplication::kde_cgidir().data()); + printf("kde_confdir=\\"%s\\"\n", KApplication::kde_configdir().data()); + printf("kde_mimedir=\\"%s\\"\n", KApplication::kde_mimedir().data()); + printf("kde_toolbardir=\\"%s\\"\n", KApplication::kde_toolbardir().data()); + printf("kde_wallpaperdir=\\"%s\\"\n", + KApplication::kde_wallpaperdir().data()); + printf("kde_bindir=\\"%s\\"\n", KApplication::kde_bindir().data()); + printf("kde_partsdir=\\"%s\\"\n", KApplication::kde_partsdir().data()); + printf("kde_servicesdir=\\"/tmp/dummy\\"\n"); + printf("kde_servicetypesdir=\\"/tmp/dummy\\"\n"); + printf("kde_moduledir=\\"/tmp/dummy\\"\n"); + printf("kde_styledir=\\"/tmp/dummy\\"\n"); + printf("kde_widgetdir=\\"/tmp/dummy\\"\n"); + printf("xdg_appsdir=\\"/tmp/dummy\\"\n"); + printf("xdg_menudir=\\"/tmp/dummy\\"\n"); + printf("xdg_directorydir=\\"/tmp/dummy\\"\n"); + printf("kde_kcfgdir=\\"/tmp/dummy\\"\n"); + return 0; + } +EOF + + ac_save_CPPFLAGS=$CPPFLAGS + CPPFLAGS="$all_includes $CPPFLAGS" + if AC_TRY_EVAL(ac_compile); then + AC_MSG_RESULT(yes) + else + AC_MSG_ERROR([your system is not able to compile a small KDE application! +Check, if you installed the KDE header files correctly. +For more details about this problem, look at the end of config.log.]) + fi + CPPFLAGS=$ac_save_CPPFLAGS + + AC_LANG_RESTORE +]) + +AC_DEFUN([KDE_CHECK_KDEQTADDON], +[ +AC_MSG_CHECKING(for kde-qt-addon) +AC_CACHE_VAL(kde_cv_have_kdeqtaddon, +[ + kde_ldflags_safe="$LDFLAGS" + kde_libs_safe="$LIBS" + kde_cxxflags_safe="$CXXFLAGS" + + LIBS="-lkde-qt-addon $LIBQT $LIBS" + CXXFLAGS="$CXXFLAGS -I$prefix/include -I$prefix/include/kde $all_includes" + LDFLAGS="$LDFLAGS $all_libraries $USER_LDFLAGS" + + AC_TRY_LINK([ + #include + ], + [ + QDomDocument doc; + ], + kde_cv_have_kdeqtaddon=yes, + kde_cv_have_kdeqtaddon=no + ) + + LDFLAGS=$kde_ldflags_safe + LIBS=$kde_libs_safe + CXXFLAGS=$kde_cxxflags_safe +]) + +AC_MSG_RESULT($kde_cv_have_kdeqtaddon) + +if test "$kde_cv_have_kdeqtaddon" = "no"; then + AC_MSG_ERROR([Can't find libkde-qt-addon. You need to install it first. +It is a separate package (and CVS module) named kde-qt-addon.]) +fi +]) + +AC_DEFUN([KDE_CREATE_LIBS_ALIASES], +[ + AC_REQUIRE([KDE_MISC_TESTS]) + AC_REQUIRE([KDE_CHECK_LIBDL]) + AC_REQUIRE([K_PATH_X]) + +if test $kde_qtver = 3; then + case $host in + *cygwin*) lib_kded="-lkdeinit_kded" ;; + *) lib_kded="" ;; + esac + AC_SUBST(LIB_KDED, $lib_kded) + AC_SUBST(LIB_KDECORE, "-lkdecore") + AC_SUBST(LIB_KDEUI, "-lkdeui") + AC_SUBST(LIB_KIO, "-lkio") + AC_SUBST(LIB_KJS, "-lkjs") + AC_SUBST(LIB_SMB, "-lsmb") + AC_SUBST(LIB_KAB, "-lkab") + AC_SUBST(LIB_KABC, "-lkabc") + AC_SUBST(LIB_KHTML, "-lkhtml") + AC_SUBST(LIB_KSPELL, "-lkspell") + AC_SUBST(LIB_KPARTS, "-lkparts") + AC_SUBST(LIB_KDEPRINT, "-lkdeprint") + AC_SUBST(LIB_KUTILS, "-lkutils") + AC_SUBST(LIB_KDEPIM, "-lkdepim") + AC_SUBST(LIB_KIMPROXY, "-lkimproxy") + AC_SUBST(LIB_KNEWSTUFF, "-lknewstuff") + AC_SUBST(LIB_KDNSSD, "-lkdnssd") + AC_SUBST(LIB_KUNITTEST, "-lkunittest") +# these are for backward compatibility + AC_SUBST(LIB_KSYCOCA, "-lkio") + AC_SUBST(LIB_KFILE, "-lkio") +elif test $kde_qtver = 2; then + AC_SUBST(LIB_KDECORE, "-lkdecore") + AC_SUBST(LIB_KDEUI, "-lkdeui") + AC_SUBST(LIB_KIO, "-lkio") + AC_SUBST(LIB_KSYCOCA, "-lksycoca") + AC_SUBST(LIB_SMB, "-lsmb") + AC_SUBST(LIB_KFILE, "-lkfile") + AC_SUBST(LIB_KAB, "-lkab") + AC_SUBST(LIB_KHTML, "-lkhtml") + AC_SUBST(LIB_KSPELL, "-lkspell") + AC_SUBST(LIB_KPARTS, "-lkparts") + AC_SUBST(LIB_KDEPRINT, "-lkdeprint") +else + AC_SUBST(LIB_KDECORE, "-lkdecore -lXext $(LIB_QT)") + AC_SUBST(LIB_KDEUI, "-lkdeui $(LIB_KDECORE)") + AC_SUBST(LIB_KFM, "-lkfm $(LIB_KDECORE)") + AC_SUBST(LIB_KFILE, "-lkfile $(LIB_KFM) $(LIB_KDEUI)") + AC_SUBST(LIB_KAB, "-lkab $(LIB_KIMGIO) $(LIB_KDECORE)") +fi +]) + +AC_DEFUN([AC_PATH_KDE], +[ + AC_BASE_PATH_KDE + AC_ARG_ENABLE(path-check,AC_HELP_STRING([--disable-path-check],[don't try to find out, where to install]), + [ + if test "$enableval" = "no"; + then ac_use_path_checking="default" + else ac_use_path_checking="" + fi + ], + [ + if test "$kde_qtver" = 1; + then ac_use_path_checking="" + else ac_use_path_checking="default" + fi + ] + ) + + AC_CREATE_KFSSTND($ac_use_path_checking) + + AC_SUBST_KFSSTND + KDE_CREATE_LIBS_ALIASES +]) + +dnl KDE_CHECK_FUNC_EXT(, [headers], [sample-use], [C prototype], [autoheader define], [call if found]) +AC_DEFUN([KDE_CHECK_FUNC_EXT], +[ +AC_MSG_CHECKING(for $1) +AC_CACHE_VAL(kde_cv_func_$1, +[ +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +save_CXXFLAGS="$CXXFLAGS" +kde_safe_LIBS="$LIBS" +LIBS="$LIBS $X_EXTRA_LIBS" +if test "$GXX" = "yes"; then +CXXFLAGS="$CXXFLAGS -pedantic-errors" +fi +AC_TRY_COMPILE([ +$2 +], +[ +$3 +], +kde_cv_func_$1=yes, +kde_cv_func_$1=no) +CXXFLAGS="$save_CXXFLAGS" +LIBS="$kde_safe_LIBS" +AC_LANG_RESTORE +]) + +AC_MSG_RESULT($kde_cv_func_$1) + +AC_MSG_CHECKING([if $1 needs custom prototype]) +AC_CACHE_VAL(kde_cv_proto_$1, +[ +if test "x$kde_cv_func_$1" = xyes; then + kde_cv_proto_$1=no +else + case "$1" in + setenv|unsetenv|usleep|random|srandom|seteuid|mkstemps|mkstemp|revoke|vsnprintf|strlcpy|strlcat) + kde_cv_proto_$1="yes - in libkdefakes" + ;; + *) + kde_cv_proto_$1=unknown + ;; + esac +fi + +if test "x$kde_cv_proto_$1" = xunknown; then + +AC_LANG_SAVE +AC_LANG_CPLUSPLUS + kde_safe_libs=$LIBS + LIBS="$LIBS $X_EXTRA_LIBS" + AC_TRY_LINK([ +$2 + +extern "C" $4; +], +[ +$3 +], +[ kde_cv_func_$1=yes + kde_cv_proto_$1=yes ], + [kde_cv_proto_$1="$1 unavailable"] +) +LIBS=$kde_safe_libs +AC_LANG_RESTORE +fi +]) +AC_MSG_RESULT($kde_cv_proto_$1) + +if test "x$kde_cv_func_$1" = xyes; then + AC_DEFINE(HAVE_$5, 1, [Define if you have $1]) + $6 +fi +if test "x$kde_cv_proto_$1" = xno; then + AC_DEFINE(HAVE_$5_PROTO, 1, + [Define if you have the $1 prototype]) +fi + +AH_VERBATIM([_HAVE_$5_PROTO], +[ +#if !defined(HAVE_$5_PROTO) +#ifdef __cplusplus +extern "C" { +#endif +$4; +#ifdef __cplusplus +} +#endif +#endif +]) +]) + +AC_DEFUN([AC_CHECK_SETENV], +[ + KDE_CHECK_FUNC_EXT(setenv, [ +#include +], + [setenv("VAR", "VALUE", 1);], + [int setenv (const char *, const char *, int)], + [SETENV]) +]) + +AC_DEFUN([AC_CHECK_UNSETENV], +[ + KDE_CHECK_FUNC_EXT(unsetenv, [ +#include +], + [unsetenv("VAR");], + [void unsetenv (const char *)], + [UNSETENV]) +]) + +AC_DEFUN([AC_CHECK_GETDOMAINNAME], +[ + KDE_CHECK_FUNC_EXT(getdomainname, [ +#include +#include +#include +], + [ +char buffer[200]; +getdomainname(buffer, 200); +], + [#include + int getdomainname (char *, size_t)], + [GETDOMAINNAME]) +]) + +AC_DEFUN([AC_CHECK_GETHOSTNAME], +[ + KDE_CHECK_FUNC_EXT(gethostname, [ +#include +#include +], + [ +char buffer[200]; +gethostname(buffer, 200); +], + [int gethostname (char *, unsigned int)], + [GETHOSTNAME]) +]) + +AC_DEFUN([AC_CHECK_USLEEP], +[ + KDE_CHECK_FUNC_EXT(usleep, [ +#include +], + [ +usleep(200); +], + [int usleep (unsigned int)], + [USLEEP]) +]) + + +AC_DEFUN([AC_CHECK_RANDOM], +[ + KDE_CHECK_FUNC_EXT(random, [ +#include +], + [ +random(); +], + [long int random(void)], + [RANDOM]) + + KDE_CHECK_FUNC_EXT(srandom, [ +#include +], + [ +srandom(27); +], + [void srandom(unsigned int)], + [SRANDOM]) + +]) + +AC_DEFUN([AC_CHECK_INITGROUPS], +[ + KDE_CHECK_FUNC_EXT(initgroups, [ +#include +#include +#include +], + [ +char buffer[200]; +initgroups(buffer, 27); +], + [int initgroups(const char *, gid_t)], + [INITGROUPS]) +]) + +AC_DEFUN([AC_CHECK_MKSTEMPS], +[ + KDE_CHECK_FUNC_EXT(mkstemps, [ +#include +#include +], + [ +mkstemps("/tmp/aaaXXXXXX", 6); +], + [int mkstemps(char *, int)], + [MKSTEMPS]) +]) + +AC_DEFUN([AC_CHECK_MKSTEMP], +[ + KDE_CHECK_FUNC_EXT(mkstemp, [ +#include +#include +], + [ +mkstemp("/tmp/aaaXXXXXX"); +], + [int mkstemp(char *)], + [MKSTEMP]) +]) + +AC_DEFUN([AC_CHECK_MKDTEMP], +[ + KDE_CHECK_FUNC_EXT(mkdtemp, [ +#include +#include +], + [ +mkdtemp("/tmp/aaaXXXXXX"); +], + [char *mkdtemp(char *)], + [MKDTEMP]) +]) + + +AC_DEFUN([AC_CHECK_RES_INIT], +[ + AC_MSG_CHECKING([if res_init needs -lresolv]) + kde_libs_safe="$LIBS" + LIBS="$LIBS $X_EXTRA_LIBS -lresolv" + AC_TRY_LINK( + [ +#include +#include +#include +#include + ], + [ + res_init(); + ], + [ + LIBRESOLV="-lresolv" + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_RES_INIT, 1, [Define if you have the res_init function]) + ], + [ AC_MSG_RESULT(no) ] + ) + LIBS=$kde_libs_safe + AC_SUBST(LIBRESOLV) + + KDE_CHECK_FUNC_EXT(res_init, + [ +#include +#include +#include +#include + ], + [res_init()], + [int res_init(void)], + [RES_INIT]) +]) + +AC_DEFUN([AC_CHECK_STRLCPY], +[ + KDE_CHECK_FUNC_EXT(strlcpy, [ +#include +], +[ char buf[20]; + strlcpy(buf, "KDE function test", sizeof(buf)); +], + [unsigned long strlcpy(char*, const char*, unsigned long)], + [STRLCPY]) +]) + +AC_DEFUN([AC_CHECK_STRLCAT], +[ + KDE_CHECK_FUNC_EXT(strlcat, [ +#include +], +[ char buf[20]; + buf[0]='\0'; + strlcat(buf, "KDE function test", sizeof(buf)); +], + [unsigned long strlcat(char*, const char*, unsigned long)], + [STRLCAT]) +]) + +AC_DEFUN([AC_CHECK_RES_QUERY], +[ + KDE_CHECK_FUNC_EXT(res_query, [ +#include +#include +#include +#include +#include +], +[ +res_query(NULL, 0, 0, NULL, 0); +], + [int res_query(const char *, int, int, unsigned char *, int)], + [RES_QUERY]) +]) + +AC_DEFUN([AC_CHECK_DN_SKIPNAME], +[ + KDE_CHECK_FUNC_EXT(dn_skipname, [ +#include +#include +#include +#include +], +[ +dn_skipname (NULL, NULL); +], + [int dn_skipname (unsigned char *, unsigned char *)], + [DN_SKIPNAME]) +]) + + +AC_DEFUN([AC_FIND_GIF], + [AC_MSG_CHECKING([for giflib]) +AC_CACHE_VAL(ac_cv_lib_gif, +[ac_save_LIBS="$LIBS" +if test "x$kde_use_qt_emb" != "xyes" && test "x$kde_use_qt_mac" != "xyes"; then +LIBS="$all_libraries -lgif -lX11 $LIBSOCKET" +else +LIBS="$all_libraries -lgif" +fi +AC_TRY_LINK(dnl +[ +#ifdef __cplusplus +extern "C" { +#endif +int GifLastError(void); +#ifdef __cplusplus +} +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +], + [return GifLastError();], + eval "ac_cv_lib_gif=yes", + eval "ac_cv_lib_gif=no") +LIBS="$ac_save_LIBS" +])dnl +if eval "test \"`echo $ac_cv_lib_gif`\" = yes"; then + AC_MSG_RESULT(yes) + AC_DEFINE_UNQUOTED(HAVE_LIBGIF, 1, [Define if you have libgif]) +else + AC_MSG_ERROR(You need giflib30. Please install the kdesupport package) +fi +]) + +AC_DEFUN([KDE_FIND_JPEG_HELPER], +[ +AC_MSG_CHECKING([for libjpeg$2]) +AC_CACHE_VAL(ac_cv_lib_jpeg_$1, +[ +ac_save_LIBS="$LIBS" +LIBS="$all_libraries $USER_LDFLAGS -ljpeg$2 -lm" +ac_save_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $all_includes $USER_INCLUDES" +AC_TRY_LINK( +[ +#ifdef __cplusplus +extern "C" { +#endif +void jpeg_CreateDecompress(); +#ifdef __cplusplus +} +#endif +], +[jpeg_CreateDecompress();], + eval "ac_cv_lib_jpeg_$1=-ljpeg$2", + eval "ac_cv_lib_jpeg_$1=no") +LIBS="$ac_save_LIBS" +CFLAGS="$ac_save_CFLAGS" +]) + +if eval "test ! \"`echo $ac_cv_lib_jpeg_$1`\" = no"; then + LIBJPEG="$ac_cv_lib_jpeg_$1" + AC_MSG_RESULT($ac_cv_lib_jpeg_$1) +else + AC_MSG_RESULT(no) + $3 +fi + +]) + +AC_DEFUN([AC_FIND_JPEG], +[ +dnl first look for libraries +KDE_FIND_JPEG_HELPER(6b, 6b, + KDE_FIND_JPEG_HELPER(normal, [], + [ + LIBJPEG= + ] + ) +) + +dnl then search the headers (can't use simply AC_TRY_xxx, as jpeglib.h +dnl requires system dependent includes loaded before it) +jpeg_incdirs="$includedir /usr/include /usr/local/include $kde_extra_includes" +AC_FIND_FILE(jpeglib.h, $jpeg_incdirs, jpeg_incdir) +test "x$jpeg_incdir" = xNO && jpeg_incdir= + +dnl if headers _and_ libraries are missing, this is no error, and we +dnl continue with a warning (the user will get no jpeg support in khtml) +dnl if only one is missing, it means a configuration error, but we still +dnl only warn +if test -n "$jpeg_incdir" && test -n "$LIBJPEG" ; then + AC_DEFINE_UNQUOTED(HAVE_LIBJPEG, 1, [Define if you have libjpeg]) +else + if test -n "$jpeg_incdir" || test -n "$LIBJPEG" ; then + AC_MSG_WARN([ +There is an installation error in jpeg support. You seem to have only one +of either the headers _or_ the libraries installed. You may need to either +provide correct --with-extra-... options, or the development package of +libjpeg6b. You can get a source package of libjpeg from http://www.ijg.org/ +Disabling JPEG support. +]) + else + AC_MSG_WARN([libjpeg not found. disable JPEG support.]) + fi + jpeg_incdir= + LIBJPEG= +fi + +AC_SUBST(LIBJPEG) +AH_VERBATIM(_AC_CHECK_JPEG, +[/* + * jpeg.h needs HAVE_BOOLEAN, when the system uses boolean in system + * headers and I'm too lazy to write a configure test as long as only + * unixware is related + */ +#ifdef _UNIXWARE +#define HAVE_BOOLEAN +#endif +]) +]) + +AC_DEFUN([KDE_CHECK_QT_JPEG], +[ +if test -n "$LIBJPEG"; then +AC_MSG_CHECKING([if Qt needs $LIBJPEG]) +AC_CACHE_VAL(kde_cv_qt_jpeg, +[ +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +ac_save_LIBS="$LIBS" +LIBS="$all_libraries $USER_LDFLAGS $LIBQT" +LIBS=`echo $LIBS | sed "s/$LIBJPEG//"` +ac_save_CXXFLAGS="$CXXFLAGS" +CXXFLAGS="$CXXFLAGS $all_includes $USER_INCLUDES" +AC_TRY_LINK( +[#include ], + [ + int argc; + char** argv; + QApplication app(argc, argv);], + eval "kde_cv_qt_jpeg=no", + eval "kde_cv_qt_jpeg=yes") +LIBS="$ac_save_LIBS" +CXXFLAGS="$ac_save_CXXFLAGS" +AC_LANG_RESTORE +fi +]) + +if eval "test ! \"`echo $kde_cv_qt_jpeg`\" = no"; then + AC_MSG_RESULT(yes) + LIBJPEG_QT='$(LIBJPEG)' +else + AC_MSG_RESULT(no) + LIBJPEG_QT= +fi + +]) + +AC_DEFUN([AC_FIND_ZLIB], +[ +AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) +AC_MSG_CHECKING([for libz]) +AC_CACHE_VAL(ac_cv_lib_z, +[ +kde_save_LIBS="$LIBS" +LIBS="$all_libraries $USER_LDFLAGS -lz $LIBSOCKET" +kde_save_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $all_includes $USER_INCLUDES" +AC_TRY_LINK(dnl +[ +#include +], +[ + char buf[42]; + gzFile f = (gzFile) 0; + /* this would segfault.. but we only link, don't run */ + (void) gzgets(f, buf, sizeof(buf)); + + return (zlibVersion() == ZLIB_VERSION); +], + eval "ac_cv_lib_z='-lz'", + eval "ac_cv_lib_z=no") +LIBS="$kde_save_LIBS" +CFLAGS="$kde_save_CFLAGS" +])dnl +if test ! "$ac_cv_lib_z" = no; then + AC_DEFINE_UNQUOTED(HAVE_LIBZ, 1, [Define if you have libz]) + LIBZ="$ac_cv_lib_z" + AC_MSG_RESULT($ac_cv_lib_z) +else + AC_MSG_ERROR(not found. + Possibly configure picks up an outdated version + installed by XFree86. Remove it from your system. + + Check your installation and look into config.log) + LIBZ="" +fi +AC_SUBST(LIBZ) +]) + +AC_DEFUN([KDE_TRY_TIFFLIB], +[ +AC_MSG_CHECKING([for libtiff $1]) + +AC_CACHE_VAL(kde_cv_libtiff_$1, +[ +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +kde_save_LIBS="$LIBS" +if test "x$kde_use_qt_emb" != "xyes" && test "x$kde_use_qt_mac" != "xyes"; then +LIBS="$all_libraries $USER_LDFLAGS -l$1 $LIBJPEG $LIBZ -lX11 $LIBSOCKET -lm" +else +LIBS="$all_libraries $USER_LDFLAGS -l$1 $LIBJPEG $LIBZ -lm" +fi +kde_save_CXXFLAGS="$CXXFLAGS" +CXXFLAGS="$CXXFLAGS $all_includes $USER_INCLUDES" + +AC_TRY_LINK(dnl +[ +#include +], + [return (TIFFOpen( "", "r") == 0); ], +[ + kde_cv_libtiff_$1="-l$1 $LIBJPEG $LIBZ" +], [ + kde_cv_libtiff_$1=no +]) + +LIBS="$kde_save_LIBS" +CXXFLAGS="$kde_save_CXXFLAGS" +AC_LANG_RESTORE +]) + +if test "$kde_cv_libtiff_$1" = "no"; then + AC_MSG_RESULT(no) + LIBTIFF="" + $3 +else + LIBTIFF="$kde_cv_libtiff_$1" + AC_MSG_RESULT(yes) + AC_DEFINE_UNQUOTED(HAVE_LIBTIFF, 1, [Define if you have libtiff]) + $2 +fi + +]) + +AC_DEFUN([AC_FIND_TIFF], +[ +AC_REQUIRE([K_PATH_X]) +AC_REQUIRE([AC_FIND_ZLIB]) +AC_REQUIRE([AC_FIND_JPEG]) +AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) + +KDE_TRY_TIFFLIB(tiff, [], + KDE_TRY_TIFFLIB(tiff34)) + +AC_SUBST(LIBTIFF) +]) + +AC_DEFUN([KDE_FIND_LIBEXR], +[ +AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) +AC_REQUIRE([AC_FIND_ZLIB]) +AC_CACHE_VAL(ac_cv_libexr, +[ + if test -z "$PKG_CONFIG"; then + AC_PATH_PROG(PKG_CONFIG, pkg-config, no) + fi + + AC_MSG_CHECKING([for OpenEXR libraries]) + + if test "$PKG_CONFIG" = "no" ; then + AC_MSG_RESULT(no) + echo "*** The pkg-config script could not be found. Make sure it is" + echo "*** in your path, or set the PKG_CONFIG environment variable" + echo "*** to the full path to pkg-config." + echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config." + else + if !(`$PKG_CONFIG --exists OpenEXR`) ; then + AC_MSG_RESULT(no) + EXRSTATUS=no + else + if !(`$PKG_CONFIG --atleast-version="1.1.1" OpenEXR`) ; then + AC_MSG_RESULT(no) + EXRSTATUS=old + else + kde_save_LIBS="$LIBS" + LIBS="$LIBS $all_libraries $USER_LDFLAGS $LIBZ `pkg-config --libs OpenEXR`" + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + kde_save_CXXFLAGS="$CXXFLAGS" + EXR_FLAGS=`$PKG_CONFIG --cflags OpenEXR` + CXXFLAGS="$CXXFLAGS $all_includes $USER_INCLUDES $EXR_FLAGS" + + AC_TRY_LINK(dnl + [ + #include + ], + [ + using namespace Imf; + RgbaInputFile file ("dummy"); + return 0; + ], + eval "ac_cv_libexr='`pkg-config --libs OpenEXR`'", + eval "ac_cv_libexr=no" + ) + LIBS="$kde_save_LIBS" + CXXFLAGS="$kde_save_CXXFLAGS" + AC_LANG_RESTORE + ])dnl + if eval "test ! \"`echo $ac_cv_libexr`\" = no"; then + AC_DEFINE_UNQUOTED(HAVE_EXR, 1, [Define if you have OpenEXR]) + LIB_EXR="$ac_cv_libexr" + AC_MSG_RESULT($ac_cv_libexr) + else + AC_MSG_RESULT(no) + LIB_EXR="" + fi + fi + fi + fi + AC_SUBST(LIB_EXR) + AC_SUBST(EXR_FLAGS) +]) + + + +AC_DEFUN([AC_FIND_PNG], +[ +AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) +AC_REQUIRE([AC_FIND_ZLIB]) +AC_MSG_CHECKING([for libpng]) +AC_CACHE_VAL(ac_cv_lib_png, +[ +kde_save_LIBS="$LIBS" +if test "x$kde_use_qt_emb" != "xyes" && test "x$kde_use_qt_mac" != "xyes"; then +LIBS="$LIBS $all_libraries $USER_LDFLAGS -lpng $LIBZ -lm -lX11 $LIBSOCKET" +else +LIBS="$LIBS $all_libraries $USER_LDFLAGS -lpng $LIBZ -lm" +fi +kde_save_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $all_includes $USER_INCLUDES" + +AC_TRY_LINK(dnl + [ + #include + ], + [ + png_structp png_ptr = png_create_read_struct( /* image ptr */ + PNG_LIBPNG_VER_STRING, 0, 0, 0 ); + return( png_ptr != 0 ); + ], + eval "ac_cv_lib_png='-lpng $LIBZ -lm'", + eval "ac_cv_lib_png=no" +) +LIBS="$kde_save_LIBS" +CFLAGS="$kde_save_CFLAGS" +])dnl +if eval "test ! \"`echo $ac_cv_lib_png`\" = no"; then + AC_DEFINE_UNQUOTED(HAVE_LIBPNG, 1, [Define if you have libpng]) + LIBPNG="$ac_cv_lib_png" + AC_SUBST(LIBPNG) + AC_MSG_RESULT($ac_cv_lib_png) +else + AC_MSG_RESULT(no) + LIBPNG="" + AC_SUBST(LIBPNG) +fi +]) + + +AC_DEFUN([AC_FIND_JASPER], +[ +AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) +AC_REQUIRE([AC_FIND_JPEG]) +AC_MSG_CHECKING([for jasper]) +AC_CACHE_VAL(ac_cv_jasper, +[ +kde_save_LIBS="$LIBS" +LIBS="$LIBS $all_libraries $USER_LDFLAGS -ljasper $LIBJPEG -lm" +kde_save_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $all_includes $USER_INCLUDES" + +AC_TRY_LINK(dnl + [ + #include + ], + [ + return( jas_init() ); + ], + eval "ac_cv_jasper='-ljasper $LIBJPEG -lm'", + eval "ac_cv_jasper=no" +) +LIBS="$kde_save_LIBS" +CFLAGS="$kde_save_CFLAGS" +])dnl +if eval "test ! \"`echo $ac_cv_jasper`\" = no"; then + AC_DEFINE_UNQUOTED(HAVE_JASPER, 1, [Define if you have jasper]) + LIB_JASPER="$ac_cv_jasper" + AC_MSG_RESULT($ac_cv_jasper) +else + AC_MSG_RESULT(no) + LIB_JASPER="" +fi +AC_SUBST(LIB_JASPER) +]) + +AC_DEFUN([AC_CHECK_BOOL], +[ + AC_DEFINE_UNQUOTED(HAVE_BOOL, 1, [You _must_ have bool]) +]) + +AC_DEFUN([AC_CHECK_GNU_EXTENSIONS], +[ +AC_MSG_CHECKING(if you need GNU extensions) +AC_CACHE_VAL(ac_cv_gnu_extensions, +[ +cat > conftest.c << EOF +#include + +#ifdef __GNU_LIBRARY__ +yes +#endif +EOF + +if (eval "$ac_cpp conftest.c") 2>&5 | + egrep "yes" >/dev/null 2>&1; then + rm -rf conftest* + ac_cv_gnu_extensions=yes +else + ac_cv_gnu_extensions=no +fi +]) + +AC_MSG_RESULT($ac_cv_gnu_extensions) +if test "$ac_cv_gnu_extensions" = "yes"; then + AC_DEFINE_UNQUOTED(_GNU_SOURCE, 1, [Define if you need to use the GNU extensions]) +fi +]) + +AC_DEFUN([KDE_CHECK_COMPILER_FLAG], +[ +AC_MSG_CHECKING([whether $CXX supports -$1]) +kde_cache=`echo $1 | sed 'y% .=/+-,%____p__%'` +AC_CACHE_VAL(kde_cv_prog_cxx_$kde_cache, +[ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS -$1" + AC_TRY_LINK([],[ return 0; ], [eval "kde_cv_prog_cxx_$kde_cache=yes"], []) + CXXFLAGS="$save_CXXFLAGS" + AC_LANG_RESTORE +]) +if eval "test \"`echo '$kde_cv_prog_cxx_'$kde_cache`\" = yes"; then + AC_MSG_RESULT(yes) + : + $2 +else + AC_MSG_RESULT(no) + : + $3 +fi +]) + +AC_DEFUN([KDE_CHECK_C_COMPILER_FLAG], +[ +AC_MSG_CHECKING([whether $CC supports -$1]) +kde_cache=`echo $1 | sed 'y% .=/+-,%____p__%'` +AC_CACHE_VAL(kde_cv_prog_cc_$kde_cache, +[ + AC_LANG_SAVE + AC_LANG_C + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -$1" + AC_TRY_LINK([],[ return 0; ], [eval "kde_cv_prog_cc_$kde_cache=yes"], []) + CFLAGS="$save_CFLAGS" + AC_LANG_RESTORE +]) +if eval "test \"`echo '$kde_cv_prog_cc_'$kde_cache`\" = yes"; then + AC_MSG_RESULT(yes) + : + $2 +else + AC_MSG_RESULT(no) + : + $3 +fi +]) + + +dnl AC_REMOVE_FORBIDDEN removes forbidden arguments from variables +dnl use: AC_REMOVE_FORBIDDEN(CC, [-forbid -bad-option whatever]) +dnl it's all white-space separated +AC_DEFUN([AC_REMOVE_FORBIDDEN], +[ __val=$$1 + __forbid=" $2 " + if test -n "$__val"; then + __new="" + ac_save_IFS=$IFS + IFS=" " + for i in $__val; do + case "$__forbid" in + *" $i "*) AC_MSG_WARN([found forbidden $i in $1, removing it]) ;; + *) # Careful to not add spaces, where there were none, because otherwise + # libtool gets confused, if we change e.g. CXX + if test -z "$__new" ; then __new=$i ; else __new="$__new $i" ; fi ;; + esac + done + IFS=$ac_save_IFS + $1=$__new + fi +]) + + +AC_DEFUN([KDE_CHECK_FOR_BAD_COMPILER], +[ + AC_MSG_CHECKING([whether $CC is blacklisted]) + + dnl In theory we have tu run this test against $CC and $CXX + dnl in C and in C++ mode, because its perfectly legal for + dnl the user to mix compiler versions, since C has a defined + dnl ABI. + dnl + dnl For now, we assume the user is not on crack. + + AC_TRY_COMPILE([ +#ifdef __GNUC__ +#if __GNUC__ == 4 && __GNUC_MINOR__ == 0 && __GNUC_PATCHLEVEL__ == 0 +choke me +#endif +#endif +], , + kde_bad_compiler=no, + kde_bad_compiler=yes +) + + AC_MSG_RESULT($kde_bad_compiler) + +if test "$kde_bad_compiler" = "yes"; then + AC_MSG_ERROR([ + +This particular compiler version is blacklisted because it +is known to miscompile KDE. Please use a newer version, or +if that is not yet available, choose an older version. + +Please do not report a bug or bother us reporting this +configure error. We know about it, and we introduced +it by intention to avoid untraceable bugs or crashes in KDE. + +]) +fi + +]) + +dnl AC_VALIDIFY_CXXFLAGS checks for forbidden flags the user may have given +AC_DEFUN([AC_VALIDIFY_CXXFLAGS], +[dnl +if test "x$kde_use_qt_emb" != "xyes"; then + AC_REMOVE_FORBIDDEN(CXX, [-fno-rtti -rpath]) + AC_REMOVE_FORBIDDEN(CXXFLAGS, [-fno-rtti -rpath]) +else + AC_REMOVE_FORBIDDEN(CXX, [-rpath]) + AC_REMOVE_FORBIDDEN(CXXFLAGS, [-rpath]) +fi +]) + +AC_DEFUN([AC_CHECK_COMPILERS], +[ + AC_ARG_ENABLE(debug, + AC_HELP_STRING([--enable-debug=ARG],[enables debug symbols (yes|no|full) [default=no]]), + [ + case $enableval in + yes) + kde_use_debug_code="yes" + kde_use_debug_define=no + ;; + full) + kde_use_debug_code="full" + kde_use_debug_define=no + ;; + *) + kde_use_debug_code="no" + kde_use_debug_define=yes + ;; + esac + ], + [kde_use_debug_code="no" + kde_use_debug_define=no + ]) + + dnl Just for configure --help + AC_ARG_ENABLE(dummyoption, + AC_HELP_STRING([--disable-debug], + [disables debug output and debug symbols [default=no]]), + [],[]) + + AC_ARG_ENABLE(strict, + AC_HELP_STRING([--enable-strict], + [compiles with strict compiler options (may not work!)]), + [ + if test $enableval = "no"; then + kde_use_strict_options="no" + else + kde_use_strict_options="yes" + fi + ], [kde_use_strict_options="no"]) + + AC_ARG_ENABLE(warnings,AC_HELP_STRING([--disable-warnings],[disables compilation with -Wall and similar]), + [ + if test $enableval = "no"; then + kde_use_warnings="no" + else + kde_use_warnings="yes" + fi + ], [kde_use_warnings="yes"]) + + dnl enable warnings for debug build + if test "$kde_use_debug_code" != "no"; then + kde_use_warnings=yes + fi + + AC_ARG_ENABLE(profile,AC_HELP_STRING([--enable-profile],[creates profiling infos [default=no]]), + [kde_use_profiling=$enableval], + [kde_use_profiling="no"] + ) + + dnl this prevents stupid AC_PROG_CC to add "-g" to the default CFLAGS + CFLAGS=" $CFLAGS" + + AC_PROG_CC + + AC_PROG_CPP + + if test "$GCC" = "yes"; then + if test "$kde_use_debug_code" != "no"; then + if test $kde_use_debug_code = "full"; then + CFLAGS="-g3 -fno-inline $CFLAGS" + else + CFLAGS="-g -O2 -fno-reorder-blocks -fno-schedule-insns -fno-inline $CFLAGS" + fi + else + CFLAGS="-O2 $CFLAGS" + fi + fi + + if test "$kde_use_debug_define" = "yes"; then + CFLAGS="-DNDEBUG $CFLAGS" + fi + + + case "$host" in + *-*-sysv4.2uw*) CFLAGS="-D_UNIXWARE $CFLAGS";; + *-*-sysv5uw7*) CFLAGS="-D_UNIXWARE7 $CFLAGS";; + esac + + if test -z "$LDFLAGS" && test "$kde_use_debug_code" = "no" && test "$GCC" = "yes"; then + LDFLAGS="" + fi + + CXXFLAGS=" $CXXFLAGS" + + AC_PROG_CXX + + KDE_CHECK_FOR_BAD_COMPILER + + if test "$GXX" = "yes" || test "$CXX" = "KCC"; then + if test "$kde_use_debug_code" != "no"; then + if test "$CXX" = "KCC"; then + CXXFLAGS="+K0 -Wall -pedantic -W -Wpointer-arith -Wwrite-strings $CXXFLAGS" + else + if test "$kde_use_debug_code" = "full"; then + CXXFLAGS="-g3 -fno-inline $CXXFLAGS" + else + CXXFLAGS="-g -O2 -fno-reorder-blocks -fno-schedule-insns -fno-inline $CXXFLAGS" + fi + fi + KDE_CHECK_COMPILER_FLAG(fno-builtin,[CXXFLAGS="-fno-builtin $CXXFLAGS"]) + + dnl convenience compiler flags + KDE_CHECK_COMPILER_FLAG(Woverloaded-virtual, [WOVERLOADED_VIRTUAL="-Woverloaded-virtual"], [WOVERLOADED_VRITUAL=""]) + AC_SUBST(WOVERLOADED_VIRTUAL) + else + if test "$CXX" = "KCC"; then + CXXFLAGS="+K3 $CXXFLAGS" + else + CXXFLAGS="-O2 $CXXFLAGS" + fi + fi + fi + + if test "$kde_use_debug_define" = "yes"; then + CXXFLAGS="-DNDEBUG -DNO_DEBUG $CXXFLAGS" + fi + + if test "$kde_use_profiling" = "yes"; then + KDE_CHECK_COMPILER_FLAG(pg, + [ + CFLAGS="-pg $CFLAGS" + CXXFLAGS="-pg $CXXFLAGS" + ]) + fi + + if test "$kde_use_warnings" = "yes"; then + if test "$GCC" = "yes"; then + CXXFLAGS="-Wall -W -Wpointer-arith $CXXFLAGS" + case $host in + *-*-linux-gnu) + CFLAGS="-std=iso9899:1990 -W -Wall -Wchar-subscripts -Wshadow -Wpointer-arith -Wmissing-prototypes -Wwrite-strings -D_XOPEN_SOURCE=500 -D_BSD_SOURCE $CFLAGS" + CXXFLAGS="-ansi -D_XOPEN_SOURCE=500 -D_BSD_SOURCE -Wcast-align -Wconversion -Wchar-subscripts $CXXFLAGS" + KDE_CHECK_COMPILER_FLAG(Wmissing-format-attribute, [CXXFLAGS="$CXXFLAGS -Wformat-security -Wmissing-format-attribute"]) + KDE_CHECK_C_COMPILER_FLAG(Wmissing-format-attribute, [CFLAGS="$CFLAGS -Wformat-security -Wmissing-format-attribute"]) + ;; + esac + KDE_CHECK_COMPILER_FLAG(Wundef,[CXXFLAGS="-Wundef $CXXFLAGS"]) + KDE_CHECK_COMPILER_FLAG(Wno-long-long,[CXXFLAGS="-Wno-long-long $CXXFLAGS"]) + dnl ### FIXME: revert for KDE 4 + KDE_CHECK_COMPILER_FLAG(Wno-non-virtual-dtor,[CXXFLAGS="$CXXFLAGS -Wno-non-virtual-dtor"]) + fi + fi + + if test "$GXX" = "yes" && test "$kde_use_strict_options" = "yes"; then + CXXFLAGS="-Wcast-qual -Wshadow -Wcast-align $CXXFLAGS" + fi + + AC_ARG_ENABLE(pch, + AC_HELP_STRING([--enable-pch], + [enables precompiled header support (currently only KCC or gcc >=3.4+unsermake) [default=no]]), + [ kde_use_pch=$enableval ],[ kde_use_pch=no ]) + + HAVE_GCC_VISIBILITY=0 + AC_SUBST([HAVE_GCC_VISIBILITY]) + + if test "$GXX" = "yes"; then + KDE_CHECK_COMPILER_FLAG(fno-exceptions,[CXXFLAGS="$CXXFLAGS -fno-exceptions"]) + KDE_CHECK_COMPILER_FLAG(fno-check-new, [CXXFLAGS="$CXXFLAGS -fno-check-new"]) + KDE_CHECK_COMPILER_FLAG(fno-common, [CXXFLAGS="$CXXFLAGS -fno-common"]) + KDE_CHECK_COMPILER_FLAG(fexceptions, [USE_EXCEPTIONS="-fexceptions"], USE_EXCEPTIONS= ) + ENABLE_PERMISSIVE_FLAG="-fpermissive" + + if test "$kde_use_pch" = "yes"; then + AC_MSG_CHECKING(whether gcc supports precompiling c header files) + echo >conftest.h + if $CC -x c-header conftest.h >/dev/null 2>/dev/null; then + kde_gcc_supports_pch=yes + AC_MSG_RESULT(yes) + else + kde_gcc_supports_pch=no + AC_MSG_RESULT(no) + fi + if test "$kde_gcc_supports_pch" = "yes"; then + AC_MSG_CHECKING(whether gcc supports precompiling c++ header files) + if $CXX -x c++-header conftest.h >/dev/null 2>/dev/null; then + kde_gcc_supports_pch=yes + AC_MSG_RESULT(yes) + else + kde_gcc_supports_pch=no + AC_MSG_RESULT(no) + fi + fi + rm -f conftest.h conftest.h.gch + fi + fi + AM_CONDITIONAL(unsermake_enable_pch, test "$kde_use_pch" = "yes" && test "$kde_gcc_supports_pch" = "yes") + if test "$CXX" = "KCC"; then + dnl unfortunately we currently cannot disable exception support in KCC + dnl because doing so is binary incompatible and Qt by default links with exceptions :-( + dnl KDE_CHECK_COMPILER_FLAG(-no_exceptions,[CXXFLAGS="$CXXFLAGS --no_exceptions"]) + dnl KDE_CHECK_COMPILER_FLAG(-exceptions, [USE_EXCEPTIONS="--exceptions"], USE_EXCEPTIONS= ) + + if test "$kde_use_pch" = "yes"; then + dnl TODO: support --pch-dir! + KDE_CHECK_COMPILER_FLAG(-pch,[CXXFLAGS="$CXXFLAGS --pch"]) + dnl the below works (but the dir must exist), but it's + dnl useless for a whole package. + dnl The are precompiled headers for each source file, so when compiling + dnl from scratch, it doesn't make a difference, and they take up + dnl around ~5Mb _per_ sourcefile. + dnl KDE_CHECK_COMPILER_FLAG(-pch_dir /tmp, + dnl [CXXFLAGS="$CXXFLAGS --pch_dir `pwd`/pcheaders"]) + fi + dnl this flag controls inlining. by default KCC inlines in optimisation mode + dnl all implementations that are defined inside the class {} declaration. + dnl because of templates-compatibility with broken gcc compilers, this + dnl can cause excessive inlining. This flag limits it to a sane level + KDE_CHECK_COMPILER_FLAG(-inline_keyword_space_time=6,[CXXFLAGS="$CXXFLAGS --inline_keyword_space_time=6"]) + KDE_CHECK_COMPILER_FLAG(-inline_auto_space_time=2,[CXXFLAGS="$CXXFLAGS --inline_auto_space_time=2"]) + KDE_CHECK_COMPILER_FLAG(-inline_implicit_space_time=2.0,[CXXFLAGS="$CXXFLAGS --inline_implicit_space_time=2.0"]) + KDE_CHECK_COMPILER_FLAG(-inline_generated_space_time=2.0,[CXXFLAGS="$CXXFLAGS --inline_generated_space_time=2.0"]) + dnl Some source files are shared between multiple executables + dnl (or libraries) and some of those need template instantiations. + dnl In that case KCC needs to compile those sources with + dnl --one_instantiation_per_object. To make it easy for us we compile + dnl _all_ objects with that flag (--one_per is a shorthand). + KDE_CHECK_COMPILER_FLAG(-one_per, [CXXFLAGS="$CXXFLAGS --one_per"]) + fi + AC_SUBST(USE_EXCEPTIONS) + dnl obsolete macro - provided to keep things going + USE_RTTI= + AC_SUBST(USE_RTTI) + + case "$host" in + *-*-irix*) test "$GXX" = yes && CXXFLAGS="-D_LANGUAGE_C_PLUS_PLUS -D__LANGUAGE_C_PLUS_PLUS $CXXFLAGS" ;; + *-*-sysv4.2uw*) CXXFLAGS="-D_UNIXWARE $CXXFLAGS";; + *-*-sysv5uw7*) CXXFLAGS="-D_UNIXWARE7 $CXXFLAGS";; + *-*-solaris*) + if test "$GXX" = yes; then + libstdcpp=`$CXX -print-file-name=libstdc++.so` + if test ! -f $libstdcpp; then + AC_MSG_ERROR([You've compiled gcc without --enable-shared. This doesn't work with KDE. Please recompile gcc with --enable-shared to receive a libstdc++.so]) + fi + fi + ;; + esac + + AC_VALIDIFY_CXXFLAGS + + AC_PROG_CXXCPP + + if test "$GCC" = yes; then + NOOPT_CFLAGS=-O0 + fi + KDE_CHECK_COMPILER_FLAG(O0,[NOOPT_CXXFLAGS=-O0]) + + AC_ARG_ENABLE(coverage, + AC_HELP_STRING([--enable-coverage],[use gcc coverage testing]), [ + if test "$am_cv_CC_dependencies_compiler_type" = "gcc3"; then + ac_coverage_compiler="-fprofile-arcs -ftest-coverage" + ac_coverage_linker="-lgcc" + elif test "$am_cv_CC_dependencies_compiler_type" = "gcc"; then + ac_coverage_compiler="-fprofile-arcs -ftest-coverage" + ac_coverage_linker="" + else + AC_MSG_ERROR([coverage with your compiler is not supported]) + fi + CFLAGS="$CFLAGS $ac_coverage_compiler" + CXXFLAGS="$CXXFLAGS $ac_coverage_compiler" + LDFLAGS="$LDFLAGS $ac_coverage_linker" + ]) + + AC_SUBST(NOOPT_CXXFLAGS) + AC_SUBST(NOOPT_CFLAGS) + AC_SUBST(ENABLE_PERMISSIVE_FLAG) + + KDE_CHECK_NEW_LDFLAGS + KDE_CHECK_FINAL + KDE_CHECK_CLOSURE + KDE_CHECK_NMCHECK + + ifdef([AM_DEPENDENCIES], AC_REQUIRE([KDE_ADD_DEPENDENCIES]), []) +]) + +AC_DEFUN([KDE_CHECK_VISIBILITY_GCC_BUG], + [ + AC_CACHE_CHECK([for gcc -fvisibility-inlines-hidden bug], kde_cv_val_gcc_visibility_bug, + [ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + + safe_CXXFLAGS=$CXXFLAGS + safe_LDFLAGS=$LDFLAGS + CXXFLAGS="$CXXFLAGS -fPIC -fvisibility-inlines-hidden -O0" + LDFLAGS="$LDFLAGS -shared -fPIC" + + AC_TRY_LINK( + [ + /* http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19664 */ + #include + int some_function( void ) __attribute__ ((visibility("default"))); + int some_function( void ) + { + std::string s("blafasel"); + return 0; + } + ], [/* elvis is alive */], + kde_cv_val_gcc_visibility_bug=no, kde_cv_val_gcc_visibility_bug=yes) + + CXXFLAGS=$safe_CXXFLAGS + LDFLAGS=$safe_LDFLAGS + AC_LANG_RESTORE + ] + ) + + if test x$kde_cv_val_gcc_visibility_bug = xno; then + CXXFLAGS="$CXXFLAGS -fvisibility-inlines-hidden" + fi + ] +) + +AC_DEFUN([KDE_ENABLE_HIDDEN_VISIBILITY], +[ + AC_BEFORE([AC_PATH_QT_1_3], [KDE_ENABLE_HIDDEN_VISIBILITY]) + + AC_MSG_CHECKING([grepping for visibility push/pop in headers]) + + if test "x$GXX" = "xyes"; then + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_EGREP_CPP( + [GCC visibility push], + [ #include + ], + [ + AC_MSG_RESULT(yes) + kde_stdc_visibility_patched=yes ], + [ + AC_MSG_RESULT(no) + AC_MSG_WARN([Your libstdc++ doesn't appear to be patched for + visibility support. Disabling -fvisibility=hidden]) + + kde_stdc_visibility_patched=no ]) + + AC_LANG_RESTORE + + kde_have_gcc_visibility=no + KDE_CHECK_COMPILER_FLAG(fvisibility=hidden, + [ + kde_have_gcc_visibility=yes + dnl the whole toolchain is just a mess, gcc is just too buggy + dnl to handle STL with visibility enabled. Lets reconsider + dnl when gcc 4.2 is out or when things get fixed in the compiler. + dnl Contact mueller@kde.org for details. + AC_ARG_ENABLE(gcc-hidden-visibility, + AC_HELP_STRING([--enable-gcc-hidden-visibility],[toolchain hidden visibility [default=no]]), + [kde_have_gcc_visibility=$enableval], + [kde_have_gcc_visibility=no]) + + AC_CACHE_CHECK([if Qt is patched for -fvisibility], kde_cv_val_qt_gcc_visibility_patched, + [ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + + safe_CXXFLAGS=$CXXFLAGS + CXXFLAGS="$CXXFLAGS $all_includes" + + AC_TRY_COMPILE( + [ +#include +#if Q_EXPORT - 0 != 0 +/* if this compiles, then Q_EXPORT is undefined */ +/* if Q_EXPORT is nonempty, this will break compilation */ +#endif + ], [/* elvis is alive */], + kde_cv_val_qt_gcc_visibility_patched=no, kde_cv_val_qt_gcc_visibility_patched=yes) + + CXXFLAGS=$safe_CXXFLAGS + AC_LANG_RESTORE + ] + ) + + if test x$kde_have_gcc_visibility = "xyes" && test x$kde_stdc_visibility_patched = "xyes" && test x$kde_cv_val_qt_gcc_visibility_patched = "xyes"; then + CXXFLAGS="$CXXFLAGS -fvisibility=hidden" + KDE_CHECK_VISIBILITY_GCC_BUG + HAVE_GCC_VISIBILITY=1 + AC_DEFINE_UNQUOTED(__KDE_HAVE_GCC_VISIBILITY, "$HAVE_GCC_VISIBILITY", [define to 1 if -fvisibility is supported]) + fi + ]) + fi +]) + +AC_DEFUN([KDE_ADD_DEPENDENCIES], +[ + [A]M_DEPENDENCIES(CC) + [A]M_DEPENDENCIES(CXX) +]) + +dnl just a wrapper to clean up configure.in +AC_DEFUN([KDE_PROG_LIBTOOL], +[ +AC_REQUIRE([AC_CHECK_COMPILERS]) +AC_REQUIRE([AC_ENABLE_SHARED]) +AC_REQUIRE([AC_ENABLE_STATIC]) + +AC_REQUIRE([AC_LIBTOOL_DLOPEN]) +AC_REQUIRE([KDE_CHECK_LIB64]) + +AC_OBJEXT +AC_EXEEXT + +AM_PROG_LIBTOOL +AC_LIBTOOL_CXX + +LIBTOOL_SHELL="/bin/sh ./libtool" +# LIBTOOL="$LIBTOOL --silent" +KDE_PLUGIN="-avoid-version -module -no-undefined \$(KDE_NO_UNDEFINED) \$(KDE_RPATH) \$(KDE_MT_LDFLAGS)" +AC_SUBST(KDE_PLUGIN) + +# This hack ensures that libtool creates shared libs for kunittest plugins. By default check_LTLIBRARIES makes static libs. +KDE_CHECK_PLUGIN="\$(KDE_PLUGIN) -rpath \$(libdir)" +AC_SUBST(KDE_CHECK_PLUGIN) + +# we patch configure quite some so we better keep that consistent for incremental runs +AC_SUBST(AUTOCONF,'$(SHELL) $(top_srcdir)/admin/cvs.sh configure || touch configure') +]) + +AC_DEFUN([KDE_CHECK_LIB64], +[ + kdelibsuff="$kde_libs_suffix" + if test -z "$kdelibsuff"; then + kdelibsuff=no + fi + AC_ARG_ENABLE(libsuffix, + AC_HELP_STRING([--enable-libsuffix], + [/lib directory suffix (64,32,none[=default])]), + kdelibsuff=$enableval) + # TODO: add an auto case that compiles a little C app to check + # where the glibc is + if test "$kdelibsuff" = "no"; then + kdelibsuff= + fi + if test -z "$kdelibsuff"; then + AC_MSG_RESULT([not using lib directory suffix]) + AC_DEFINE(KDELIBSUFF, [""], Suffix for lib directories) + else + if test "$libdir" = '${exec_prefix}/lib'; then + libdir="$libdir${kdelibsuff}" + AC_SUBST([libdir], ["$libdir"]) dnl ugly hack for lib64 platforms + fi + AC_DEFINE_UNQUOTED(KDELIBSUFF, ["${kdelibsuff}"], Suffix for lib directories) + AC_MSG_RESULT([using lib directory suffix $kdelibsuff]) + fi +]) + +AC_DEFUN([KDE_CHECK_TYPES], +[ AC_CHECK_SIZEOF(int, 4)dnl + AC_CHECK_SIZEOF(short)dnl + AC_CHECK_SIZEOF(long, 4)dnl + AC_CHECK_SIZEOF(char *, 4)dnl +])dnl + +dnl Not used - kept for compat only? +AC_DEFUN([KDE_DO_IT_ALL], +[ +AC_CANONICAL_SYSTEM +AC_ARG_PROGRAM +AM_INIT_AUTOMAKE($1, $2) +AM_DISABLE_LIBRARIES +AC_PREFIX_DEFAULT(${KDEDIR:-/usr/local/kde}) +AC_CHECK_COMPILERS +KDE_PROG_LIBTOOL +AM_KDE_WITH_NLS +AC_PATH_KDE +]) + +AC_DEFUN([AC_CHECK_RPATH], +[ +AC_MSG_CHECKING(for rpath) +AC_ARG_ENABLE(rpath, + AC_HELP_STRING([--disable-rpath],[do not use the rpath feature of ld]), + USE_RPATH=$enableval, USE_RPATH=yes) + +if test -z "$KDE_RPATH" && test "$USE_RPATH" = "yes"; then + + KDE_RPATH="-R \$(libdir)" + + if test "$kde_libraries" != "$libdir"; then + KDE_RPATH="$KDE_RPATH -R \$(kde_libraries)" + fi + + if test -n "$qt_libraries"; then + KDE_RPATH="$KDE_RPATH -R \$(qt_libraries)" + fi + dnl $x_libraries is set to /usr/lib in case + if test -n "$X_LDFLAGS"; then + X_RPATH="-R \$(x_libraries)" + KDE_RPATH="$KDE_RPATH $X_RPATH" + fi + if test -n "$KDE_EXTRA_RPATH"; then + KDE_RPATH="$KDE_RPATH \$(KDE_EXTRA_RPATH)" + fi +fi +AC_SUBST(KDE_EXTRA_RPATH) +AC_SUBST(KDE_RPATH) +AC_SUBST(X_RPATH) +AC_MSG_RESULT($USE_RPATH) +]) + +dnl Check for the type of the third argument of getsockname +AC_DEFUN([AC_CHECK_SOCKLEN_T], +[ + AC_MSG_CHECKING(for socklen_t) + AC_CACHE_VAL(kde_cv_socklen_t, + [ + AC_LANG_PUSH(C++) + kde_cv_socklen_t=no + AC_TRY_COMPILE([ + #include + #include + ], + [ + socklen_t len; + getpeername(0,0,&len); + ], + [ + kde_cv_socklen_t=yes + kde_cv_socklen_t_equiv=socklen_t + ]) + AC_LANG_POP(C++) + ]) + AC_MSG_RESULT($kde_cv_socklen_t) + if test $kde_cv_socklen_t = no; then + AC_MSG_CHECKING([for socklen_t equivalent for socket functions]) + AC_CACHE_VAL(kde_cv_socklen_t_equiv, + [ + kde_cv_socklen_t_equiv=int + AC_LANG_PUSH(C++) + for t in int size_t unsigned long "unsigned long"; do + AC_TRY_COMPILE([ + #include + #include + ], + [ + $t len; + getpeername(0,0,&len); + ], + [ + kde_cv_socklen_t_equiv="$t" + break + ]) + done + AC_LANG_POP(C++) + ]) + AC_MSG_RESULT($kde_cv_socklen_t_equiv) + fi + AC_DEFINE_UNQUOTED(kde_socklen_t, $kde_cv_socklen_t_equiv, + [type to use in place of socklen_t if not defined]) + AC_DEFINE_UNQUOTED(ksize_t, $kde_cv_socklen_t_equiv, + [type to use in place of socklen_t if not defined (deprecated, use kde_socklen_t)]) +]) + +dnl This is a merge of some macros out of the gettext aclocal.m4 +dnl since we don't need anything, I took the things we need +dnl the copyright for them is: +dnl > +dnl Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +dnl This Makefile.in is free software; the Free Software Foundation +dnl gives unlimited permission to copy and/or distribute it, +dnl with or without modifications, as long as this notice is preserved. + +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without +dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A +dnl PARTICULAR PURPOSE. +dnl > +dnl for this file it is relicensed under LGPL + +AC_DEFUN([AM_KDE_WITH_NLS], + [ + dnl If we use NLS figure out what method + + AM_PATH_PROG_WITH_TEST_KDE(MSGFMT, msgfmt, + [test -n "`$ac_dir/$ac_word --version 2>&1 | grep 'GNU gettext'`"], msgfmt) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + + if test -z "`$GMSGFMT --version 2>&1 | grep 'GNU gettext'`"; then + AC_MSG_RESULT([found msgfmt program is not GNU msgfmt; ignore it]) + GMSGFMT=":" + fi + MSGFMT=$GMSGFMT + AC_SUBST(GMSGFMT) + AC_SUBST(MSGFMT) + + AM_PATH_PROG_WITH_TEST_KDE(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + + dnl Test whether we really found GNU xgettext. + if test "$XGETTEXT" != ":"; then + dnl If it is no GNU xgettext we define it as : so that the + dnl Makefiles still can work. + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + AC_MSG_RESULT( + [found xgettext programs is not GNU xgettext; ignore it]) + XGETTEXT=":" + fi + fi + AC_SUBST(XGETTEXT) + + ]) + +# Search path for a program which passes the given test. +# Ulrich Drepper , 1996. + +# serial 1 +# Stephan Kulow: I appended a _KDE against name conflicts + +dnl AM_PATH_PROG_WITH_TEST_KDE(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +AC_DEFUN([AM_PATH_PROG_WITH_TEST_KDE], +[# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL(ac_cv_path_$1, +[case "[$]$1" in + /*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in ifelse([$5], , $PATH, [$5]); do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test -n "[$]$1"; then + AC_MSG_RESULT([$]$1) +else + AC_MSG_RESULT(no) +fi +AC_SUBST($1)dnl +]) + + +# Check whether LC_MESSAGES is available in . +# Ulrich Drepper , 1995. + +# serial 1 + +AC_DEFUN([AM_LC_MESSAGES], + [if test $ac_cv_header_locale_h = yes; then + AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES, + [AC_TRY_LINK([#include ], [return LC_MESSAGES], + am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)]) + if test $am_cv_val_LC_MESSAGES = yes; then + AC_DEFINE(HAVE_LC_MESSAGES, 1, [Define if your locale.h file contains LC_MESSAGES]) + fi + fi]) + +dnl From Jim Meyering. +dnl FIXME: migrate into libit. + +AC_DEFUN([AM_FUNC_OBSTACK], +[AC_CACHE_CHECK([for obstacks], am_cv_func_obstack, + [AC_TRY_LINK([#include "obstack.h"], + [struct obstack *mem;obstack_free(mem,(char *) 0)], + am_cv_func_obstack=yes, + am_cv_func_obstack=no)]) + if test $am_cv_func_obstack = yes; then + AC_DEFINE(HAVE_OBSTACK) + else + LIBOBJS="$LIBOBJS obstack.o" + fi +]) + +dnl From Jim Meyering. Use this if you use the GNU error.[ch]. +dnl FIXME: Migrate into libit + +AC_DEFUN([AM_FUNC_ERROR_AT_LINE], +[AC_CACHE_CHECK([for error_at_line], am_cv_lib_error_at_line, + [AC_TRY_LINK([],[error_at_line(0, 0, "", 0, "");], + am_cv_lib_error_at_line=yes, + am_cv_lib_error_at_line=no)]) + if test $am_cv_lib_error_at_line = no; then + LIBOBJS="$LIBOBJS error.o" + fi + AC_SUBST(LIBOBJS)dnl +]) + +# Macro to add for using GNU gettext. +# Ulrich Drepper , 1995. + +# serial 1 +# Stephan Kulow: I put a KDE in it to avoid name conflicts + +AC_DEFUN([AM_KDE_GNU_GETTEXT], + [AC_REQUIRE([AC_PROG_MAKE_SET])dnl + AC_REQUIRE([AC_PROG_RANLIB])dnl + AC_REQUIRE([AC_HEADER_STDC])dnl + AC_REQUIRE([AC_TYPE_OFF_T])dnl + AC_REQUIRE([AC_TYPE_SIZE_T])dnl + AC_REQUIRE([AC_FUNC_ALLOCA])dnl + AC_REQUIRE([AC_FUNC_MMAP])dnl + AC_REQUIRE([AM_KDE_WITH_NLS])dnl + AC_CHECK_HEADERS([limits.h locale.h nl_types.h string.h values.h alloca.h]) + AC_CHECK_FUNCS([getcwd munmap putenv setlocale strchr strcasecmp \ +__argz_count __argz_stringify __argz_next]) + + AC_MSG_CHECKING(for stpcpy) + AC_CACHE_VAL(kde_cv_func_stpcpy, + [ + kde_safe_cxxflags=$CXXFLAGS + CXXFLAGS="-Werror" + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_TRY_COMPILE([ + #include + ], + [ + char buffer[200]; + stpcpy(buffer, buffer); + ], + kde_cv_func_stpcpy=yes, + kde_cv_func_stpcpy=no) + AC_LANG_RESTORE + CXXFLAGS=$kde_safe_cxxflags + ]) + AC_MSG_RESULT($kde_cv_func_stpcpy) + if eval "test \"`echo $kde_cv_func_stpcpy`\" = yes"; then + AC_DEFINE(HAVE_STPCPY, 1, [Define if you have stpcpy]) + fi + + AM_LC_MESSAGES + + if test "x$CATOBJEXT" != "x"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + AC_MSG_CHECKING(for catalogs to be installed) + NEW_LINGUAS= + for lang in ${LINGUAS=$ALL_LINGUAS}; do + case "$ALL_LINGUAS" in + *$lang*) NEW_LINGUAS="$NEW_LINGUAS $lang" ;; + esac + done + LINGUAS=$NEW_LINGUAS + AC_MSG_RESULT($LINGUAS) + fi + + dnl Construct list of names of catalog files to be constructed. + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + ]) + +AC_DEFUN([AC_HAVE_XPM], + [AC_REQUIRE_CPP()dnl + AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) + + test -z "$XPM_LDFLAGS" && XPM_LDFLAGS= + test -z "$XPM_INCLUDE" && XPM_INCLUDE= + + AC_ARG_WITH(xpm,AC_HELP_STRING([--without-xpm],[disable color pixmap XPM tests]), + xpm_test=$withval, xpm_test="yes") + if test "x$xpm_test" = xno; then + ac_cv_have_xpm=no + else + AC_MSG_CHECKING(for XPM) + AC_CACHE_VAL(ac_cv_have_xpm, + [ + ac_save_ldflags="$LDFLAGS" + ac_save_cflags="$CFLAGS" + if test "x$kde_use_qt_emb" != "xyes" && test "x$kde_use_qt_mac" != "xyes"; then + LDFLAGS="$LDFLAGS $X_LDFLAGS $USER_LDFLAGS $LDFLAGS $XPM_LDFLAGS $all_libraries -lXpm -lX11 -lXext $LIBZ $LIBSOCKET" + else + LDFLAGS="$LDFLAGS $X_LDFLAGS $USER_LDFLAGS $LDFLAGS $XPM_LDFLAGS $all_libraries -lXpm $LIBZ $LIBSOCKET" + fi + CFLAGS="$CFLAGS $X_INCLUDES $USER_INCLUDES" + test -n "$XPM_INCLUDE" && CFLAGS="-I$XPM_INCLUDE $CFLAGS" + AC_TRY_LINK([#include ],[], + ac_cv_have_xpm="yes",ac_cv_have_xpm="no") + LDFLAGS="$ac_save_ldflags" + CFLAGS="$ac_save_cflags" + ])dnl + + if test "$ac_cv_have_xpm" = no; then + AC_MSG_RESULT(no) + XPM_LDFLAGS="" + XPMINC="" + $2 + else + AC_DEFINE(HAVE_XPM, 1, [Define if you have XPM support]) + if test "$XPM_LDFLAGS" = ""; then + XPMLIB='-lXpm $(LIB_X11)' + else + XPMLIB="-L$XPM_LDFLAGS -lXpm "'$(LIB_X11)' + fi + if test "$XPM_INCLUDE" = ""; then + XPMINC="" + else + XPMINC="-I$XPM_INCLUDE" + fi + AC_MSG_RESULT(yes) + $1 + fi + fi + AC_SUBST(XPMINC) + AC_SUBST(XPMLIB) +]) + +AC_DEFUN([AC_HAVE_DPMS], + [AC_REQUIRE_CPP()dnl + AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) + + test -z "$DPMS_LDFLAGS" && DPMS_LDFLAGS= + test -z "$DPMS_INCLUDE" && DPMS_INCLUDE= + DPMS_LIB= + + AC_ARG_WITH(dpms,AC_HELP_STRING([--without-dpms],[disable DPMS power saving]), + dpms_test=$withval, dpms_test="yes") + if test "x$dpms_test" = xno; then + ac_cv_have_dpms=no + else + AC_MSG_CHECKING(for DPMS) + dnl Note: ac_cv_have_dpms can be no, yes, or -lXdpms. + dnl 'yes' means DPMS_LIB="", '-lXdpms' means DPMS_LIB="-lXdpms". + AC_CACHE_VAL(ac_cv_have_dpms, + [ + if test "x$kde_use_qt_emb" = "xyes" || test "x$kde_use_qt_mac" = "xyes"; then + AC_MSG_RESULT(no) + ac_cv_have_dpms="no" + else + ac_save_ldflags="$LDFLAGS" + ac_save_cflags="$CFLAGS" + ac_save_libs="$LIBS" + LDFLAGS="$LDFLAGS $DPMS_LDFLAGS $all_libraries" + LIBS="-lX11 -lXext $LIBSOCKET" + CFLAGS="$CFLAGS $X_INCLUDES" + test -n "$DPMS_INCLUDE" && CFLAGS="-I$DPMS_INCLUDE $CFLAGS" + AC_TRY_LINK([ + #include + #include + #include + #include + int foo_test_dpms() + { return DPMSSetTimeouts( 0, 0, 0, 0 ); }],[], + ac_cv_have_dpms="yes", [ + LIBS="-lXdpms $LIBS" + AC_TRY_LINK([ + #include + #include + #include + #include + int foo_test_dpms() + { return DPMSSetTimeouts( 0, 0, 0, 0 ); }],[], + [ + ac_cv_have_dpms="-lXdpms" + ],ac_cv_have_dpms="no") + ]) + LDFLAGS="$ac_save_ldflags" + CFLAGS="$ac_save_cflags" + LIBS="$ac_save_libs" + fi + ])dnl + + if test "$ac_cv_have_dpms" = no; then + AC_MSG_RESULT(no) + DPMS_LDFLAGS="" + DPMSINC="" + $2 + else + AC_DEFINE(HAVE_DPMS, 1, [Define if you have DPMS support]) + if test "$ac_cv_have_dpms" = "-lXdpms"; then + DPMS_LIB="-lXdpms" + fi + if test "$DPMS_LDFLAGS" = ""; then + DPMSLIB="$DPMS_LIB "'$(LIB_X11)' + else + DPMSLIB="$DPMS_LDFLAGS $DPMS_LIB "'$(LIB_X11)' + fi + if test "$DPMS_INCLUDE" = ""; then + DPMSINC="" + else + DPMSINC="-I$DPMS_INCLUDE" + fi + AC_MSG_RESULT(yes) + $1 + fi + fi + ac_save_cflags="$CFLAGS" + CFLAGS="$CFLAGS $X_INCLUDES" + test -n "$DPMS_INCLUDE" && CFLAGS="-I$DPMS_INCLUDE $CFLAGS" + AH_TEMPLATE(HAVE_DPMSCAPABLE_PROTO, + [Define if you have the DPMSCapable prototype in ]) + AC_CHECK_DECL(DPMSCapable, + AC_DEFINE(HAVE_DPMSCAPABLE_PROTO),, + [#include + #include ]) + AH_TEMPLATE(HAVE_DPMSINFO_PROTO, + [Define if you have the DPMSInfo prototype in ]) + AC_CHECK_DECL(DPMSInfo, + AC_DEFINE(HAVE_DPMSINFO_PROTO),, + [#include + #include ]) + CFLAGS="$ac_save_cflags" + AC_SUBST(DPMSINC) + AC_SUBST(DPMSLIB) +]) + +AC_DEFUN([AC_HAVE_GL], + [AC_REQUIRE_CPP()dnl + AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) + + test -z "$GL_LDFLAGS" && GL_LDFLAGS= + test -z "$GL_INCLUDE" && GL_INCLUDE= + + AC_ARG_WITH(gl,AC_HELP_STRING([--without-gl],[disable 3D GL modes]), + gl_test=$withval, gl_test="yes") + if test "x$kde_use_qt_emb" = "xyes"; then + # GL and Qt Embedded is a no-go for now. + ac_cv_have_gl=no + elif test "x$gl_test" = xno; then + ac_cv_have_gl=no + else + AC_MSG_CHECKING(for GL) + AC_CACHE_VAL(ac_cv_have_gl, + [ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + ac_save_ldflags=$LDFLAGS + ac_save_cxxflags=$CXXFLAGS + ac_save_libs=$LIBS + LDFLAGS="$LDFLAGS $GL_LDFLAGS $X_LDFLAGS $all_libraries" + LIBS="$LIBS -lGL -lGLU" + test "x$kde_use_qt_mac" != xyes && test "x$kde_use_qt_emb" != xyes && LIBS="$LIBS -lX11" + LIBS="$LIBS $LIB_XEXT -lm $LIBSOCKET" + CXXFLAGS="$CFLAGS $X_INCLUDES" + test -n "$GL_INCLUDE" && CFLAGS="-I$GL_INCLUDE $CFLAGS" + AC_TRY_LINK([#include +#include +], [], + ac_cv_have_gl="yes", ac_cv_have_gl="no") + AC_LANG_RESTORE + LDFLAGS=$ac_save_ldflags + CXXFLAGS=$ac_save_cxxflags + LIBS=$ac_save_libs + ])dnl + + if test "$ac_cv_have_gl" = "no"; then + AC_MSG_RESULT(no) + GL_LDFLAGS="" + GLINC="" + $2 + else + AC_DEFINE(HAVE_GL, 1, [Defines if you have GL (Mesa, OpenGL, ...)]) + if test "$GL_LDFLAGS" = ""; then + GLLIB='-lGLU -lGL $(LIB_X11)' + else + GLLIB="$GL_LDFLAGS -lGLU -lGL "'$(LIB_X11)' + fi + if test "$GL_INCLUDE" = ""; then + GLINC="" + else + GLINC="-I$GL_INCLUDE" + fi + AC_MSG_RESULT($ac_cv_have_gl) + $1 + fi + fi + AC_SUBST(GLINC) + AC_SUBST(GLLIB) +]) + + + dnl shadow password and PAM magic - maintained by ossi@kde.org + +AC_DEFUN([KDE_PAM], [ + AC_REQUIRE([KDE_CHECK_LIBDL]) + + want_pam= + AC_ARG_WITH(pam, + AC_HELP_STRING([--with-pam[=ARG]],[enable support for PAM: ARG=[yes|no|service name]]), + [ if test "x$withval" = "xyes"; then + want_pam=yes + pam_service=kde + elif test "x$withval" = "xno"; then + want_pam=no + else + want_pam=yes + pam_service=$withval + fi + ], [ pam_service=kde ]) + + use_pam= + PAMLIBS= + if test "x$want_pam" != xno; then + AC_CHECK_LIB(pam, pam_start, [ + AC_CHECK_HEADER(security/pam_appl.h, + [ pam_header=security/pam_appl.h ], + [ AC_CHECK_HEADER(pam/pam_appl.h, + [ pam_header=pam/pam_appl.h ], + [ + AC_MSG_WARN([PAM detected, but no headers found! +Make sure you have the necessary development packages installed.]) + ] + ) + ] + ) + ], , $LIBDL) + if test -z "$pam_header"; then + if test "x$want_pam" = xyes; then + AC_MSG_ERROR([--with-pam was specified, but cannot compile with PAM!]) + fi + else + AC_DEFINE(HAVE_PAM, 1, [Defines if you have PAM (Pluggable Authentication Modules)]) + PAMLIBS="$PAM_MISC_LIB -lpam $LIBDL" + use_pam=yes + + dnl darwin claims to be something special + if test "$pam_header" = "pam/pam_appl.h"; then + AC_DEFINE(HAVE_PAM_PAM_APPL_H, 1, [Define if your PAM headers are in pam/ instead of security/]) + fi + + dnl test whether struct pam_message is const (Linux) or not (Sun) + AC_MSG_CHECKING(for const pam_message) + AC_EGREP_HEADER([struct pam_message], $pam_header, + [ AC_EGREP_HEADER([const struct pam_message], $pam_header, + [AC_MSG_RESULT([const: Linux-type PAM])], + [AC_MSG_RESULT([nonconst: Sun-type PAM]) + AC_DEFINE(PAM_MESSAGE_NONCONST, 1, [Define if your PAM support takes non-const arguments (Solaris)])] + )], + [AC_MSG_RESULT([not found - assume const, Linux-type PAM])]) + fi + fi + + AC_SUBST(PAMLIBS) +]) + +dnl DEF_PAM_SERVICE(arg name, full name, define name) +AC_DEFUN([DEF_PAM_SERVICE], [ + AC_ARG_WITH($1-pam, + AC_HELP_STRING([--with-$1-pam=[val]],[override PAM service from --with-pam for $2]), + [ if test "x$use_pam" = xyes; then + $3_PAM_SERVICE=$withval + else + AC_MSG_ERROR([Cannot use use --with-$1-pam, as no PAM was detected. +You may want to enforce it by using --with-pam.]) + fi + ], + [ if test "x$use_pam" = xyes; then + $3_PAM_SERVICE="$pam_service" + fi + ]) + if test -n "$$3_PAM_SERVICE"; then + AC_MSG_RESULT([The PAM service used by $2 will be $$3_PAM_SERVICE]) + AC_DEFINE_UNQUOTED($3_PAM_SERVICE, "$$3_PAM_SERVICE", [The PAM service to be used by $2]) + fi + AC_SUBST($3_PAM_SERVICE) +]) + +AC_DEFUN([KDE_SHADOWPASSWD], [ + AC_REQUIRE([KDE_PAM]) + + AC_CHECK_LIB(shadow, getspent, + [ LIBSHADOW="-lshadow" + ac_use_shadow=yes + ], + [ dnl for UnixWare + AC_CHECK_LIB(gen, getspent, + [ LIBGEN="-lgen" + ac_use_shadow=yes + ], + [ AC_CHECK_FUNC(getspent, + [ ac_use_shadow=yes ], + [ ac_use_shadow=no ]) + ]) + ]) + AC_SUBST(LIBSHADOW) + AC_SUBST(LIBGEN) + + AC_MSG_CHECKING([for shadow passwords]) + + AC_ARG_WITH(shadow, + AC_HELP_STRING([--with-shadow],[If you want shadow password support]), + [ if test "x$withval" != "xno"; then + use_shadow=yes + else + use_shadow=no + fi + ], [ + use_shadow="$ac_use_shadow" + ]) + + if test "x$use_shadow" = xyes; then + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_SHADOW, 1, [Define if you use shadow passwords]) + else + AC_MSG_RESULT(no) + LIBSHADOW= + LIBGEN= + fi + + dnl finally make the relevant binaries setuid root, if we have shadow passwds. + dnl this still applies, if we could use it indirectly through pam. + if test "x$use_shadow" = xyes || + ( test "x$use_pam" = xyes && test "x$ac_use_shadow" = xyes ); then + case $host in + *-*-freebsd* | *-*-netbsd* | *-*-openbsd*) + SETUIDFLAGS="-m 4755 -o root";; + *) + SETUIDFLAGS="-m 4755";; + esac + fi + AC_SUBST(SETUIDFLAGS) + +]) + +AC_DEFUN([KDE_PASSWDLIBS], [ + AC_REQUIRE([KDE_MISC_TESTS]) dnl for LIBCRYPT + AC_REQUIRE([KDE_PAM]) + AC_REQUIRE([KDE_SHADOWPASSWD]) + + if test "x$use_pam" = "xyes"; then + PASSWDLIBS="$PAMLIBS" + else + PASSWDLIBS="$LIBCRYPT $LIBSHADOW $LIBGEN" + fi + + dnl FreeBSD uses a shadow-like setup, where /etc/passwd holds the users, but + dnl /etc/master.passwd holds the actual passwords. /etc/master.passwd requires + dnl root to read, so kcheckpass needs to be root (even when using pam, since pam + dnl may need to read /etc/master.passwd). + case $host in + *-*-freebsd*) + SETUIDFLAGS="-m 4755 -o root" + ;; + *) + ;; + esac + + AC_SUBST(PASSWDLIBS) +]) + +AC_DEFUN([KDE_CHECK_LIBDL], +[ +AC_CHECK_LIB(dl, dlopen, [ +LIBDL="-ldl" +ac_cv_have_dlfcn=yes +]) + +AC_CHECK_LIB(dld, shl_unload, [ +LIBDL="-ldld" +ac_cv_have_shload=yes +]) + +AC_SUBST(LIBDL) +]) + +AC_DEFUN([KDE_CHECK_DLOPEN], +[ +KDE_CHECK_LIBDL +AC_CHECK_HEADERS(dlfcn.h dl.h) +if test "$ac_cv_header_dlfcn_h" = "no"; then + ac_cv_have_dlfcn=no +fi + +if test "$ac_cv_header_dl_h" = "no"; then + ac_cv_have_shload=no +fi + +dnl XXX why change enable_dlopen? its already set by autoconf's AC_ARG_ENABLE +dnl (MM) +AC_ARG_ENABLE(dlopen, +AC_HELP_STRING([--disable-dlopen],[link statically [default=no]]), +enable_dlopen=$enableval, +enable_dlopen=yes) + +# override the user's opinion, if we know it better ;) +if test "$ac_cv_have_dlfcn" = "no" && test "$ac_cv_have_shload" = "no"; then + enable_dlopen=no +fi + +if test "$ac_cv_have_dlfcn" = "yes"; then + AC_DEFINE_UNQUOTED(HAVE_DLFCN, 1, [Define if you have dlfcn]) +fi + +if test "$ac_cv_have_shload" = "yes"; then + AC_DEFINE_UNQUOTED(HAVE_SHLOAD, 1, [Define if you have shload]) +fi + +if test "$enable_dlopen" = no ; then + test -n "$1" && eval $1 +else + test -n "$2" && eval $2 +fi + +]) + +AC_DEFUN([KDE_CHECK_DYNAMIC_LOADING], +[ +KDE_CHECK_DLOPEN(libtool_enable_shared=yes, libtool_enable_static=no) +KDE_PROG_LIBTOOL +AC_MSG_CHECKING([dynamic loading]) +eval "`egrep '^build_libtool_libs=' libtool`" +if test "$build_libtool_libs" = "yes" && test "$enable_dlopen" = "yes"; then + dynamic_loading=yes + AC_DEFINE_UNQUOTED(HAVE_DYNAMIC_LOADING) +else + dynamic_loading=no +fi +AC_MSG_RESULT($dynamic_loading) +if test "$dynamic_loading" = "yes"; then + $1 +else + $2 +fi +]) + +AC_DEFUN([KDE_ADD_INCLUDES], +[ +if test -z "$1"; then + test_include="Pix.h" +else + test_include="$1" +fi + +AC_MSG_CHECKING([for libg++ ($test_include)]) + +AC_CACHE_VAL(kde_cv_libgpp_includes, +[ +kde_cv_libgpp_includes=no + + for ac_dir in \ + \ + /usr/include/g++ \ + /usr/include \ + /usr/unsupported/include \ + /opt/include \ + $extra_include \ + ; \ + do + if test -r "$ac_dir/$test_include"; then + kde_cv_libgpp_includes=$ac_dir + break + fi + done +]) + +AC_MSG_RESULT($kde_cv_libgpp_includes) +if test "$kde_cv_libgpp_includes" != "no"; then + all_includes="-I$kde_cv_libgpp_includes $all_includes $USER_INCLUDES" +fi +]) +]) + +AC_DEFUN([KDE_CHECK_LIBPTHREAD], +[ + dnl This code is here specifically to handle the + dnl various flavors of threading library on FreeBSD + dnl 4-, 5-, and 6-, and the (weird) rules around it. + dnl There may be an environment PTHREAD_LIBS that + dnl specifies what to use; otherwise, search for it. + dnl -pthread is special cased and unsets LIBPTHREAD + dnl below if found. + LIBPTHREAD="" + + if test -n "$PTHREAD_LIBS"; then + if test "x$PTHREAD_LIBS" = "x-pthread" ; then + LIBPTHREAD="PTHREAD" + else + PTHREAD_LIBS_save="$PTHREAD_LIBS" + PTHREAD_LIBS=`echo "$PTHREAD_LIBS_save" | sed -e 's,^-l,,g'` + AC_MSG_CHECKING([for pthread_create in $PTHREAD_LIBS]) + KDE_CHECK_LIB($PTHREAD_LIBS, pthread_create, [ + LIBPTHREAD="$PTHREAD_LIBS_save"]) + PTHREAD_LIBS="$PTHREAD_LIBS_save" + fi + fi + + dnl Is this test really needed, in the face of the Tru64 test below? + if test -z "$LIBPTHREAD"; then + AC_CHECK_LIB(pthread, pthread_create, [LIBPTHREAD="-lpthread"]) + fi + + dnl This is a special Tru64 check, see BR 76171 issue #18. + if test -z "$LIBPTHREAD" ; then + AC_MSG_CHECKING([for pthread_create in -lpthread]) + kde_safe_libs=$LIBS + LIBS="$LIBS -lpthread" + AC_TRY_LINK([#include ],[(void)pthread_create(0,0,0,0);],[ + AC_MSG_RESULT(yes) + LIBPTHREAD="-lpthread"],[ + AC_MSG_RESULT(no)]) + LIBS=$kde_safe_libs + fi + + dnl Un-special-case for FreeBSD. + if test "x$LIBPTHREAD" = "xPTHREAD" ; then + LIBPTHREAD="" + fi + + AC_SUBST(LIBPTHREAD) +]) + +AC_DEFUN([KDE_CHECK_PTHREAD_OPTION], +[ + USE_THREADS="" + if test -z "$LIBPTHREAD"; then + KDE_CHECK_COMPILER_FLAG(pthread, [USE_THREADS="-D_THREAD_SAFE -pthread"]) + fi + + AH_VERBATIM(__svr_define, [ +#if defined(__SVR4) && !defined(__svr4__) +#define __svr4__ 1 +#endif +]) + case $host_os in + solaris*) + KDE_CHECK_COMPILER_FLAG(mt, [USE_THREADS="-mt"]) + CPPFLAGS="$CPPFLAGS -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS -DUSE_SOLARIS -DSVR4" + ;; + freebsd*) + CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE $PTHREAD_CFLAGS" + ;; + aix*) + CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" + LIBPTHREAD="$LIBPTHREAD -lc_r" + ;; + linux*) CPPFLAGS="$CPPFLAGS -D_REENTRANT" + if test "$CXX" = "KCC"; then + CXXFLAGS="$CXXFLAGS --thread_safe" + NOOPT_CXXFLAGS="$NOOPT_CXXFLAGS --thread_safe" + fi + ;; + *) + ;; + esac + AC_SUBST(USE_THREADS) + AC_SUBST(LIBPTHREAD) +]) + +AC_DEFUN([KDE_CHECK_THREADING], +[ + AC_REQUIRE([KDE_CHECK_LIBPTHREAD]) + AC_REQUIRE([KDE_CHECK_PTHREAD_OPTION]) + dnl default is yes if libpthread is found and no if no libpthread is available + if test -z "$LIBPTHREAD"; then + if test -z "$USE_THREADS"; then + kde_check_threading_default=no + else + kde_check_threading_default=yes + fi + else + kde_check_threading_default=yes + fi + AC_ARG_ENABLE(threading,AC_HELP_STRING([--disable-threading],[disables threading even if libpthread found]), + kde_use_threading=$enableval, kde_use_threading=$kde_check_threading_default) + if test "x$kde_use_threading" = "xyes"; then + AC_DEFINE(HAVE_LIBPTHREAD, 1, [Define if you have a working libpthread (will enable threaded code)]) + fi +]) + +AC_DEFUN([KDE_TRY_LINK_PYTHON], +[ +if test "$kde_python_link_found" = no; then + +if test "$1" = normal; then + AC_MSG_CHECKING(if a Python application links) +else + AC_MSG_CHECKING(if Python depends on $2) +fi + +AC_CACHE_VAL(kde_cv_try_link_python_$1, +[ +kde_save_cflags="$CFLAGS" +CFLAGS="$CFLAGS $PYTHONINC" +kde_save_libs="$LIBS" +LIBS="$LIBS $LIBPYTHON $2 $LIBDL $LIBSOCKET" +kde_save_ldflags="$LDFLAGS" +LDFLAGS="$LDFLAGS $PYTHONLIB" + +AC_TRY_LINK( +[ +#include +],[ + PySys_SetArgv(1, 0); +], + [kde_cv_try_link_python_$1=yes], + [kde_cv_try_link_python_$1=no] +) +CFLAGS="$kde_save_cflags" +LIBS="$kde_save_libs" +LDFLAGS="$kde_save_ldflags" +]) + +if test "$kde_cv_try_link_python_$1" = "yes"; then + AC_MSG_RESULT(yes) + kde_python_link_found=yes + if test ! "$1" = normal; then + LIBPYTHON="$LIBPYTHON $2" + fi + $3 +else + AC_MSG_RESULT(no) + $4 +fi + +fi + +]) + +AC_DEFUN([KDE_CHECK_PYTHON_DIR], +[ +AC_MSG_CHECKING([for Python directory]) + +AC_CACHE_VAL(kde_cv_pythondir, +[ + if test -z "$PYTHONDIR"; then + kde_cv_pythondir=/usr/local + else + kde_cv_pythondir="$PYTHONDIR" + fi +]) + +AC_ARG_WITH(pythondir, +AC_HELP_STRING([--with-pythondir=pythondir],[use python installed in pythondir]), +[ + ac_python_dir=$withval +], ac_python_dir=$kde_cv_pythondir +) + +AC_MSG_RESULT($ac_python_dir) +]) + +AC_DEFUN([KDE_CHECK_PYTHON_INTERN], +[ +AC_REQUIRE([KDE_CHECK_LIBDL]) +AC_REQUIRE([KDE_CHECK_LIBPTHREAD]) +AC_REQUIRE([KDE_CHECK_PYTHON_DIR]) + +if test -z "$1"; then + version="1.5" +else + version="$1" +fi + +AC_MSG_CHECKING([for Python$version]) + +python_incdirs="$ac_python_dir/include /usr/include /usr/local/include/ $kde_extra_includes" +AC_FIND_FILE(Python.h, $python_incdirs, python_incdir) +if test ! -r $python_incdir/Python.h; then + AC_FIND_FILE(python$version/Python.h, $python_incdirs, python_incdir) + python_incdir=$python_incdir/python$version + if test ! -r $python_incdir/Python.h; then + python_incdir=no + fi +fi + +PYTHONINC=-I$python_incdir + +python_libdirs="$ac_python_dir/lib$kdelibsuff /usr/lib$kdelibsuff /usr/local /usr/lib$kdelibsuff $kde_extra_libs" +AC_FIND_FILE(libpython$version.so, $python_libdirs, python_libdir) +if test ! -r $python_libdir/libpython$version.so; then + AC_FIND_FILE(libpython$version.a, $python_libdirs, python_libdir) + if test ! -r $python_libdir/libpython$version.a; then + AC_FIND_FILE(python$version/config/libpython$version.a, $python_libdirs, python_libdir) + python_libdir=$python_libdir/python$version/config + if test ! -r $python_libdir/libpython$version.a; then + python_libdir=no + fi + fi +fi + +PYTHONLIB=-L$python_libdir +kde_orig_LIBPYTHON=$LIBPYTHON +if test -z "$LIBPYTHON"; then + LIBPYTHON=-lpython$version +fi + +AC_FIND_FILE(python$version/copy.py, $python_libdirs, python_moddir) +python_moddir=$python_moddir/python$version +if test ! -r $python_moddir/copy.py; then + python_moddir=no +fi + +PYTHONMODDIR=$python_moddir + +AC_MSG_RESULT(header $python_incdir library $python_libdir modules $python_moddir) + +if test x$python_incdir = xno || test x$python_libdir = xno || test x$python_moddir = xno; then + LIBPYTHON=$kde_orig_LIBPYTHON + test "x$PYTHONLIB" = "x-Lno" && PYTHONLIB="" + test "x$PYTHONINC" = "x-Ino" && PYTHONINC="" + $2 +else + dnl Note: this test is very weak + kde_python_link_found=no + KDE_TRY_LINK_PYTHON(normal) + KDE_TRY_LINK_PYTHON(m, -lm) + KDE_TRY_LINK_PYTHON(pthread, $LIBPTHREAD) + KDE_TRY_LINK_PYTHON(tcl, -ltcl) + KDE_TRY_LINK_PYTHON(db2, -ldb2) + KDE_TRY_LINK_PYTHON(m_and_thread, [$LIBPTHREAD -lm]) + KDE_TRY_LINK_PYTHON(m_and_thread_and_util, [$LIBPTHREAD -lm -lutil]) + KDE_TRY_LINK_PYTHON(m_and_thread_and_db3, [$LIBPTHREAD -lm -ldb-3 -lutil]) + KDE_TRY_LINK_PYTHON(pthread_and_db3, [$LIBPTHREAD -ldb-3]) + KDE_TRY_LINK_PYTHON(m_and_thread_and_db, [$LIBPTHREAD -lm -ldb -ltermcap -lutil]) + KDE_TRY_LINK_PYTHON(pthread_and_dl, [$LIBPTHREAD $LIBDL -lutil -lreadline -lncurses -lm]) + KDE_TRY_LINK_PYTHON(pthread_and_panel_curses, [$LIBPTHREAD $LIBDL -lm -lpanel -lcurses]) + KDE_TRY_LINK_PYTHON(m_and_thread_and_db_special, [$LIBPTHREAD -lm -ldb -lutil], [], + [AC_MSG_WARN([it seems, Python depends on another library. + Please set LIBPYTHON to '-lpython$version -lotherlib' before calling configure to fix this + and contact the authors to let them know about this problem]) + ]) + + LIBPYTHON="$LIBPYTHON $LIBDL $LIBSOCKET" + AC_SUBST(PYTHONINC) + AC_SUBST(PYTHONLIB) + AC_SUBST(LIBPYTHON) + AC_SUBST(PYTHONMODDIR) + AC_DEFINE(HAVE_PYTHON, 1, [Define if you have the development files for python]) +fi + +]) + + +AC_DEFUN([KDE_CHECK_PYTHON], +[ + KDE_CHECK_PYTHON_INTERN("2.4", + [KDE_CHECK_PYTHON_INTERN("2.3", + [KDE_CHECK_PYTHON_INTERN("2.2", + [KDE_CHECK_PYTHON_INTERN("2.1", + [KDE_CHECK_PYTHON_INTERN("2.0", + [KDE_CHECK_PYTHON_INTERN($1, $2) ]) + ]) + ]) + ]) + ]) +]) + +AC_DEFUN([KDE_CHECK_STL], +[ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="`echo $CXXFLAGS | sed s/-fno-exceptions//`" + + AC_MSG_CHECKING([if C++ programs can be compiled]) + AC_CACHE_VAL(kde_cv_stl_works, + [ + AC_TRY_COMPILE([ +#include +using namespace std; +],[ + string astring="Hallo Welt."; + astring.erase(0, 6); // now astring is "Welt" + return 0; +], kde_cv_stl_works=yes, + kde_cv_stl_works=no) +]) + + AC_MSG_RESULT($kde_cv_stl_works) + + if test "$kde_cv_stl_works" = "yes"; then + # back compatible + AC_DEFINE_UNQUOTED(HAVE_SGI_STL, 1, [Define if you have a STL implementation by SGI]) + else + AC_MSG_ERROR([Your Installation isn't able to compile simple C++ programs. +Check config.log for details - if you're using a Linux distribution you might miss +a package named similar to libstdc++-dev.]) + fi + + CXXFLAGS="$ac_save_CXXFLAGS" + AC_LANG_RESTORE +]) + +AC_DEFUN([AC_FIND_QIMGIO], + [AC_REQUIRE([AC_FIND_JPEG]) +AC_REQUIRE([KDE_CHECK_EXTRA_LIBS]) +AC_MSG_CHECKING([for qimgio]) +AC_CACHE_VAL(ac_cv_lib_qimgio, +[ +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +ac_save_LIBS="$LIBS" +ac_save_CXXFLAGS="$CXXFLAGS" +LIBS="$all_libraries -lqimgio -lpng -lz $LIBJPEG $LIBQT" +CXXFLAGS="$CXXFLAGS -I$qt_incdir $all_includes" +AC_TRY_RUN(dnl +[ +#include +#include +int main() { + QString t = "hallo"; + t.fill('t'); + qInitImageIO(); +} +], + ac_cv_lib_qimgio=yes, + ac_cv_lib_qimgio=no, + ac_cv_lib_qimgio=no) +LIBS="$ac_save_LIBS" +CXXFLAGS="$ac_save_CXXFLAGS" +AC_LANG_RESTORE +])dnl +if eval "test \"`echo $ac_cv_lib_qimgio`\" = yes"; then + LIBQIMGIO="-lqimgio -lpng -lz $LIBJPEG" + AC_MSG_RESULT(yes) + AC_DEFINE_UNQUOTED(HAVE_QIMGIO, 1, [Define if you have the Qt extension qimgio available]) + AC_SUBST(LIBQIMGIO) +else + AC_MSG_RESULT(not found) +fi +]) + +AC_DEFUN([AM_DISABLE_LIBRARIES], +[ + AC_PROVIDE([AM_ENABLE_STATIC]) + AC_PROVIDE([AM_ENABLE_SHARED]) + enable_static=no + enable_shared=yes +]) + + +AC_DEFUN([AC_CHECK_UTMP_FILE], +[ + AC_MSG_CHECKING([for utmp file]) + + AC_CACHE_VAL(kde_cv_utmp_file, + [ + kde_cv_utmp_file=no + + for ac_file in \ + \ + /var/run/utmp \ + /var/adm/utmp \ + /etc/utmp \ + ; \ + do + if test -r "$ac_file"; then + kde_cv_utmp_file=$ac_file + break + fi + done + ]) + + if test "$kde_cv_utmp_file" != "no"; then + AC_DEFINE_UNQUOTED(UTMP, "$kde_cv_utmp_file", [Define the file for utmp entries]) + $1 + AC_MSG_RESULT($kde_cv_utmp_file) + else + $2 + AC_MSG_RESULT([non found]) + fi +]) + + +AC_DEFUN([KDE_CREATE_SUBDIRSLIST], +[ + +DO_NOT_COMPILE="$DO_NOT_COMPILE CVS debian bsd-port admin" +TOPSUBDIRS="" + +if test ! -s $srcdir/subdirs; then + dnl Note: Makefile.common creates subdirs, so this is just a fallback + files=`cd $srcdir && ls -1` + dirs=`for i in $files; do if test -d $i; then echo $i; fi; done` + for i in $dirs; do + echo $i >> $srcdir/subdirs + done +fi + +ac_topsubdirs= +if test -s $srcdir/inst-apps; then + ac_topsubdirs="`cat $srcdir/inst-apps`" +elif test -s $srcdir/subdirs; then + ac_topsubdirs="`cat $srcdir/subdirs`" +fi + +for i in $ac_topsubdirs; do + AC_MSG_CHECKING([if $i should be compiled]) + if test -d $srcdir/$i; then + install_it="yes" + for j in $DO_NOT_COMPILE; do + if test $i = $j; then + install_it="no" + fi + done + else + install_it="no" + fi + AC_MSG_RESULT($install_it) + vari=`echo $i | sed -e 's,[[-+.@]],_,g'` + if test $install_it = "yes"; then + TOPSUBDIRS="$TOPSUBDIRS $i" + eval "$vari""_SUBDIR_included=yes" + else + eval "$vari""_SUBDIR_included=no" + fi +done + +AC_SUBST(TOPSUBDIRS) +]) + +AC_DEFUN([KDE_CHECK_NAMESPACES], +[ +AC_MSG_CHECKING(whether C++ compiler supports namespaces) +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +AC_TRY_COMPILE([ +], +[ +namespace Foo { + extern int i; + namespace Bar { + extern int i; + } +} + +int Foo::i = 0; +int Foo::Bar::i = 1; +],[ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_NAMESPACES) +], [ +AC_MSG_RESULT(no) +]) +AC_LANG_RESTORE +]) + +dnl ------------------------------------------------------------------------ +dnl Check for S_ISSOCK macro. Doesn't exist on Unix SCO. faure@kde.org +dnl ------------------------------------------------------------------------ +dnl +AC_DEFUN([AC_CHECK_S_ISSOCK], +[ +AC_MSG_CHECKING(for S_ISSOCK) +AC_CACHE_VAL(ac_cv_have_s_issock, +[ +AC_TRY_LINK( +[ +#include +], +[ +struct stat buff; +int b = S_ISSOCK( buff.st_mode ); +], +ac_cv_have_s_issock=yes, +ac_cv_have_s_issock=no) +]) +AC_MSG_RESULT($ac_cv_have_s_issock) +if test "$ac_cv_have_s_issock" = "yes"; then + AC_DEFINE_UNQUOTED(HAVE_S_ISSOCK, 1, [Define if sys/stat.h declares S_ISSOCK.]) +fi + +AH_VERBATIM(_ISSOCK, +[ +#ifndef HAVE_S_ISSOCK +#define HAVE_S_ISSOCK +#define S_ISSOCK(mode) (1==0) +#endif +]) + +]) + +dnl ------------------------------------------------------------------------ +dnl Check for MAXPATHLEN macro, defines KDEMAXPATHLEN. faure@kde.org +dnl ------------------------------------------------------------------------ +dnl +AC_DEFUN([AC_CHECK_KDEMAXPATHLEN], +[ +AC_MSG_CHECKING(for MAXPATHLEN) +AC_CACHE_VAL(ac_cv_maxpathlen, +[ +cat > conftest.$ac_ext < +#endif +#include +#include +#ifndef MAXPATHLEN +#define MAXPATHLEN 1024 +#endif + +KDE_HELLO MAXPATHLEN + +EOF + +ac_try="$ac_cpp conftest.$ac_ext 2>/dev/null | grep '^KDE_HELLO' >conftest.out" + +if AC_TRY_EVAL(ac_try) && test -s conftest.out; then + ac_cv_maxpathlen=`sed 's#KDE_HELLO ##' conftest.out` +else + ac_cv_maxpathlen=1024 +fi + +rm conftest.* + +]) +AC_MSG_RESULT($ac_cv_maxpathlen) +AC_DEFINE_UNQUOTED(KDEMAXPATHLEN,$ac_cv_maxpathlen, [Define a safe value for MAXPATHLEN] ) +]) + +AC_DEFUN([KDE_CHECK_HEADER], +[ + kde_safe_cppflags=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $all_includes" + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_CHECK_HEADER([$1], [$2], [$3], [$4]) + AC_LANG_RESTORE + CPPFLAGS=$kde_safe_cppflags +]) + +AC_DEFUN([KDE_CHECK_HEADERS], +[ + AH_CHECK_HEADERS([$1]) + AC_LANG_SAVE + kde_safe_cppflags=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $all_includes" + AC_LANG_CPLUSPLUS + AC_CHECK_HEADERS([$1], [$2], [$3], [$4]) + CPPFLAGS=$kde_safe_cppflags + AC_LANG_RESTORE +]) + +AC_DEFUN([KDE_FAST_CONFIGURE], +[ + dnl makes configure fast (needs perl) + AC_ARG_ENABLE(fast-perl, AC_HELP_STRING([--disable-fast-perl],[disable fast Makefile generation (needs perl)]), + with_fast_perl=$enableval, with_fast_perl=yes) +]) + +AC_DEFUN([KDE_CONF_FILES], +[ + val= + if test -f $srcdir/configure.files ; then + val=`sed -e 's%^%\$(top_srcdir)/%' $srcdir/configure.files` + fi + CONF_FILES= + if test -n "$val" ; then + for i in $val ; do + CONF_FILES="$CONF_FILES $i" + done + fi + AC_SUBST(CONF_FILES) +])dnl + +dnl This sets the prefix, for arts and kdelibs +dnl Do NOT use in any other module. +dnl It only looks at --prefix, KDEDIR and falls back to /usr/local/kde +AC_DEFUN([KDE_SET_PREFIX_CORE], +[ + unset CDPATH + dnl make $KDEDIR the default for the installation + AC_PREFIX_DEFAULT(${KDEDIR:-/usr/local/kde}) + + if test "x$prefix" = "xNONE"; then + prefix=$ac_default_prefix + ac_configure_args="$ac_configure_args --prefix=$prefix" + fi + # And delete superfluous '/' to make compares easier + prefix=`echo "$prefix" | sed 's,//*,/,g' | sed -e 's,/$,,'` + kde_libs_htmldir=$prefix/share/doc/HTML/ + exec_prefix=`echo "$exec_prefix" | sed 's,//*,/,g' | sed -e 's,/$,,'` + + kde_libs_prefix='$(prefix)' + kde_libs_htmldir='$(kde_htmldir)' + AC_SUBST(kde_libs_prefix) + AC_SUBST(kde_libs_htmldir) + KDE_FAST_CONFIGURE + KDE_CONF_FILES +]) + + +AC_DEFUN([KDE_SET_PREFIX], +[ + unset CDPATH + dnl We can't give real code to that macro, only a value. + dnl It only matters for --help, since we set the prefix in this function anyway. + AC_PREFIX_DEFAULT(${KDEDIR:-the kde prefix}) + + KDE_SET_DEFAULT_BINDIRS + if test "x$prefix" = "xNONE"; then + dnl no prefix given: look for kde-config in the PATH and deduce the prefix from it + KDE_FIND_PATH(kde-config, KDECONFIG, [$kde_default_bindirs], [KDE_MISSING_PROG_ERROR(kde-config)], [], prepend) + else + dnl prefix given: look for kde-config, preferrably in prefix, otherwise in PATH + kde_save_PATH="$PATH" + PATH="$exec_prefix/bin:$prefix/bin:$PATH" + KDE_FIND_PATH(kde-config, KDECONFIG, [$kde_default_bindirs], [KDE_MISSING_PROG_ERROR(kde-config)], [], prepend) + PATH="$kde_save_PATH" + fi + + kde_libs_prefix=`$KDECONFIG --prefix` + if test -z "$kde_libs_prefix" || test ! -x "$kde_libs_prefix"; then + AC_MSG_ERROR([$KDECONFIG --prefix outputed the non existant prefix '$kde_libs_prefix' for kdelibs. + This means it has been moved since you installed it. + This won't work. Please recompile kdelibs for the new prefix. + ]) + fi + kde_libs_htmldir=`$KDECONFIG --install html --expandvars` + kde_libs_suffix=`$KDECONFIG --libsuffix` + + AC_MSG_CHECKING([where to install]) + if test "x$prefix" = "xNONE"; then + prefix=$kde_libs_prefix + AC_MSG_RESULT([$prefix (as returned by kde-config)]) + else + dnl --prefix was given. Compare prefixes and warn (in configure.in.bot.end) if different + given_prefix=$prefix + AC_MSG_RESULT([$prefix (as requested)]) + fi + + # And delete superfluous '/' to make compares easier + prefix=`echo "$prefix" | sed 's,//*,/,g' | sed -e 's,/$,,'` + exec_prefix=`echo "$exec_prefix" | sed 's,//*,/,g' | sed -e 's,/$,,'` + given_prefix=`echo "$given_prefix" | sed 's,//*,/,g' | sed -e 's,/$,,'` + + AC_SUBST(KDECONFIG) + AC_SUBST(kde_libs_prefix) + AC_SUBST(kde_libs_htmldir) + + KDE_FAST_CONFIGURE + KDE_CONF_FILES +]) + +pushdef([AC_PROG_INSTALL], +[ + dnl our own version, testing for a -p flag + popdef([AC_PROG_INSTALL]) + dnl as AC_PROG_INSTALL works as it works we first have + dnl to save if the user didn't specify INSTALL, as the + dnl autoconf one overwrites INSTALL and we have no chance to find + dnl out afterwards + test -n "$INSTALL" && kde_save_INSTALL_given=$INSTALL + test -n "$INSTALL_PROGRAM" && kde_save_INSTALL_PROGRAM_given=$INSTALL_PROGRAM + test -n "$INSTALL_SCRIPT" && kde_save_INSTALL_SCRIPT_given=$INSTALL_SCRIPT + AC_PROG_INSTALL + + if test -z "$kde_save_INSTALL_given" ; then + # OK, user hasn't given any INSTALL, autoconf found one for us + # now we test, if it supports the -p flag + AC_MSG_CHECKING(for -p flag to install) + rm -f confinst.$$.* > /dev/null 2>&1 + echo "Testtest" > confinst.$$.orig + ac_res=no + if ${INSTALL} -p confinst.$$.orig confinst.$$.new > /dev/null 2>&1 ; then + if test -f confinst.$$.new ; then + # OK, -p seems to do no harm to install + INSTALL="${INSTALL} -p" + ac_res=yes + fi + fi + rm -f confinst.$$.* + AC_MSG_RESULT($ac_res) + fi + dnl the following tries to resolve some signs and wonders coming up + dnl with different autoconf/automake versions + dnl e.g.: + dnl *automake 1.4 install-strip sets A_M_INSTALL_PROGRAM_FLAGS to -s + dnl and has INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(A_M_INSTALL_PROGRAM_FLAGS) + dnl it header-vars.am, so there the actual INSTALL_PROGRAM gets the -s + dnl *automake 1.4a (and above) use INSTALL_STRIP_FLAG and only has + dnl INSTALL_PROGRAM = @INSTALL_PROGRAM@ there, but changes the + dnl install-@DIR@PROGRAMS targets to explicitly use that flag + dnl *autoconf 2.13 is dumb, and thinks it can use INSTALL_PROGRAM as + dnl INSTALL_SCRIPT, which breaks with automake <= 1.4 + dnl *autoconf >2.13 (since 10.Apr 1999) has not that failure + dnl *sometimes KDE does not use the install-@DIR@PROGRAM targets from + dnl automake (due to broken Makefile.am or whatever) to install programs, + dnl and so does not see the -s flag in automake > 1.4 + dnl to clean up that mess we: + dnl +set INSTALL_PROGRAM to use INSTALL_STRIP_FLAG + dnl which cleans KDE's program with automake > 1.4; + dnl +set INSTALL_SCRIPT to only use INSTALL, to clean up autoconf's problems + dnl with automake<=1.4 + dnl note that dues to this sometimes two '-s' flags are used (if KDE + dnl properly uses install-@DIR@PROGRAMS, but I don't care + dnl + dnl And to all this comes, that I even can't write in comments variable + dnl names used by automake, because it is so stupid to think I wanted to + dnl _use_ them, therefor I have written A_M_... instead of AM_ + dnl hmm, I wanted to say something ... ahh yes: Arghhh. + + if test -z "$kde_save_INSTALL_PROGRAM_given" ; then + INSTALL_PROGRAM='${INSTALL} $(INSTALL_STRIP_FLAG)' + fi + if test -z "$kde_save_INSTALL_SCRIPT_given" ; then + INSTALL_SCRIPT='${INSTALL}' + fi +])dnl + +AC_DEFUN([KDE_LANG_CPLUSPLUS], +[AC_LANG_CPLUSPLUS +ac_link='rm -rf SunWS_cache; ${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&AC_FD_CC' +pushdef([AC_LANG_CPLUSPLUS], [popdef([AC_LANG_CPLUSPLUS]) KDE_LANG_CPLUSPLUS]) +]) + +pushdef([AC_LANG_CPLUSPLUS], +[popdef([AC_LANG_CPLUSPLUS]) +KDE_LANG_CPLUSPLUS +]) + +AC_DEFUN([KDE_CHECK_LONG_LONG], +[ +AC_MSG_CHECKING(for long long) +AC_CACHE_VAL(kde_cv_c_long_long, +[ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_TRY_LINK([], [ + long long foo = 0; + foo = foo+1; + ], + kde_cv_c_long_long=yes, kde_cv_c_long_long=no) + AC_LANG_RESTORE +]) +AC_MSG_RESULT($kde_cv_c_long_long) +if test "$kde_cv_c_long_long" = yes; then + AC_DEFINE(HAVE_LONG_LONG, 1, [Define if you have long long as datatype]) +fi +]) + +AC_DEFUN([KDE_CHECK_LIB], +[ + kde_save_LDFLAGS="$LDFLAGS" + dnl AC_CHECK_LIB modifies LIBS, so save it here + kde_save_LIBS="$LIBS" + LDFLAGS="$LDFLAGS $all_libraries" + case $host_os in + aix*) LDFLAGS="-brtl $LDFLAGS" + test "$GCC" = yes && LDFLAGS="-Wl,$LDFLAGS" + ;; + esac + AC_CHECK_LIB($1, $2, $3, $4, $5) + LDFLAGS="$kde_save_LDFLAGS" + LIBS="$kde_save_LIBS" +]) + +AC_DEFUN([KDE_JAVA_PREFIX], +[ + dir=`dirname "$1"` + base=`basename "$1"` + list=`ls -1 $dir 2> /dev/null` + for entry in $list; do + if test -d $dir/$entry/bin; then + case $entry in + $base) + javadirs="$javadirs $dir/$entry/bin" + ;; + esac + elif test -d $dir/$entry/jre/bin; then + case $entry in + $base) + javadirs="$javadirs $dir/$entry/jre/bin" + ;; + esac + fi + done +]) + +dnl KDE_CHEC_JAVA_DIR(onlyjre) +AC_DEFUN([KDE_CHECK_JAVA_DIR], +[ + +AC_ARG_WITH(java, +AC_HELP_STRING([--with-java=javadir],[use java installed in javadir, --without-java disables]), +[ ac_java_dir=$withval +], ac_java_dir="" +) + +AC_MSG_CHECKING([for Java]) + +dnl at this point ac_java_dir is either a dir, 'no' to disable, or '' to say look in $PATH +if test "x$ac_java_dir" = "xno"; then + kde_java_bindir=no + kde_java_includedir=no + kde_java_libjvmdir=no + kde_java_libgcjdir=no + kde_java_libhpidir=no +else + if test "x$ac_java_dir" = "x"; then + + + dnl No option set -> collect list of candidate paths + if test -n "$JAVA_HOME"; then + KDE_JAVA_PREFIX($JAVA_HOME) + fi + KDE_JAVA_PREFIX(/usr/j2se) + KDE_JAVA_PREFIX(/usr/lib/j2se) + KDE_JAVA_PREFIX(/usr/j*dk*) + KDE_JAVA_PREFIX(/usr/lib/j*dk*) + KDE_JAVA_PREFIX(/opt/j*sdk*) + KDE_JAVA_PREFIX(/usr/lib/java*) + KDE_JAVA_PREFIX(/usr/java*) + KDE_JAVA_PREFIX(/usr/java/j*dk*) + KDE_JAVA_PREFIX(/usr/java/j*re*) + KDE_JAVA_PREFIX(/usr/lib/SunJava2*) + KDE_JAVA_PREFIX(/usr/lib/SunJava*) + KDE_JAVA_PREFIX(/usr/lib/IBMJava2*) + KDE_JAVA_PREFIX(/usr/lib/IBMJava*) + KDE_JAVA_PREFIX(/opt/java*) + + kde_cv_path="NONE" + kde_save_IFS=$IFS + IFS=':' + for dir in $PATH; do + if test -d "$dir"; then + javadirs="$javadirs $dir" + fi + done + IFS=$kde_save_IFS + jredirs= + + dnl Now javadirs contains a list of paths that exist, all ending with bin/ + for dir in $javadirs; do + dnl Check for the java executable + if test -x "$dir/java"; then + dnl And also check for a libjvm.so somewhere under there + dnl Since we have to go to the parent dir, /usr/bin is excluded, /usr is too big. + if test "$dir" != "/usr/bin"; then + libjvmdir=`find $dir/.. -name libjvm.so | sed 's,libjvm.so,,'|head -n 1` + if test ! -f $libjvmdir/libjvm.so; then continue; fi + jredirs="$jredirs $dir" + fi + fi + done + + dnl Now jredirs contains a reduced list, of paths where both java and ../**/libjvm.so was found + JAVAC= + JAVA= + kde_java_bindir=no + for dir in $jredirs; do + JAVA="$dir/java" + kde_java_bindir=$dir + if test -x "$dir/javac"; then + JAVAC="$dir/javac" + break + fi + done + + if test -n "$JAVAC"; then + dnl this substitution might not work - well, we test for jni.h below + kde_java_includedir=`echo $JAVAC | sed -e 's,bin/javac$,include/,'` + else + kde_java_includedir=no + fi + else + dnl config option set + kde_java_bindir=$ac_java_dir/bin + if test -x $ac_java_dir/bin/java && test ! -x $ac_java_dir/bin/javac; then + kde_java_includedir=no + else + kde_java_includedir=$ac_java_dir/include + fi + fi +fi + +dnl At this point kde_java_bindir and kde_java_includedir are either set or "no" +if test "x$kde_java_bindir" != "xno"; then + + dnl Look for libjvm.so + kde_java_libjvmdir=`find $kde_java_bindir/.. -name libjvm.so | sed 's,libjvm.so,,'|head -n 1` + dnl Look for libgcj.so + kde_java_libgcjdir=`find $kde_java_bindir/.. -name libgcj.so | sed 's,libgcj.so,,'|head -n 1` + dnl Look for libhpi.so and avoid green threads + kde_java_libhpidir=`find $kde_java_bindir/.. -name libhpi.so | grep -v green | sed 's,libhpi.so,,' | head -n 1` + + dnl Now check everything's fine under there + dnl the include dir is our flag for having the JDK + if test -d "$kde_java_includedir"; then + if test ! -x "$kde_java_bindir/javac"; then + AC_MSG_ERROR([javac not found under $kde_java_bindir - it seems you passed a wrong --with-java.]) + fi + if test ! -x "$kde_java_bindir/javah"; then + AC_MSG_ERROR([javah not found under $kde_java_bindir. javac was found though! Use --with-java or --without-java.]) + fi + if test ! -x "$kde_java_bindir/jar"; then + AC_MSG_ERROR([jar not found under $kde_java_bindir. javac was found though! Use --with-java or --without-java.]) + fi + if test ! -r "$kde_java_includedir/jni.h"; then + AC_MSG_ERROR([jni.h not found under $kde_java_includedir. Use --with-java or --without-java.]) + fi + + jni_includes="-I$kde_java_includedir" + dnl Strange thing, jni.h requires jni_md.h which is under genunix here.. + dnl and under linux here.. + + dnl not needed for gcj + + if test "x$kde_java_libgcjdir" = "x"; then + test -d "$kde_java_includedir/linux" && jni_includes="$jni_includes -I$kde_java_includedir/linux" + test -d "$kde_java_includedir/solaris" && jni_includes="$jni_includes -I$kde_java_includedir/solaris" + test -d "$kde_java_includedir/genunix" && jni_includes="$jni_includes -I$kde_java_includedir/genunix" + fi + + else + JAVAC= + jni_includes= + fi + + if test "x$kde_java_libgcjdir" = "x"; then + if test ! -r "$kde_java_libjvmdir/libjvm.so"; then + AC_MSG_ERROR([libjvm.so not found under $kde_java_libjvmdir. Use --without-java.]) + fi + else + if test ! -r "$kde_java_libgcjdir/libgcj.so"; then + AC_MSG_ERROR([libgcj.so not found under $kde_java_libgcjdir. Use --without-java.]) + fi + fi + + if test ! -x "$kde_java_bindir/java"; then + AC_MSG_ERROR([java not found under $kde_java_bindir. javac was found though! Use --with-java or --without-java.]) + fi + + dnl not needed for gcj compile + + if test "x$kde_java_libgcjdir" = "x"; then + if test ! -r "$kde_java_libhpidir/libhpi.so"; then + AC_MSG_ERROR([libhpi.so not found under $kde_java_libhpidir. Use --without-java.]) + fi + fi + + if test -n "$jni_includes"; then + dnl Check for JNI version + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + ac_cxxflags_safe="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $all_includes $jni_includes" + + AC_TRY_COMPILE([ + #include + ], + [ + #ifndef JNI_VERSION_1_2 + Syntax Error + #endif + ],[ kde_jni_works=yes ], + [ kde_jni_works=no ]) + + if test $kde_jni_works = no; then + AC_MSG_ERROR([Incorrect version of $kde_java_includedir/jni.h. + You need to have Java Development Kit (JDK) version 1.2. + + Use --with-java to specify another location. + Use --without-java to configure without java support. + Or download a newer JDK and try again. + See e.g. http://java.sun.com/products/jdk/1.2 ]) + fi + + CXXFLAGS="$ac_cxxflags_safe" + AC_LANG_RESTORE + + dnl All tests ok, inform and subst the variables + + JAVAC=$kde_java_bindir/javac + JAVAH=$kde_java_bindir/javah + JAR=$kde_java_bindir/jar + AC_DEFINE_UNQUOTED(PATH_JAVA, "$kde_java_bindir/java", [Define where your java executable is]) + if test "x$kde_java_libgcjdir" = "x"; then + JVMLIBS="-L$kde_java_libjvmdir -ljvm -L$kde_java_libhpidir -lhpi" + else + JVMLIBS="-L$kde_java_libgcjdir -lgcj" + fi + AC_MSG_RESULT([java JDK in $kde_java_bindir]) + + else + AC_DEFINE_UNQUOTED(PATH_JAVA, "$kde_java_bindir/java", [Define where your java executable is]) + AC_MSG_RESULT([java JRE in $kde_java_bindir]) + fi +elif test -d "/Library/Java/Home"; then + kde_java_bindir="/Library/Java/Home/bin" + jni_includes="-I/Library/Java/Home/include" + + JAVAC=$kde_java_bindir/javac + JAVAH=$kde_java_bindir/javah + JAR=$kde_java_bindir/jar + JVMLIBS="-Xlinker -framework -Xlinker JavaVM" + + AC_DEFINE_UNQUOTED(PATH_JAVA, "$kde_java_bindir/java", [Define where your java executable is]) + AC_MSG_RESULT([Apple Java Framework]) +else + AC_MSG_RESULT([none found]) +fi + +AC_SUBST(JAVAC) +AC_SUBST(JAVAH) +AC_SUBST(JAR) +AC_SUBST(JVMLIBS) +AC_SUBST(jni_includes) + +# for backward compat +kde_cv_java_includedir=$kde_java_includedir +kde_cv_java_bindir=$kde_java_bindir +]) + +dnl this is a redefinition of autoconf 2.5x's AC_FOREACH. +dnl When the argument list becomes big, as in KDE for AC_OUTPUT in +dnl big packages, m4_foreach is dog-slow. So use our own version of +dnl it. (matz@kde.org) +m4_define([mm_foreach], +[m4_pushdef([$1])_mm_foreach($@)m4_popdef([$1])]) +m4_define([mm_car], [[$1]]) +m4_define([mm_car2], [[$@]]) +m4_define([_mm_foreach], +[m4_if(m4_quote($2), [], [], + [m4_define([$1], mm_car($2))$3[]_mm_foreach([$1], + mm_car2(m4_shift($2)), + [$3])])]) +m4_define([AC_FOREACH], +[mm_foreach([$1], m4_split(m4_normalize([$2])), [$3])]) + +AC_DEFUN([KDE_NEED_FLEX], +[ +kde_libs_safe=$LIBS +LIBS="$LIBS $USER_LDFLAGS" +AM_PROG_LEX +LIBS=$kde_libs_safe +if test -z "$LEXLIB"; then + AC_MSG_ERROR([You need to have flex installed.]) +fi +AC_SUBST(LEXLIB) +]) + +AC_DEFUN([AC_PATH_QTOPIA], +[ + dnl TODO: use AC_CACHE_VAL + + if test -z "$1"; then + qtopia_minver_maj=1 + qtopia_minver_min=5 + qtopia_minver_pat=0 + else + qtopia_minver_maj=`echo "$1" | sed -e "s/^\(.*\)\..*\..*$/\1/"` + qtopia_minver_min=`echo "$1" | sed -e "s/^.*\.\(.*\)\..*$/\1/"` + qtopia_minver_pat=`echo "$1" | sed -e "s/^.*\..*\.\(.*\)$/\1/"` + fi + + qtopia_minver="$qtopia_minver_maj$qtopia_minver_min$qtopia_minver_pat" + qtopia_minverstr="$qtopia_minver_maj.$qtopia_minver_min.$qtopia_minver_pat" + + AC_REQUIRE([AC_PATH_QT]) + + AC_MSG_CHECKING([for Qtopia]) + + LIB_QTOPIA="-lqpe" + AC_SUBST(LIB_QTOPIA) + + kde_qtopia_dirs="$QPEDIR /opt/Qtopia" + + ac_qtopia_incdir=NO + + AC_ARG_WITH(qtopia-dir, + AC_HELP_STRING([--with-qtopia-dir=DIR],[where the root of Qtopia is installed]), + [ ac_qtopia_incdir="$withval"/include] ) + + qtopia_incdirs="" + for dir in $kde_qtopia_dirs; do + qtopia_incdirs="$qtopia_incdirs $dir/include" + done + + if test ! "$ac_qtopia_incdir" = "NO"; then + qtopia_incdirs="$ac_qtopia_incdir $qtopia_incdirs" + fi + + qtopia_incdir="" + AC_FIND_FILE(qpe/qpeapplication.h, $qtopia_incdirs, qtopia_incdir) + ac_qtopia_incdir="$qtopia_incdir" + + if test -z "$qtopia_incdir"; then + AC_MSG_ERROR([Cannot find Qtopia headers. Please check your installation.]) + fi + + qtopia_ver_maj=`cat $qtopia_incdir/qpe/version.h | sed -n -e 's,.*QPE_VERSION "\(.*\)\..*\..*".*,\1,p'`; + qtopia_ver_min=`cat $qtopia_incdir/qpe/version.h | sed -n -e 's,.*QPE_VERSION ".*\.\(.*\)\..*".*,\1,p'`; + qtopia_ver_pat=`cat $qtopia_incdir/qpe/version.h | sed -n -e 's,.*QPE_VERSION ".*\..*\.\(.*\)".*,\1,p'`; + + qtopia_ver="$qtopia_ver_maj$qtopia_ver_min$qtopia_ver_pat" + qtopia_verstr="$qtopia_ver_maj.$qtopia_ver_min.$qtopia_ver_pat" + if test "$qtopia_ver" -lt "$qtopia_minver"; then + AC_MSG_ERROR([found Qtopia version $qtopia_verstr but version $qtopia_minverstr +is required.]) + fi + + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + + ac_cxxflags_safe="$CXXFLAGS" + ac_ldflags_safe="$LDFLAGS" + ac_libs_safe="$LIBS" + + CXXFLAGS="$CXXFLAGS -I$qtopia_incdir $all_includes" + LDFLAGS="$LDFLAGS $QT_LDFLAGS $all_libraries $USER_LDFLAGS $KDE_MT_LDFLAGS" + LIBS="$LIBS $LIB_QTOPIA $LIBQT" + + cat > conftest.$ac_ext < +#include + +int main( int argc, char **argv ) +{ + QPEApplication app( argc, argv ); + return 0; +} +EOF + + if AC_TRY_EVAL(ac_link) && test -s conftest; then + rm -f conftest* + else + rm -f conftest* + AC_MSG_ERROR([Cannot link small Qtopia Application. For more details look at +the end of config.log]) + fi + + CXXFLAGS="$ac_cxxflags_safe" + LDFLAGS="$ac_ldflags_safe" + LIBS="$ac_libs_safe" + + AC_LANG_RESTORE + + QTOPIA_INCLUDES="-I$qtopia_incdir" + AC_SUBST(QTOPIA_INCLUDES) + + AC_MSG_RESULT([found version $qtopia_verstr with headers at $qtopia_incdir]) +]) + + +AC_DEFUN([KDE_INIT_DOXYGEN], +[ +AC_MSG_CHECKING([for Qt docs]) +kde_qtdir= +if test "${with_qt_dir+set}" = set; then + kde_qtdir="$with_qt_dir" +fi + +AC_FIND_FILE(qsql.html, [ $kde_qtdir/doc/html $QTDIR/doc/html /usr/share/doc/packages/qt3/html /usr/lib/qt/doc /usr/lib/qt3/doc /usr/lib/qt3/doc/html /usr/doc/qt3/html /usr/doc/qt3 /usr/share/doc/qt3-doc /usr/share/qt3/doc/html /usr/X11R6/share/doc/qt/html ], QTDOCDIR) +AC_MSG_RESULT($QTDOCDIR) + +AC_SUBST(QTDOCDIR) + +KDE_FIND_PATH(dot, DOT, [], []) +if test -n "$DOT"; then + KDE_HAVE_DOT="YES" +else + KDE_HAVE_DOT="NO" +fi +AC_SUBST(KDE_HAVE_DOT) +KDE_FIND_PATH(doxygen, DOXYGEN, [], []) +AC_SUBST(DOXYGEN) + +DOXYGEN_PROJECT_NAME="$1" +DOXYGEN_PROJECT_NUMBER="$2" +AC_SUBST(DOXYGEN_PROJECT_NAME) +AC_SUBST(DOXYGEN_PROJECT_NUMBER) + +KDE_HAS_DOXYGEN=no +if test -n "$DOXYGEN" && test -x "$DOXYGEN" && test -f $QTDOCDIR/qsql.html; then + KDE_HAS_DOXYGEN=yes +fi +AC_SUBST(KDE_HAS_DOXYGEN) + +]) + + +AC_DEFUN([AC_FIND_BZIP2], +[ +AC_MSG_CHECKING([for bzDecompress in libbz2]) +AC_CACHE_VAL(ac_cv_lib_bzip2, +[ +AC_LANG_SAVE +AC_LANG_CPLUSPLUS +kde_save_LIBS="$LIBS" +LIBS="$all_libraries $USER_LDFLAGS -lbz2 $LIBSOCKET" +kde_save_CXXFLAGS="$CXXFLAGS" +CXXFLAGS="$CXXFLAGS $all_includes $USER_INCLUDES" +AC_TRY_LINK(dnl +[ +#define BZ_NO_STDIO +#include +], + [ bz_stream s; (void) bzDecompress(&s); ], + eval "ac_cv_lib_bzip2='-lbz2'", + eval "ac_cv_lib_bzip2=no") +LIBS="$kde_save_LIBS" +CXXFLAGS="$kde_save_CXXFLAGS" +AC_LANG_RESTORE +])dnl +AC_MSG_RESULT($ac_cv_lib_bzip2) + +if test ! "$ac_cv_lib_bzip2" = no; then + BZIP2DIR=bzip2 + + LIBBZ2="$ac_cv_lib_bzip2" + AC_SUBST(LIBBZ2) + +else + + cxx_shared_flag= + ld_shared_flag= + KDE_CHECK_COMPILER_FLAG(shared, [ + ld_shared_flag="-shared" + ]) + KDE_CHECK_COMPILER_FLAG(fPIC, [ + cxx_shared_flag="-fPIC" + ]) + + AC_MSG_CHECKING([for BZ2_bzDecompress in (shared) libbz2]) + AC_CACHE_VAL(ac_cv_lib_bzip2_prefix, + [ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + kde_save_LIBS="$LIBS" + LIBS="$all_libraries $USER_LDFLAGS $ld_shared_flag -lbz2 $LIBSOCKET" + kde_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CFLAGS $cxx_shared_flag $all_includes $USER_INCLUDES" + + AC_TRY_LINK(dnl + [ + #define BZ_NO_STDIO + #include + ], + [ bz_stream s; (void) BZ2_bzDecompress(&s); ], + eval "ac_cv_lib_bzip2_prefix='-lbz2'", + eval "ac_cv_lib_bzip2_prefix=no") + LIBS="$kde_save_LIBS" + CXXFLAGS="$kde_save_CXXFLAGS" + AC_LANG_RESTORE + ])dnl + + AC_MSG_RESULT($ac_cv_lib_bzip2_prefix) + + if test ! "$ac_cv_lib_bzip2_prefix" = no; then + BZIP2DIR=bzip2 + + LIBBZ2="$ac_cv_lib_bzip2_prefix" + AC_SUBST(LIBBZ2) + + AC_DEFINE(NEED_BZ2_PREFIX, 1, [Define if the libbz2 functions need the BZ2_ prefix]) + dnl else, we just ignore this + fi + +fi +AM_CONDITIONAL(include_BZIP2, test -n "$BZIP2DIR") +]) + +dnl ------------------------------------------------------------------------ +dnl Try to find the SSL headers and libraries. +dnl $(SSL_LDFLAGS) will be -Lsslliblocation (if needed) +dnl and $(SSL_INCLUDES) will be -Isslhdrlocation (if needed) +dnl ------------------------------------------------------------------------ +dnl +AC_DEFUN([KDE_CHECK_SSL], +[ +LIBSSL="-lssl -lcrypto" +AC_REQUIRE([KDE_CHECK_LIB64]) + +ac_ssl_includes=NO ac_ssl_libraries=NO +ssl_libraries="" +ssl_includes="" +AC_ARG_WITH(ssl-dir, + AC_HELP_STRING([--with-ssl-dir=DIR],[where the root of OpenSSL is installed]), + [ ac_ssl_includes="$withval"/include + ac_ssl_libraries="$withval"/lib$kdelibsuff + ]) + +want_ssl=yes +AC_ARG_WITH(ssl, + AC_HELP_STRING([--without-ssl],[disable SSL checks]), + [want_ssl=$withval]) + +if test $want_ssl = yes; then + +AC_MSG_CHECKING(for OpenSSL) + +AC_CACHE_VAL(ac_cv_have_ssl, +[#try to guess OpenSSL locations + + ssl_incdirs="/usr/include /usr/local/include /usr/ssl/include /usr/local/ssl/include $prefix/include $kde_extra_includes" + ssl_incdirs="$ac_ssl_includes $ssl_incdirs" + AC_FIND_FILE(openssl/ssl.h, $ssl_incdirs, ssl_incdir) + ac_ssl_includes="$ssl_incdir" + + ssl_libdirs="/usr/lib$kdelibsuff /usr/local/lib$kdelibsuff /usr/ssl/lib$kdelibsuff /usr/local/ssl/lib$kdelibsuff $libdir $prefix/lib$kdelibsuff $exec_prefix/lib$kdelibsuff $kde_extra_libs" + if test ! "$ac_ssl_libraries" = "NO"; then + ssl_libdirs="$ac_ssl_libraries $ssl_libdirs" + fi + + test=NONE + ssl_libdir=NONE + for dir in $ssl_libdirs; do + try="ls -1 $dir/libssl*" + if test=`eval $try 2> /dev/null`; then ssl_libdir=$dir; break; else echo "tried $dir" >&AC_FD_CC ; fi + done + + ac_ssl_libraries="$ssl_libdir" + + ac_ldflags_safe="$LDFLAGS" + ac_libs_safe="$LIBS" + + LDFLAGS="$LDFLAGS -L$ssl_libdir $all_libraries" + LIBS="$LIBS $LIBSSL -lRSAglue -lrsaref" + + AC_TRY_LINK(,void RSAPrivateEncrypt(void);RSAPrivateEncrypt();, + ac_ssl_rsaref="yes" + , + ac_ssl_rsaref="no" + ) + + LDFLAGS="$ac_ldflags_safe" + LIBS="$ac_libs_safe" + + if test "$ac_ssl_includes" = NO || test "$ac_ssl_libraries" = NO; then + have_ssl=no + else + have_ssl=yes; + fi + + ]) + + eval "$ac_cv_have_ssl" + + AC_MSG_RESULT([libraries $ac_ssl_libraries, headers $ac_ssl_includes]) + + AC_MSG_CHECKING([whether OpenSSL uses rsaref]) + AC_MSG_RESULT($ac_ssl_rsaref) + + AC_MSG_CHECKING([for easter eggs]) + AC_MSG_RESULT([none found]) + +else + have_ssl=no +fi + +if test "$have_ssl" = yes; then + AC_MSG_CHECKING(for OpenSSL version) + dnl Check for SSL version + AC_CACHE_VAL(ac_cv_ssl_version, + [ + + cat >conftest.$ac_ext < +#include + int main() { + +#ifndef OPENSSL_VERSION_NUMBER + printf("ssl_version=\\"error\\"\n"); +#else + if (OPENSSL_VERSION_NUMBER < 0x00906000) + printf("ssl_version=\\"old\\"\n"); + else + printf("ssl_version=\\"ok\\"\n"); +#endif + return (0); + } +EOF + + ac_save_CPPFLAGS=$CPPFLAGS + if test "$ac_ssl_includes" != "/usr/include"; then + CPPFLAGS="$CPPFLAGS -I$ac_ssl_includes" + fi + + if AC_TRY_EVAL(ac_link); then + + if eval `./conftest 2>&5`; then + if test $ssl_version = error; then + AC_MSG_ERROR([$ssl_incdir/openssl/opensslv.h doesn't define OPENSSL_VERSION_NUMBER !]) + else + if test $ssl_version = old; then + AC_MSG_WARN([OpenSSL version too old. Upgrade to 0.9.6 at least, see http://www.openssl.org. SSL support disabled.]) + have_ssl=no + fi + fi + ac_cv_ssl_version="ssl_version=$ssl_version" + else + AC_MSG_ERROR([Your system couldn't run a small SSL test program. + Check config.log, and if you can't figure it out, send a mail to + David Faure , attaching your config.log]) + fi + + else + AC_MSG_ERROR([Your system couldn't link a small SSL test program. + Check config.log, and if you can't figure it out, send a mail to + David Faure , attaching your config.log]) + fi + CPPFLAGS=$ac_save_CPPFLAGS + + ]) + + eval "$ac_cv_ssl_version" + AC_MSG_RESULT($ssl_version) +fi + +if test "$have_ssl" != yes; then + LIBSSL=""; +else + AC_DEFINE(HAVE_SSL, 1, [If we are going to use OpenSSL]) + ac_cv_have_ssl="have_ssl=yes \ + ac_ssl_includes=$ac_ssl_includes ac_ssl_libraries=$ac_ssl_libraries ac_ssl_rsaref=$ac_ssl_rsaref" + + + ssl_libraries="$ac_ssl_libraries" + ssl_includes="$ac_ssl_includes" + + if test "$ac_ssl_rsaref" = yes; then + LIBSSL="-lssl -lcrypto -lRSAglue -lrsaref" + fi + + if test $ssl_version = "old"; then + AC_DEFINE(HAVE_OLD_SSL_API, 1, [Define if you have OpenSSL < 0.9.6]) + fi +fi + +SSL_INCLUDES= + +if test "$ssl_includes" = "/usr/include"; then + if test -f /usr/kerberos/include/krb5.h; then + SSL_INCLUDES="-I/usr/kerberos/include" + fi +elif test "$ssl_includes" != "/usr/local/include" && test -n "$ssl_includes"; then + SSL_INCLUDES="-I$ssl_includes" +fi + +if test "$ssl_libraries" = "/usr/lib" || test "$ssl_libraries" = "/usr/local/lib" || test -z "$ssl_libraries" || test "$ssl_libraries" = "NONE"; then + SSL_LDFLAGS="" +else + SSL_LDFLAGS="-L$ssl_libraries -R$ssl_libraries" +fi + +AC_SUBST(SSL_INCLUDES) +AC_SUBST(SSL_LDFLAGS) +AC_SUBST(LIBSSL) +]) + +AC_DEFUN([KDE_CHECK_STRLCPY], +[ + AC_REQUIRE([AC_CHECK_STRLCAT]) + AC_REQUIRE([AC_CHECK_STRLCPY]) + AC_CHECK_SIZEOF(size_t) + AC_CHECK_SIZEOF(unsigned long) + + AC_MSG_CHECKING([sizeof size_t == sizeof unsigned long]) + AC_TRY_COMPILE(,[ + #if SIZEOF_SIZE_T != SIZEOF_UNSIGNED_LONG + choke me + #endif + ],AC_MSG_RESULT([yes]),[ + AC_MSG_RESULT(no) + AC_MSG_ERROR([ + Apparently on your system our assumption sizeof size_t == sizeof unsigned long + does not apply. Please mail kde-devel@kde.org with a description of your system! + ]) + ]) +]) + +AC_DEFUN([KDE_CHECK_BINUTILS], +[ + AC_MSG_CHECKING([if ld supports unversioned version maps]) + + kde_save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -Wl,--version-script=conftest.map" + echo "{ local: extern \"C++\" { foo }; };" > conftest.map + AC_TRY_LINK([int foo;], +[ +#ifdef __INTEL_COMPILER +icc apparently does not support libtools version-info and version-script +at the same time. Dunno where the bug is, but until somebody figured out, +better disable the optional version scripts. +#endif + + foo = 42; +], kde_supports_versionmaps=yes, kde_supports_versionmaps=no) + LDFLAGS="$kde_save_LDFLAGS" + rm -f conftest.map + AM_CONDITIONAL(include_VERSION_SCRIPT, + [test "$kde_supports_versionmaps" = "yes" && test "$kde_use_debug_code" = "no"]) + + AC_MSG_RESULT($kde_supports_versionmaps) +]) + +AC_DEFUN([AM_PROG_OBJC],[ +AC_CHECK_PROGS(OBJC, gcc, gcc) +test -z "$OBJC" && AC_MSG_ERROR([no acceptable objective-c gcc found in \$PATH]) +if test "x${OBJCFLAGS-unset}" = xunset; then + OBJCFLAGS="-g -O2" +fi +AC_SUBST(OBJCFLAGS) +_AM_IF_OPTION([no-dependencies],, [_AM_DEPENDENCIES(OBJC)]) +]) + +AC_DEFUN([KDE_CHECK_PERL], +[ + KDE_FIND_PATH(perl, PERL, [$bindir $exec_prefix/bin $prefix/bin], [ + AC_MSG_ERROR([No Perl found in your $PATH. +We need perl to generate some code.]) + ]) + AC_SUBST(PERL) +]) + +AC_DEFUN([KDE_CHECK_LARGEFILE], +[ +AC_SYS_LARGEFILE +if test "$ac_cv_sys_file_offset_bits" != no; then + CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=$ac_cv_sys_file_offset_bits" +fi + +if test "x$ac_cv_sys_large_files" != "xno"; then + CPPFLAGS="$CPPFLAGS -D_LARGE_FILES=1" +fi + +]) + +dnl A small extension to PKG_CHECK_MODULES (defined in pkg.m4.in) +dnl which allows to search for libs that get installed into the KDE prefix. +dnl +dnl Syntax: KDE_PKG_CHECK_MODULES(KSTUFF, libkexif >= 0.2 glib = 1.3.4, action-if, action-not) +dnl defines KSTUFF_LIBS, KSTUFF_CFLAGS, see pkg-config man page +dnl also defines KSTUFF_PKG_ERRORS on error +AC_DEFUN([KDE_PKG_CHECK_MODULES], [ + + PKG_CONFIG_PATH="$prefix/lib${kdelibsuff}/pkgconfig:$PKG_CONFIG_PATH" + if test "$prefix" != "$kde_libs_prefix"; then + PKG_CONFIG_PATH="$kde_libs_prefix/lib${kdelibsuff}/pkgconfig:$PKG_CONFIG_PATH" + fi + export PKG_CONFIG_PATH + PKG_CHECK_MODULES($1,$2,$3,$4) +]) + + +dnl Check for PIE support in the compiler and linker +AC_DEFUN([KDE_CHECK_PIE_SUPPORT], +[ + AC_CACHE_CHECK([for PIE support], kde_cv_val_pie_support, + [ + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + safe_CXXFLAGS=$CXXFLAGS + safe_LDFLAGS=$LDFLAGS + CXXFLAGS="$CXXFLAGS -fpie" + LDFLAGS="$LDFLAGS -pie" + + AC_TRY_LINK([int foo;], [], [kde_cv_val_pie_support=yes], [kde_cv_val_pie_support=no]) + + CXXFLAGS=$safe_CXXFLAGS + LDFLAGS=$safe_LDFLAGS + AC_LANG_RESTORE + ]) + + AC_MSG_CHECKING(if enabling -pie/fpie support) + + AC_ARG_ENABLE(pie, + AC_HELP_STRING([--enable-pie],[platform supports PIE linking [default=detect]]), + [kde_has_pie_support=$enableval], + [kde_has_pie_support=detect]) + + if test "$kde_has_pie_support" = "detect"; then + kde_has_pie_support=$kde_cv_val_pie_support + fi + + AC_MSG_RESULT([$kde_has_pie_support]) + + KDE_USE_FPIE="" + KDE_USE_PIE="" + + AC_SUBST([KDE_USE_FPIE]) + AC_SUBST([KDE_USE_PIE]) + + if test "$kde_has_pie_support" = "yes"; then + KDE_USE_FPIE="-fpie" + KDE_USE_PIE="-pie" + fi +]) +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +## Copyright 1996, 1997, 1998, 1999, 2000, 2001 +## Free Software Foundation, Inc. +## Originally by Gordon Matzigkeit , 1996 +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +## +## As a special exception to the GNU General Public License, if you +## distribute this file as part of a program that contains a +## configuration script generated by Autoconf, you may include it under +## the same distribution terms that you use for the rest of that program. + +# serial 47 AC_PROG_LIBTOOL + + +# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) +# ----------------------------------------------------------- +# If this macro is not defined by Autoconf, define it here. +m4_ifdef([AC_PROVIDE_IFELSE], + [], + [m4_define([AC_PROVIDE_IFELSE], + [m4_ifdef([AC_PROVIDE_$1], + [$2], [$3])])]) + + +# AC_PROG_LIBTOOL +# --------------- +AC_DEFUN([AC_PROG_LIBTOOL], +[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl +dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX +dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX. + AC_PROVIDE_IFELSE([AC_PROG_CXX], + [AC_LIBTOOL_CXX], + [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX + ])]) +dnl And a similar setup for Fortran 77 support + AC_PROVIDE_IFELSE([AC_PROG_F77], + [AC_LIBTOOL_F77], + [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77 +])]) + +dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly. +dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run +dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both. + AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [ifdef([AC_PROG_GCJ], + [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([A][M_PROG_GCJ], + [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([LT_AC_PROG_GCJ], + [define([LT_AC_PROG_GCJ], + defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])]) +])])# AC_PROG_LIBTOOL + + +# _AC_PROG_LIBTOOL +# ---------------- +AC_DEFUN([_AC_PROG_LIBTOOL], +[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl +AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl +AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl +AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool --silent' +AC_SUBST(LIBTOOL)dnl + +# Prevent multiple expansion +define([AC_PROG_LIBTOOL], []) +])# _AC_PROG_LIBTOOL + + +# AC_LIBTOOL_SETUP +# ---------------- +AC_DEFUN([AC_LIBTOOL_SETUP], +[AC_PREREQ(2.50)dnl +AC_REQUIRE([AC_ENABLE_SHARED])dnl +AC_REQUIRE([AC_ENABLE_STATIC])dnl +AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_LD])dnl +AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl +AC_REQUIRE([AC_PROG_NM])dnl + +AC_REQUIRE([AC_PROG_LN_S])dnl +AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl +# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! +AC_REQUIRE([AC_OBJEXT])dnl +AC_REQUIRE([AC_EXEEXT])dnl +dnl + +AC_LIBTOOL_SYS_MAX_CMD_LEN +AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +AC_LIBTOOL_OBJDIR + +AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +_LT_AC_PROG_ECHO_BACKSLASH + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e s/^X//' +[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'] + +# Same as above, but do not quote variable references. +[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'] + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Constants: +rm="rm -f" + +# Global variables: +default_ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except M$VC, +# which needs '.lib'). +libext=a +ltmain="$ac_aux_dir/ltmain.sh" +ofile="$default_ofile" +with_gnu_ld="$lt_cv_prog_gnu_ld" + +AC_CHECK_TOOL(AR, ar, false) +AC_CHECK_TOOL(RANLIB, ranlib, :) +AC_CHECK_TOOL(STRIP, strip, :) + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +test -z "$AS" && AS=as +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$LD" && LD=ld +test -z "$LN_S" && LN_S="ln -s" +test -z "$MAGIC_CMD" && MAGIC_CMD=file +test -z "$NM" && NM=nm +test -z "$SED" && SED=sed +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$RANLIB" && RANLIB=: +test -z "$STRIP" && STRIP=: +test -z "$ac_objext" && ac_objext=o + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds" + ;; + *) + old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +# Only perform the check for file, if the check method requires it +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + AC_PATH_MAGIC + fi + ;; +esac + +AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +enable_win32_dll=yes, enable_win32_dll=no) + +AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +AC_ARG_WITH([pic], + [AC_HELP_STRING([--with-pic], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [pic_mode="$withval"], + [pic_mode=default]) +test -z "$pic_mode" && pic_mode=default + +# Use C for the default configuration in the libtool script +tagname= +AC_LIBTOOL_LANG_C_CONFIG +_LT_AC_TAGCONFIG +])# AC_LIBTOOL_SETUP + + +# _LT_AC_SYS_COMPILER +# ------------------- +AC_DEFUN([_LT_AC_SYS_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_AC_SYS_COMPILER + + +# _LT_AC_SYS_LIBPATH_AIX +# ---------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX], +[AC_LINK_IFELSE(AC_LANG_PROGRAM,[ +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi],[]) +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi +])# _LT_AC_SYS_LIBPATH_AIX + + +# _LT_AC_SHELL_INIT(ARG) +# ---------------------- +AC_DEFUN([_LT_AC_SHELL_INIT], +[ifdef([AC_DIVERSION_NOTICE], + [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], + [AC_DIVERT_PUSH(NOTICE)]) +$1 +AC_DIVERT_POP +])# _LT_AC_SHELL_INIT + + +# _LT_AC_PROG_ECHO_BACKSLASH +# -------------------------- +# Add some code to the start of the generated configure script which +# will find an echo command which doesn't interpret backslashes. +AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], +[_LT_AC_SHELL_INIT([ +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` + ;; +esac + +echo=${ECHO-echo} +if test "X[$]1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X[$]1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} +fi + +if test "X[$]1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null && + echo_test_string="`eval $cmd`" && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null + then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : +else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} + else + # Try using printf. + echo='printf %s\n' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL [$]0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$CONFIG_SHELL [$]0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "[$]0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +ECHO=$echo +if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then + ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" +fi + +AC_SUBST(ECHO) +])])# _LT_AC_PROG_ECHO_BACKSLASH + + +# _LT_AC_LOCK +# ----------- +AC_DEFUN([_LT_AC_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case "`/usr/bin/file conftest.o`" in + *32-bit*) + LINUX_64_MODE="32" + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + LINUX_64_MODE="64" + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +[*-*-cygwin* | *-*-mingw* | *-*-pw32*) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; + ]) +esac + +need_locks="$enable_libtool_lock" + +])# _LT_AC_LOCK + + +# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], +[AC_REQUIRE([LT_AC_PROG_SED]) +AC_CACHE_CHECK([$1], [$2], + [$2=no + ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test ! -s conftest.err; then + $2=yes + fi + fi + $rm conftest* +]) + +if test x"[$]$2" = xyes; then + ifelse([$5], , :, [$5]) +else + ifelse([$6], , :, [$6]) +fi +])# AC_LIBTOOL_COMPILER_OPTION + + +# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ------------------------------------------------------------ +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], +[AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + else + $2=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + ifelse([$4], , :, [$4]) +else + ifelse([$5], , :, [$5]) +fi +])# AC_LIBTOOL_LINKER_OPTION + + +# AC_LIBTOOL_SYS_MAX_CMD_LEN +# -------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], +[# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + testring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + *) + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while (test "X"`$CONFIG_SHELL [$]0 --fallback-echo "X$testring" 2>/dev/null` \ + = "XX$testring") >/dev/null 2>&1 && + new_result=`expr "X$testring" : ".*" 2>&1` && + lt_cv_sys_max_cmd_len=$new_result && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + testring=$testring$testring + done + testring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +])# AC_LIBTOOL_SYS_MAX_CMD_LEN + + +# _LT_AC_CHECK_DLFCN +# -------------------- +AC_DEFUN([_LT_AC_CHECK_DLFCN], +[AC_CHECK_HEADERS(dlfcn.h)dnl +])# _LT_AC_CHECK_DLFCN + + +# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ------------------------------------------------------------------ +AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + + exit (status); +}] +EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_unknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_AC_TRY_DLOPEN_SELF + + +# AC_LIBTOOL_DLOPEN_SELF +# ------------------- +AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + LDFLAGS="$LDFLAGS $link_static_flag" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +])# AC_LIBTOOL_DLOPEN_SELF + + +# AC_LIBTOOL_PROG_CC_C_O([TAGNAME]) +# --------------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler +AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + # According to Tom Tromey, Ian Lance Taylor reported there are C compilers + # that will create temporary files in the current directory regardless of + # the output directory. Thus, making CWD read-only will cause this test + # to fail, enabling locking or at least warning the user not to do parallel + # builds. + chmod -w . + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test ! -s out/conftest.err; then + _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . + $rm conftest* out/* + rmdir out + cd .. + rmdir conftest + $rm conftest* +]) +])# AC_LIBTOOL_PROG_CC_C_O + + +# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME]) +# ----------------------------------------- +# Check to see if we can do hard links to lock some files if needed +AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], +[AC_REQUIRE([_LT_AC_LOCK])dnl + +hard_links="nottested" +if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS + + +# AC_LIBTOOL_OBJDIR +# ----------------- +AC_DEFUN([AC_LIBTOOL_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +])# AC_LIBTOOL_OBJDIR + + +# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME]) +# ---------------------------------------------- +# Check hardcoding attributes. +AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_AC_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \ + test -n "$_LT_AC_TAGVAR(runpath_var $1)" || \ + test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)"="Xyes" ; then + + # We can hardcode non-existant directories. + if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_AC_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_AC_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_AC_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH + + +# AC_LIBTOOL_SYS_LIB_STRIP +# ------------------------ +AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP], +[striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) +fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +])# AC_LIBTOOL_SYS_LIB_STRIP + + +# AC_LIBTOOL_SYS_DYNAMIC_LINKER +# ----------------------------- +# PORTME Fill in your ld.so characteristics +AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER], +[AC_MSG_CHECKING([dynamic linker characteristics]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi4*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext='$(test .$module = .yes && echo .so || echo .dylib)' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +kfreebsd*-gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd*) + objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + *) # from 3.2 on + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case "$host_cpu" in + ia64*) + shrext='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + libsuff= + if test "x$LINUX_64_MODE" = x64; then + # Some platforms are per default 64-bit, so there's no /lib64 + if test -d /lib64; then + libsuff=64 + fi + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff}" + sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}" + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +sco3.2v5*) + version_type=osf + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no +])# AC_LIBTOOL_SYS_DYNAMIC_LINKER + + +# _LT_AC_TAGCONFIG +# ---------------- +AC_DEFUN([_LT_AC_TAGCONFIG], +[AC_ARG_WITH([tags], + [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@], + [include additional configurations @<:@automatic@:>@])], + [tagnames="$withval"]) + +if test -f "$ltmain" && test -n "$tagnames"; then + if test ! -f "${ofile}"; then + AC_MSG_WARN([output file `$ofile' does not exist]) + fi + + if test -z "$LTCC"; then + eval "`$SHELL ${ofile} --config | grep '^LTCC='`" + if test -z "$LTCC"; then + AC_MSG_WARN([output file `$ofile' does not look like a libtool script]) + else + AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) + fi + fi + + # Extract list of available tagged configurations in $ofile. + # Note that this assumes the entire list is on one line. + available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` + + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for tagname in $tagnames; do + IFS="$lt_save_ifs" + # Check whether tagname contains only valid characters + case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in + "") ;; + *) AC_MSG_ERROR([invalid tag name: $tagname]) + ;; + esac + + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null + then + AC_MSG_ERROR([tag name \"$tagname\" already exists]) + fi + + # Update the list of available tags. + if test -n "$tagname"; then + echo appending configuration tag \"$tagname\" to $ofile + + case $tagname in + CXX) + if test -n "$CXX" && test "X$CXX" != "Xno"; then + AC_LIBTOOL_LANG_CXX_CONFIG + else + tagname="" + fi + ;; + + F77) + if test -n "$F77" && test "X$F77" != "Xno"; then + AC_LIBTOOL_LANG_F77_CONFIG + else + tagname="" + fi + ;; + + GCJ) + if test -n "$GCJ" && test "X$GCJ" != "Xno"; then + AC_LIBTOOL_LANG_GCJ_CONFIG + else + tagname="" + fi + ;; + + RC) + AC_LIBTOOL_LANG_RC_CONFIG + ;; + + *) + AC_MSG_ERROR([Unsupported tag name: $tagname]) + ;; + esac + + # Append the new tag name to the list of available tags. + if test -n "$tagname" ; then + available_tags="$available_tags $tagname" + fi + fi + done + IFS="$lt_save_ifs" + + # Now substitute the updated list of available tags. + if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then + mv "${ofile}T" "$ofile" + chmod +x "$ofile" + else + rm -f "${ofile}T" + AC_MSG_ERROR([unable to update list of available tagged configurations.]) + fi +fi +])# _LT_AC_TAGCONFIG + + +# AC_LIBTOOL_DLOPEN +# ----------------- +# enable checks for dlopen support +AC_DEFUN([AC_LIBTOOL_DLOPEN], + [AC_BEFORE([$0],[AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_DLOPEN + + +# AC_LIBTOOL_WIN32_DLL +# -------------------- +# declare package support for building win32 dll's +AC_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_BEFORE([$0], [AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_WIN32_DLL + + +# AC_ENABLE_SHARED([DEFAULT]) +# --------------------------- +# implement the --enable-shared flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_SHARED], +[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([shared], + [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]AC_ENABLE_SHARED_DEFAULT) +])# AC_ENABLE_SHARED + + +# AC_DISABLE_SHARED +# ----------------- +#- set the default shared flag to --disable-shared +AC_DEFUN([AC_DISABLE_SHARED], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_SHARED(no) +])# AC_DISABLE_SHARED + + +# AC_ENABLE_STATIC([DEFAULT]) +# --------------------------- +# implement the --enable-static flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_STATIC], +[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([static], + [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]AC_ENABLE_STATIC_DEFAULT) +])# AC_ENABLE_STATIC + + +# AC_DISABLE_STATIC +# ----------------- +# set the default static flag to --disable-static +AC_DEFUN([AC_DISABLE_STATIC], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_STATIC(no) +])# AC_DISABLE_STATIC + + +# AC_ENABLE_FAST_INSTALL([DEFAULT]) +# --------------------------------- +# implement the --enable-fast-install flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_FAST_INSTALL], +[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([fast-install], + [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT) +])# AC_ENABLE_FAST_INSTALL + + +# AC_DISABLE_FAST_INSTALL +# ----------------------- +# set the default to --disable-fast-install +AC_DEFUN([AC_DISABLE_FAST_INSTALL], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_FAST_INSTALL(no) +])# AC_DISABLE_FAST_INSTALL + + +# AC_LIBTOOL_PICMODE([MODE]) +# -------------------------- +# implement the --with-pic flag +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +AC_DEFUN([AC_LIBTOOL_PICMODE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +pic_mode=ifelse($#,1,$1,default) +])# AC_LIBTOOL_PICMODE + + +# AC_PROG_EGREP +# ------------- +# This is predefined starting with Autoconf 2.54, so this conditional +# definition can be removed once we require Autoconf 2.54 or later. +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP], +[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep], + [if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi]) + EGREP=$ac_cv_prog_egrep + AC_SUBST([EGREP]) +])]) + + +# AC_PATH_TOOL_PREFIX +# ------------------- +# find a file program which can recognise shared library +AC_DEFUN([AC_PATH_TOOL_PREFIX], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="ifelse([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +])# AC_PATH_TOOL_PREFIX + + +# AC_PATH_MAGIC +# ------------- +# find a file program which can recognise a shared library +AC_DEFUN([AC_PATH_MAGIC], +[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# AC_PATH_MAGIC + + +# AC_PROG_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([AC_PROG_LD], +[AC_ARG_WITH([gnu-ld], + [AC_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no]) +AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case "$host_cpu" in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + irix5* | nonstopux*) + # this will be overridden with pass_all, but let us keep it just in case + lt_cv_deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1" + ;; + *) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + # this will be overridden with pass_all, but let us keep it just in case + lt_cv_deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[[1234]] dynamic lib MIPS - version 1" + ;; + esac + lt_cv_file_magic_test_file=`echo /lib${libsuff}/libc.so*` + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux*) + case $host_cpu in + alpha* | hppa* | i*86 | ia64* | m68* | mips* | powerpc* | sparc* | s390* | sh* | x86_64* ) + lt_cv_deplibs_check_method=pass_all ;; + # the debian people say, arm and glibc 2.3.1 works for them with pass_all + arm* ) + lt_cv_deplibs_check_method=pass_all ;; + *) + # glibc up to 2.1.1 does not perform some relocations on ARM + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; + esac + lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so` + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +nto-qnx*) + lt_cv_deplibs_check_method=unknown + ;; + +openbsd*) + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB shared object' + else + lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library' + fi + ;; + +osf3* | osf4* | osf5*) + # this will be overridden with pass_all, but let us keep it just in case + lt_cv_deplibs_check_method='file_magic COFF format alpha shared library' + lt_cv_file_magic_test_file=/shlib/libc.so + lt_cv_deplibs_check_method=pass_all + ;; + +sco3.2v5*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + lt_cv_file_magic_test_file=/lib/libc.so + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown +])# AC_DEPLIBS_CHECK_METHOD + + +# AC_PROG_NM +# ---------- +# find the pathname to a BSD-compatible name lister +AC_DEFUN([AC_PROG_NM], +[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/${ac_tool_prefix}nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + esac + fi + done + IFS="$lt_save_ifs" + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi]) +NM="$lt_cv_path_NM" +])# AC_PROG_NM + + +# AC_CHECK_LIBM +# ------------- +# check for math library +AC_DEFUN([AC_CHECK_LIBM], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +])# AC_CHECK_LIBM + + +# AC_LIBLTDL_CONVENIENCE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl convenience library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-convenience to the configure arguments. Note that LIBLTDL +# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If +# DIRECTORY is not provided, it is assumed to be `libltdl'. LIBLTDL will +# be prefixed with '${top_builddir}/' and LTDLINCL will be prefixed with +# '${top_srcdir}/' (note the single quotes!). If your package is not +# flat and you're not using automake, define top_builddir and +# top_srcdir appropriately in the Makefiles. +AC_DEFUN([AC_LIBLTDL_CONVENIENCE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + case $enable_ltdl_convenience in + no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; + "") enable_ltdl_convenience=yes + ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; + esac + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_CONVENIENCE + + +# AC_LIBLTDL_INSTALLABLE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl installable library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-install to the configure arguments. Note that LIBLTDL +# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If +# DIRECTORY is not provided and an installed libltdl is not found, it is +# assumed to be `libltdl'. LIBLTDL will be prefixed with '${top_builddir}/' +# and LTDLINCL will be prefixed with '${top_srcdir}/' (note the single +# quotes!). If your package is not flat and you're not using automake, +# define top_builddir and top_srcdir appropriately in the Makefiles. +# In the future, this macro may have to be called after AC_PROG_LIBTOOL. +AC_DEFUN([AC_LIBLTDL_INSTALLABLE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + AC_CHECK_LIB(ltdl, lt_dlinit, + [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], + [if test x"$enable_ltdl_install" = xno; then + AC_MSG_WARN([libltdl not installed, but installation disabled]) + else + enable_ltdl_install=yes + fi + ]) + if test x"$enable_ltdl_install" = x"yes"; then + ac_configure_args="$ac_configure_args --enable-ltdl-install" + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + else + ac_configure_args="$ac_configure_args --enable-ltdl-install=no" + LIBLTDL="-lltdl" + LTDLINCL= + fi + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_INSTALLABLE + + +# AC_LIBTOOL_CXX +# -------------- +# enable support for C++ libraries +AC_DEFUN([AC_LIBTOOL_CXX], +[AC_REQUIRE([_LT_AC_LANG_CXX]) +])# AC_LIBTOOL_CXX + + +# _LT_AC_LANG_CXX +# --------------- +AC_DEFUN([_LT_AC_LANG_CXX], +[AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([AC_PROG_CXXCPP]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX]) +])# _LT_AC_LANG_CXX + + +# AC_LIBTOOL_F77 +# -------------- +# enable support for Fortran 77 libraries +AC_DEFUN([AC_LIBTOOL_F77], +[AC_REQUIRE([_LT_AC_LANG_F77]) +])# AC_LIBTOOL_F77 + + +# _LT_AC_LANG_F77 +# --------------- +AC_DEFUN([_LT_AC_LANG_F77], +[AC_REQUIRE([AC_PROG_F77]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77]) +])# _LT_AC_LANG_F77 + + +# AC_LIBTOOL_GCJ +# -------------- +# enable support for GCJ libraries +AC_DEFUN([AC_LIBTOOL_GCJ], +[AC_REQUIRE([_LT_AC_LANG_GCJ]) +])# AC_LIBTOOL_GCJ + + +# _LT_AC_LANG_GCJ +# --------------- +AC_DEFUN([_LT_AC_LANG_GCJ], +[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[], + [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])], + [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])], + [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ]) +])# _LT_AC_LANG_GCJ + + +# AC_LIBTOOL_RC +# -------------- +# enable support for Windows resource files +AC_DEFUN([AC_LIBTOOL_RC], +[AC_REQUIRE([LT_AC_PROG_RC]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC]) +])# AC_LIBTOOL_RC + + +# AC_LIBTOOL_LANG_C_CONFIG +# ------------------------ +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG]) +AC_DEFUN([_LT_AC_LANG_C_CONFIG], +[lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}\n' + +_LT_AC_SYS_COMPILER + +# +# Check for any special shared library compilation flags. +# +_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)= +if test "$GCC" = no; then + case $host_os in + sco3.2v5*) + _LT_AC_TAGVAR(lt_prog_cc_shlib, $1)='-belf' + ;; + esac +fi +if test -n "$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)"; then + AC_MSG_WARN([`$CC' requires `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to build shared libraries]) + if echo "$old_CC $old_CFLAGS " | grep "[[ ]]$]_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)[[[ ]]" >/dev/null; then : + else + AC_MSG_WARN([add `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to the CC or CFLAGS env variable and reconfigure]) + _LT_AC_TAGVAR(lt_cv_prog_cc_can_build_shared, $1)=no + fi +fi + + +# +# Check to make sure the static flag actually works. +# +AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $_LT_AC_TAGVAR(lt_prog_compiler_static, $1) works], + _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), + $_LT_AC_TAGVAR(lt_prog_compiler_static, $1), + [], + [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_DLOPEN_SELF($1) + +# Report which librarie types wil actually be built +AC_MSG_CHECKING([if libtool supports shared libraries]) +AC_MSG_RESULT([$can_build_shared]) + +AC_MSG_CHECKING([whether to build shared libraries]) +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case "$host_os" in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + darwin* | rhapsody*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + case "$host_os" in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-Wl,-undefined -Wl,suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-Wl,-flat_namespace -Wl,-undefined -Wl,suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-Wl,-flat_namespace -Wl,-undefined -Wl,suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-Wl,-undefined -Wl,dynamic_lookup' + ;; + esac + fi + ;; + esac + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $compiler_flags $libobjs $deplibs -install_name $rpath/$soname $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $compiler_flags $libobjs $deplibs' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $compiler_flags $libobjs $deplibs -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $compiler_flags $libobjs $deplibs~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; +esac +AC_MSG_RESULT([$enable_shared]) + +AC_MSG_CHECKING([whether to build static libraries]) +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +AC_MSG_RESULT([$enable_static]) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_C_CONFIG + + +# AC_LIBTOOL_LANG_CXX_CONFIG +# -------------------------- +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)]) +AC_DEFUN([_LT_AC_LANG_CXX_CONFIG], +[AC_LANG_PUSH(C++) +AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([AC_PROG_CXXCPP]) + +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_AC_TAGVAR(allow_undefined_flag, $1)= +_LT_AC_TAGVAR(always_export_symbols, $1)=no +_LT_AC_TAGVAR(archive_expsym_cmds, $1)= +_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_direct, $1)=no +_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_AC_TAGVAR(hardcode_libdir_separator, $1)= +_LT_AC_TAGVAR(hardcode_minus_L, $1)=no +_LT_AC_TAGVAR(hardcode_automatic, $1)=no +_LT_AC_TAGVAR(module_cmds, $1)= +_LT_AC_TAGVAR(module_expsym_cmds, $1)= +_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown +_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_AC_TAGVAR(no_undefined_flag, $1)= +_LT_AC_TAGVAR(whole_archive_flag_spec, $1)= +_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Dependencies to place before and after the object being linked: +_LT_AC_TAGVAR(predep_objects, $1)= +_LT_AC_TAGVAR(postdep_objects, $1)= +_LT_AC_TAGVAR(predeps, $1)= +_LT_AC_TAGVAR(postdeps, $1)= +_LT_AC_TAGVAR(compiler_lib_search_path, $1)= + +# Source file extension for C++ test sources. +ac_ext=cc + +# Object file extension for compiled C++ test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_LD=$LD +lt_save_GCC=$GCC +GCC=$GXX +lt_save_with_gnu_ld=$with_gnu_ld +lt_save_path_LD=$lt_cv_path_LD +if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx +else + unset lt_cv_prog_gnu_ld +fi +if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX +else + unset lt_cv_path_LD +fi +test -z "${LDCXX+set}" || LD=$LDCXX +CC=${CXX-"c++"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` + +# We don't want -fno-exception wen compiling C++ code, so set the +# no_builtin_flag separately +if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' +else + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= +fi + +if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + AC_PROG_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ + grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + +else + GXX=no + with_gnu_ld=no + wlarc= +fi + +# PORTME: fill in a description of your system's C++ link characteristics +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +_LT_AC_TAGVAR(ld_shlibs, $1)=yes +case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # KDE requires run time linking. Make it the default. + aix_use_runtimelinking=yes + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='-qmkshrobj ${wl}-G' + else + shared_flag='-qmkshrobj' + fi + fi + fi + + # Let the compiler handle the export list. + _LT_AC_TAGVAR(always_export_symbols, $1)=no + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_AC_TAGVAR(archive_cmds, $1)="\$CC"' -o $output_objdir/$soname $compiler_flags $libobjs $deplibs `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '" $shared_flag" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $compiler_flags $libobjs $deplibs `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $compiler_flags $libobjs $deplibs ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # -bexpall does not export symbols beginning with underscore (_) + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' ' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds it's shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $compiler_flags $libobjs $deplibs ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=no + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + darwin* | rhapsody*) + if test "$GXX" = yes; then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + case "$host_os" in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-Wl,-undefined -Wl,suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-Wl,-flat_namespace -Wl,-undefined -Wl,suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-Wl,-flat_namespace -Wl,-undefined -Wl,suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-Wl,-undefined -Wl,dynamic_lookup' + ;; + esac + fi + ;; + esac + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $compiler_flags $libobjs $deplibs -install_name $rpath/$soname $verstring' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $compiler_flags $deplibs -install_name $rpath/$soname $verstring' + fi + _LT_AC_TAGVAR(module_cmds, $1)='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $compiler_flags $libobjs $deplibs' + + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $compiler_flags $libobjs $deplibs -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $compiler_flags $deplibs -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $compiler_flags $libobjs $deplibs~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + dgux*) + case $cc_basename in + ec++) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + freebsd[12]*) + # C++ shared libraries reported to be fairly broken before switch to ELF + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + freebsd-elf*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + freebsd* | kfreebsd*-gnu) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + ;; + gnu*) + ;; + hpux9*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | egrep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + case "$host_cpu" in + hppa*64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + ;; + *) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case "$host_cpu" in + hppa*64*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + ia64*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC) + case "$host_cpu" in + hppa*64*|ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case "$host_cpu" in + ia64*|hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + irix5* | irix6*) + case $cc_basename in + CC) + # SGI C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' + fi + fi + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + linux*) + case $cc_basename in + KCC) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects --soname $soname -o \$templib; mv \$templib $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc) + # Intel C++ + with_gnu_ld=yes + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + cxx) + # Compaq C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + esac + ;; + lynxos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + m88k*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + mvs*) + case $cc_basename in + cxx) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + osf3*) + case $cc_basename in + KCC) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + + ;; + RCC) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + osf4* | osf5*) + case $cc_basename in + KCC) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' + ;; + RCC) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry $objdir/so_locations -o $lib~ + $rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + psos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + sco*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + case $cc_basename in + CC) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + lcc) + # Lucid + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + solaris*) + case $cc_basename in + CC) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -nolib -h$soname -o $lib $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -nolib ${wl}-M ${wl}$lib.exp -h$soname -o $lib $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects~$rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The C++ compiler is used as linker so we must use $wl + # flag to pass the commands to the underlying system + # linker. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep "\-[[LR]]"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | grep -v '^2\.7' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $compiler_flags $predep_objects $libobjs $deplibs $postdep_objects~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + fi + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + fi + ;; + esac + ;; + sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + tandem*) + case $cc_basename in + NCC) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + vxworks*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; +esac +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_AC_TAGVAR(GCC, $1)="$GXX" +_LT_AC_TAGVAR(LD, $1)="$LD" + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_POSTDEP_PREDEP($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_DLOPEN_SELF($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC=$lt_save_CC +LDCXX=$LD +LD=$lt_save_LD +GCC=$lt_save_GCC +with_gnu_ldcxx=$with_gnu_ld +with_gnu_ld=$lt_save_with_gnu_ld +lt_cv_path_LDCXX=$lt_cv_path_LD +lt_cv_path_LD=$lt_save_path_LD +lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld +lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +])# AC_LIBTOOL_LANG_CXX_CONFIG + +# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) +# ------------------------ +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[ +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +ifelse([$1],[],[cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext <> "$cfgfile" +ifelse([$1], [], +[#! $SHELL + +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# +# This file is part of GNU Libtool: +# Originally by Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="$SED -e s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi + +# The names of the tagged configurations supported by this script. +available_tags= + +# ### BEGIN LIBTOOL CONFIG], +[# ### BEGIN LIBTOOL TAG CONFIG: $tagname]) + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1) + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# A language-specific compiler. +CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) + +# Is the compiler the GNU C compiler? +with_gcc=$_LT_AC_TAGVAR(GCC, $1) + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_[]_LT_AC_TAGVAR(LD, $1) + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext='$shrext' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) + +# Must we lock files when doing compilation ? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1) + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1) + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1) + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1) + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1) +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1) + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) + +# Commands used to build and install a shared archive. +archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1) +archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1) +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1) +module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1) + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1) + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1) + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1) + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1) + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1) + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1) + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1) + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1) + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1) + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1) + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)" + +# Set to yes if exported symbols are required. +always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) + +# The commands to list exported symbols. +export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1) + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1) + +# Symbols that must always be exported. +include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1) + +ifelse([$1],[], +[# ### END LIBTOOL CONFIG], +[# ### END LIBTOOL TAG CONFIG: $tagname]) + +__EOF__ + +ifelse([$1],[], [ + case $host_os in + aix3*) + cat <<\EOF >> "$cfgfile" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || \ + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +]) +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + test -f Makefile && make "$ltmain" +fi +])# AC_LIBTOOL_CONFIG + + +# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl + +_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + + AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI + + +# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +# --------------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], +[AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_NM]) +AC_REQUIRE([AC_OBJEXT]) +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Transform the above into a raw symbol and a C symbol. +symxfrm='\1 \2\3 \3' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris* | sysv5*) + symcode='[[BDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGISTW]]' ;; +esac + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext < $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if grep ' nm_test_var$' "$nlist" >/dev/null; then + if grep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[[]] = +{ +EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi +]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE + + +# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME]) +# --------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC], +[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_static, $1)= + +AC_MSG_CHECKING([for $compiler option to produce PIC]) + ifelse([$1],[CXX],[ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | os2* | pw32*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case "$host_cpu" in + hppa*64*|ia64*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix4* | aix5*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68) + # Green Hills C++ Compiler + # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | kfreebsd*-gnu) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" + case "$host_cpu" in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux*) + case $cc_basename in + KCC) + # KAI C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + icpc) + # Intel C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + cxx) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC) + # Rational C++ 2.4.1 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx) + # Digital/Compaq C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + sco*) + case $cc_basename in + CC) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + *) + ;; + esac + ;; + solaris*) + case $cc_basename in + CC) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC) + # Sun C++ 4.x + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc) + # Lucid + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC) + # NonStop-UX NCC 3.20 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + unixware*) + ;; + vxworks*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case "$host_cpu" in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case "$host_cpu" in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + newsos6) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + linux*) + case $CC in + icc* | ecc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + ccc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + sco3.2v5*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-dn' + ;; + + solaris*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sunos4*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + uts4*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then + AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], + _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1), + [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +case "$host_os" in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])" + ;; +esac +]) + + +# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) +# ------------------------------------ +# See if the linker supports building shared libraries. +AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], +[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +ifelse([$1],[CXX],[ + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix4* | aix5*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + ;; + *) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +],[ + runpath_var= + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)= + _LT_AC_TAGVAR(archive_expsym_cmds, $1)= + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)= + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + _LT_AC_TAGVAR(thread_safe_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_minus_L, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown + _LT_AC_TAGVAR(hardcode_automatic, $1)=no + _LT_AC_TAGVAR(module_cmds, $1)= + _LT_AC_TAGVAR(module_expsym_cmds, $1)= + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_AC_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $compiler_flags $libobjs $deplibs ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=no + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $compiler_flags $libobjs $deplibs -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $compiler_flags $libobjs $deplibs -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $compiler_flags $libobjs $deplibs ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $compiler_flags $libobjs $deplibs ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris* | sysv5*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $compiler_flags $libobjs $deplibs ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $compiler_flags $libobjs $deplibs ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sunos4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $compiler_flags $libobjs $deplibs ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $compiler_flags $libobjs $deplibs ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = yes; then + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$link_static_flag"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + + # KDE requires run time linking. Make it the default. + aix_use_runtimelinking=yes + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='-qmkshrobj ${wl}-G' + else + shared_flag='-qmkshrobj' + fi + fi + fi + + # Let the compiler handle the export list. + _LT_AC_TAGVAR(always_export_symbols, $1)=no + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_AC_TAGVAR(archive_cmds, $1)="\$CC"' -o $output_objdir/$soname $compiler_flags $libobjs $deplibs `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '" $shared_flag" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $compiler_flags $libobjs $deplibs `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $compiler_flags $libobjs $deplibs ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # -bexpall does not export symbols beginning with underscore (_) + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' ' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds it's shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $compiler_flags $libobjs $deplibs ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + # see comment about different semantics on the GNU ld section + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + bsdi4*) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=no + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $compiler_flags $libobjs `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path='`cygpath -w "$srcfile"`' + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + darwin* | rhapsody*) + if test "$GXX" = yes ; then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + case "$host_os" in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-Wl,-undefined -Wl,suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-Wl,-flat_namespace -Wl,-undefined -Wl,suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[012]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-Wl,-flat_namespace -Wl,-undefined -Wl,suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-Wl,-undefined -Wl,dynamic_lookup' + ;; + esac + fi + ;; + esac + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $compiler_flags $libobjs $deplibs -install_name $rpath/$soname $verstring' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $compiler_flags $deplibs -install_name $rpath/$soname $verstring' + fi + _LT_AC_TAGVAR(module_cmds, $1)='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $compiler_flags $libobjs $deplibs' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $compiler_flags $libobjs $deplibs -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $compiler_flags $deplibs -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $compiler_flags $libobjs $deplibs~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + dgux*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + freebsd1*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | kfreebsd*-gnu) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $compiler_flags $libobjs $deplibs' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $compiler_flags $libobjs $deplibs~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10* | hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case "$host_cpu" in + hppa*64*|ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $compiler_flags $libobjs $deplibs' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $compiler_flags $libobjs $deplibs' + ;; + esac + else + case "$host_cpu" in + hppa*64*|ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + case "$host_cpu" in + hppa*64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + ;; + *) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $compiler_flags $libobjs $deplibs ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + openbsd*) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $compiler_flags $libobjs $deplibs' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $compiler_flags $libobjs $deplibs' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $compiler_flags $libobjs $deplibs$output_objdir/$libname.def' + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $compiler_flags $libobjs $deplibs ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $compiler_flags $libobjs $deplibs ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + sco3.2v5*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ;; + + solaris*) + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $compiler_flags $libobjs $deplibs' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $compiler_flags $libobjs $deplibs~$rm $lib.exp' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $compiler_flags $libobjs $deplibs' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4.2uw2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + hardcode_runpath_var=yes + runpath_var=LD_RUN_PATH + ;; + + sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z ${wl}text' + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $compiler_flags $libobjs $deplibs' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h ${wl}$soname -o $lib $compiler_flags $libobjs $deplibs' + fi + runpath_var='LD_RUN_PATH' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv5*) + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' + # $CC -shared without GNU ld will not create a library from C++ + # object files and a static libstdc++, better avoid it by now + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + ;; + + uts4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +# +# Do we need to explicitly link libc? +# +case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_AC_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_MSG_CHECKING([whether -lc should be explicitly linked in]) + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1) + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) + then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + else + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)]) + ;; + esac + fi + ;; +esac +])# AC_LIBTOOL_PROG_LD_SHLIBS + + +# _LT_AC_FILE_LTDLL_C +# ------------------- +# Be careful that the start marker always follows a newline. +AC_DEFUN([_LT_AC_FILE_LTDLL_C], [ +# /* ltdll.c starts here */ +# #define WIN32_LEAN_AND_MEAN +# #include +# #undef WIN32_LEAN_AND_MEAN +# #include +# +# #ifndef __CYGWIN__ +# # ifdef __CYGWIN32__ +# # define __CYGWIN__ __CYGWIN32__ +# # endif +# #endif +# +# #ifdef __cplusplus +# extern "C" { +# #endif +# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); +# #ifdef __cplusplus +# } +# #endif +# +# #ifdef __CYGWIN__ +# #include +# DECLARE_CYGWIN_DLL( DllMain ); +# #endif +# HINSTANCE __hDllInstance_base; +# +# BOOL APIENTRY +# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) +# { +# __hDllInstance_base = hInst; +# return TRUE; +# } +# /* ltdll.c ends here */ +])# _LT_AC_FILE_LTDLL_C + + +# _LT_AC_TAGVAR(VARNAME, [TAGNAME]) +# --------------------------------- +AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])]) + + +# old names +AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) +AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) +AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) +AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) +AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) + +# This is just to silence aclocal about the macro not being used +ifelse([AC_DISABLE_FAST_INSTALL]) + +AC_DEFUN([LT_AC_PROG_GCJ], +[AC_CHECK_TOOL(GCJ, gcj, no) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS) +]) + +AC_DEFUN([LT_AC_PROG_RC], +[AC_CHECK_TOOL(RC, windres, no) +]) + +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +# LT_AC_PROG_SED +# -------------- +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +AC_DEFUN([LT_AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && break + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_MSG_RESULT([$SED]) +]) diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..a0c3e02 --- /dev/null +++ b/config.h.in @@ -0,0 +1,259 @@ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Define to 1 if you have the header file. */ +#undef HAVE_CARBON_CARBON_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_CDDA_INTERFACE_H + +/* Define if you have the CoreAudio API */ +#undef HAVE_COREAUDIO + +/* Define to 1 if you have the header file. */ +#undef HAVE_CRT_EXTERNS_H + +/* Defines if your system has the crypt function */ +#undef HAVE_CRYPT + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define if you have libjpeg */ +#undef HAVE_LIBJPEG + +/* Define if you have libpng */ +#undef HAVE_LIBPNG + +/* Define if you have a working libpthread (will enable threaded code) */ +#undef HAVE_LIBPTHREAD + +/* Define if you have libz */ +#undef HAVE_LIBZ + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* have mp4v2 */ +#undef HAVE_MP4V2 + +/* Define to 1 if you have the header file. */ +#undef HAVE_MP4_H + +/* Define if your system needs _NSGetEnviron to set up the environment */ +#undef HAVE_NSGETENVIRON + +/* Define if you have res_init */ +#undef HAVE_RES_INIT + +/* Define if you have the res_init prototype */ +#undef HAVE_RES_INIT_PROTO + +/* Define if you have a STL implementation by SGI */ +#undef HAVE_SGI_STL + +/* Define to 1 if you have the `snprintf' function. */ +#undef HAVE_SNPRINTF + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define if you have strlcat */ +#undef HAVE_STRLCAT + +/* Define if you have the strlcat prototype */ +#undef HAVE_STRLCAT_PROTO + +/* Define if you have strlcpy */ +#undef HAVE_STRLCPY + +/* Define if you have the strlcpy prototype */ +#undef HAVE_STRLCPY_PROTO + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYSTEMS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_BITYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* have TagLib */ +#undef HAVE_TAGLIB + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `vsnprintf' function. */ +#undef HAVE_VSNPRINTF + +/* Suffix for lib directories */ +#undef KDELIBSUFF + +/* Define a safe value for MAXPATHLEN */ +#undef KDEMAXPATHLEN + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* The size of `char *', as computed by sizeof. */ +#undef SIZEOF_CHAR_P + +/* The size of `int', as computed by sizeof. */ +#undef SIZEOF_INT + +/* The size of `long', as computed by sizeof. */ +#undef SIZEOF_LONG + +/* The size of `short', as computed by sizeof. */ +#undef SIZEOF_SHORT + +/* The size of `size_t', as computed by sizeof. */ +#undef SIZEOF_SIZE_T + +/* The size of `unsigned long', as computed by sizeof. */ +#undef SIZEOF_UNSIGNED_LONG + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION + +/* Defined if compiling without arts */ +#undef WITHOUT_ARTS + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +#undef WORDS_BIGENDIAN + +/* + * jpeg.h needs HAVE_BOOLEAN, when the system uses boolean in system + * headers and I'm too lazy to write a configure test as long as only + * unixware is related + */ +#ifdef _UNIXWARE +#define HAVE_BOOLEAN +#endif + + + +/* + * AIX defines FD_SET in terms of bzero, but fails to include + * that defines bzero. + */ + +#if defined(_AIX) +#include +#endif + + + +#if defined(HAVE_NSGETENVIRON) && defined(HAVE_CRT_EXTERNS_H) +# include +# include +# define environ (*_NSGetEnviron()) +#endif + + + +#if !defined(HAVE_RES_INIT_PROTO) +#ifdef __cplusplus +extern "C" { +#endif +int res_init(void); +#ifdef __cplusplus +} +#endif +#endif + + + +#if !defined(HAVE_STRLCAT_PROTO) +#ifdef __cplusplus +extern "C" { +#endif +unsigned long strlcat(char*, const char*, unsigned long); +#ifdef __cplusplus +} +#endif +#endif + + + +#if !defined(HAVE_STRLCPY_PROTO) +#ifdef __cplusplus +extern "C" { +#endif +unsigned long strlcpy(char*, const char*, unsigned long); +#ifdef __cplusplus +} +#endif +#endif + + + +/* + * On HP-UX, the declaration of vsnprintf() is needed every time ! + */ + +#if !defined(HAVE_VSNPRINTF) || defined(hpux) +#if __STDC__ +#include +#include +#else +#include +#endif +#ifdef __cplusplus +extern "C" +#endif +int vsnprintf(char *str, size_t n, char const *fmt, va_list ap); +#ifdef __cplusplus +extern "C" +#endif +int snprintf(char *str, size_t n, char const *fmt, ...); +#endif + + + +#if defined(__SVR4) && !defined(__svr4__) +#define __svr4__ 1 +#endif + + +/* type to use in place of socklen_t if not defined */ +#undef kde_socklen_t + +/* type to use in place of socklen_t if not defined (deprecated, use + kde_socklen_t) */ +#undef ksize_t diff --git a/configure.files b/configure.files new file mode 100644 index 0000000..030bce8 --- /dev/null +++ b/configure.files @@ -0,0 +1,2 @@ +./admin/configure.in.min +configure.in.in diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..0472847 --- /dev/null +++ b/configure.in @@ -0,0 +1,282 @@ +dnl ======================================================= +dnl FILE: ./admin/configure.in.min +dnl ======================================================= + +dnl This file is part of the KDE libraries/packages +dnl Copyright (C) 2001 Stephan Kulow (coolo@kde.org) + +dnl This file is free software; you can redistribute it and/or +dnl modify it under the terms of the GNU Library General Public +dnl License as published by the Free Software Foundation; either +dnl version 2 of the License, or (at your option) any later version. + +dnl This library is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl Library General Public License for more details. + +dnl You should have received a copy of the GNU Library General Public License +dnl along with this library; see the file COPYING.LIB. If not, write to +dnl the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +dnl Boston, MA 02110-1301, USA. + +# Original Author was Kalle@kde.org +# I lifted it in some mater. (Stephan Kulow) +# I used much code from Janos Farkas + +dnl Process this file with autoconf to produce a configure script. + +AC_INIT(acinclude.m4) dnl a source file from your sub dir + +dnl This is so we can use kde-common +AC_CONFIG_AUX_DIR(admin) + +dnl This ksh/zsh feature conflicts with `cd blah ; pwd` +unset CDPATH + +dnl Checking host/target/build systems, for make, install etc. +AC_CANONICAL_SYSTEM +dnl Perform program name transformation +AC_ARG_PROGRAM + +dnl Automake doc recommends to do this only here. (Janos) +AM_INIT_AUTOMAKE(soundkonverter, 0.3.7) dnl searches for some needed programs + +KDE_SET_PREFIX + +dnl generate the config header +AM_CONFIG_HEADER(config.h) dnl at the distribution this done + +dnl Checks for programs. +AC_CHECK_COMPILERS +AC_ENABLE_SHARED(yes) +AC_ENABLE_STATIC(no) +KDE_PROG_LIBTOOL + +dnl for NLS support. Call them in this order! +dnl WITH_NLS is for the po files +AM_KDE_WITH_NLS + +KDE_USE_QT(3.2.0) +AC_PATH_KDE +dnl ======================================================= +dnl FILE: configure.in.in +dnl ======================================================= + +#MIN_CONFIG(3.2.0) + +dnl PACKAGE set before +AC_C_BIGENDIAN +AC_CHECK_KDEMAXPATHLEN + + +############################################################################### +# BEGIN CDPARANOIA CHECK +############################################################################### +# +#AC_CHECK_HEADER([cdda_interface.h], [with_cdparanoia=yes], [with_cdparanoia=no]) +# +#if test "$with_cdparanoia" != "yes" ; then +# soundkonverter_error_nocdparanoia=yes +# DO_NOT_COMPILE="$DO_NOT_COMPILE soundkonverter" +# no_soundkonverter=yes +# +# echo "" +# echo "-----------------------------------------" +# echo "ERROR: Could not find cdparanoia headers." +# echo "-----------------------------------------" +# echo "" +# +# AC_MSG_ERROR([could not find cdparanoia headers]) +#fi +# +############################################################################### +# END CDPARANOIA CHECK +############################################################################### + + +dnl ------------------------------------- +dnl cdparanoia check +dnl ------------------------------------- + +AC_CHECK_HEADERS(cdda_interface.h, have_paranoia="yes", have_paranoia="no" ) + +dnl ---------------------------------- +dnl Can soundkonverter be compiled? +dnl ---------------------------------- + +if test x$have_paranoia != xyes; then + DO_NOT_COMPILE="$DO_NOT_COMPILE soundkonverter" + no_paranoia=yes +fi + +############################################################################### +# BEGIN TAGLIB CHECK +############################################################################### + +TAGLIB_REQ_VERSION="1.4.0"; +AC_DEFUN([VERSION_TO_NUMBER], [`$1 | awk 'BEGIN { FS = "."; } { printf "%d", ([$]1* 1000 + [$]2) * 1000 + [$]3;}'`]) + +AC_PATH_PROG(TAGLIB_CONFIG, taglib-config, no) + +if test "x$TAGLIB_CONFIG" = "xno" ; then + soundkonverter_error_notaglib=yes + DO_NOT_COMPILE="$DO_NOT_COMPILE soundkonverter" + no_soundkonverter=yes +else + AC_DEFINE(HAVE_TAGLIB, 1, [have TagLib]) + taglib_includes=[`$TAGLIB_CONFIG --cflags`] + taglib_libs=[`$TAGLIB_CONFIG --libs`] + taglib_version=[`$TAGLIB_CONFIG --version`] + + if test VERSION_TO_NUMBER(echo $taglib_version) -lt VERSION_TO_NUMBER(echo $TAGLIB_REQ_VERSION); then + soundkonverter_error_taglibold=yes + DO_NOT_COMPILE="$DO_NOT_COMPILE soundkonverter" + no_soundkonverter=yes + fi +fi + +AC_SUBST(taglib_includes) +AC_SUBST(taglib_libs) + +############################################################################### +# END TAGLIB CHECK +############################################################################### + + +############################################################################### +# BEGIN MP4V2 CHECK +############################################################################### +# m4a/aac tag reading and writing needs libmp4v2 from faad2 or better mpeg4ip + +AC_ARG_WITH(mp4v2, + AC_HELP_STRING([--with-mp4v2],[build soundkonverter with M4A/AAC tag support from mp4v2/faad2]), + [have_mp4v2=$withval], + [have_mp4v2=no] +) + +AC_ARG_WITH(mp4v2-dir, + AC_HELP_STRING([--with-mp4v2-dir],[path to mp4v2 [default=/usr]]), + [mp4v2_dir="$withval"], + [mp4v2_dir=/usr] +) + +if test "$have_mp4v2" != "no"; then + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + ac_cxxflags_save=$CXXFLAGS + CXXFLAGS="$CXXFLAGS -I$mp4v2_dir/include" + ac_ldflags_save=$LDFLAGS + LDFLAGS="$LDFLAGS -L$mp4v2_dir/lib" + + # not even everyone using faad2 has + if ! test -f config.h; then + echo "#include \"confdefs.h\"" > config.h + fi + ac_cppflags_save=$CPPFLAGS + CPPFLAGS="$CPPFLAGS -I." + AC_CHECK_HEADERS(systems.h) + AC_CHECK_HEADERS([mp4.h], [have_mp4_h=yes], [], + [#ifdef HAVE_SYSTEMS_H + # include + #endif + ]) + + AC_CHECK_LIB( mp4v2, MP4Read, have_mp4v2=yes, have_mp4v2=no ) + + if test "$have_mp4v2" = "yes" -a "$have_mp4_h" = "yes"; then + AC_DEFINE(HAVE_MP4V2, 1, [have mp4v2]) + MP4V2_INCLUDES="-I$mp4v2_dir/include" + MP4V2_LIBS="-L$mp4v2_dir/lib -lmp4v2" + else + have_mp4v2=no + fi + + CPPFLAGS=$ac_cppflags_save + CXXFLAGS=$ac_cxxflags_save + LDFLAGS=$ac_ldflags_save + AC_LANG_RESTORE +fi + +AC_SUBST(MP4V2_INCLUDES) +AC_SUBST(MP4V2_LIBS) + +AM_CONDITIONAL(with_mp4v2, [test x$have_mp4v2 != xno ]) + +############################################################################### +# END MP4V2 CHECK +############################################################################### + +KDE_CREATE_SUBDIRSLIST +AC_CONFIG_FILES([ Makefile ]) +AC_CONFIG_FILES([ doc/Makefile ]) +AC_CONFIG_FILES([ doc/en/Makefile ]) +AC_CONFIG_FILES([ po/Makefile ]) +AC_CONFIG_FILES([ src/Makefile ]) +AC_CONFIG_FILES([ src/amarokscript/Makefile ]) +AC_CONFIG_FILES([ src/metadata/Makefile ]) +AC_CONFIG_FILES([ src/metadata/aac/Makefile ]) +AC_CONFIG_FILES([ src/metadata/ape/Makefile ]) +AC_CONFIG_FILES([ src/metadata/asf/Makefile ]) +AC_CONFIG_FILES([ src/metadata/audible/Makefile ]) +AC_CONFIG_FILES([ src/metadata/m4a/Makefile ]) +AC_CONFIG_FILES([ src/metadata/mp4/Makefile ]) +AC_CONFIG_FILES([ src/metadata/optimfrog/Makefile ]) +AC_CONFIG_FILES([ src/metadata/rmff/Makefile ]) +AC_CONFIG_FILES([ src/metadata/speex/Makefile ]) +AC_CONFIG_FILES([ src/metadata/trueaudio/Makefile ]) +AC_CONFIG_FILES([ src/metadata/wav/Makefile ]) +AC_CONFIG_FILES([ src/metadata/wavpack/Makefile ]) +AC_CONFIG_FILES([ src/pics/Makefile ]) +AC_CONFIG_FILES([ src/pluginloader/Makefile ]) +AC_CONFIG_FILES([ src/plugins/Makefile ]) +AC_CONFIG_FILES([ src/plugins/format_infos/Makefile ]) +AC_CONFIG_FILES([ src/plugins/mime_types/Makefile ]) +AC_CONFIG_FILES([ src/plugins/plugins/Makefile ]) +AC_CONFIG_FILES([ src/plugins/rohling/Makefile ]) +AC_OUTPUT +# Check if KDE_SET_PREFIX was called, and --prefix was passed to configure +if test -n "$kde_libs_prefix" -a -n "$given_prefix"; then + # And if so, warn when they don't match + if test "$kde_libs_prefix" != "$given_prefix"; then + # And if kde doesn't know about the prefix yet + echo ":"`kde-config --path exe`":" | grep ":$given_prefix/bin/:" 2>&1 >/dev/null + if test $? -ne 0; then + echo "" + echo "Warning: you chose to install this package in $given_prefix," + echo "but KDE was found in $kde_libs_prefix." + echo "For this to work, you will need to tell KDE about the new prefix, by ensuring" + echo "that KDEDIRS contains it, e.g. export KDEDIRS=$given_prefix:$kde_libs_prefix" + echo "Then restart KDE." + echo "" + fi + fi +fi + +if test x$GXX = "xyes" -a x$kde_have_gcc_visibility = "xyes" -a x$kde_cv_val_qt_gcc_visibility_patched = "xno"; then + echo "" + echo "Your GCC supports symbol visibility, but the patch for Qt supporting visibility" + echo "was not included. Therefore, GCC symbol visibility support remains disabled." + echo "" + echo "For better performance, consider including the Qt visibility supporting patch" + echo "located at:" + echo "" + echo "http://bugs.kde.org/show_bug.cgi?id=109386" + echo "" + echo "and recompile all of Qt and KDE. Note, this is entirely optional and" + echo "everything will continue to work just fine without it." + echo "" +fi + +if test "$all_tests" = "bad"; then + if test ! "$cache_file" = "/dev/null"; then + echo "" + echo "Please remove the file $cache_file after changing your setup" + echo "so that configure will find the changes next time." + echo "" + fi +else + echo "" + echo "Good - your configure finished. Start make now" + echo "" +fi diff --git a/configure.in.in b/configure.in.in new file mode 100644 index 0000000..59d111e --- /dev/null +++ b/configure.in.in @@ -0,0 +1,144 @@ +#MIN_CONFIG(3.2.0) + +AM_INIT_AUTOMAKE(soundkonverter, 0.3.7) +AC_C_BIGENDIAN +AC_CHECK_KDEMAXPATHLEN + + +############################################################################### +# BEGIN CDPARANOIA CHECK +############################################################################### +# +#AC_CHECK_HEADER([cdda_interface.h], [with_cdparanoia=yes], [with_cdparanoia=no]) +# +#if test "$with_cdparanoia" != "yes" ; then +# soundkonverter_error_nocdparanoia=yes +# DO_NOT_COMPILE="$DO_NOT_COMPILE soundkonverter" +# no_soundkonverter=yes +# +# echo "" +# echo "-----------------------------------------" +# echo "ERROR: Could not find cdparanoia headers." +# echo "-----------------------------------------" +# echo "" +# +# AC_MSG_ERROR([could not find cdparanoia headers]) +#fi +# +############################################################################### +# END CDPARANOIA CHECK +############################################################################### + + +dnl ------------------------------------- +dnl cdparanoia check +dnl ------------------------------------- + +AC_CHECK_HEADERS(cdda_interface.h, have_paranoia="yes", have_paranoia="no" ) + +dnl ---------------------------------- +dnl Can soundkonverter be compiled? +dnl ---------------------------------- + +if test x$have_paranoia != xyes; then + DO_NOT_COMPILE="$DO_NOT_COMPILE soundkonverter" + no_paranoia=yes +fi + +############################################################################### +# BEGIN TAGLIB CHECK +############################################################################### + +TAGLIB_REQ_VERSION="1.4.0"; +AC_DEFUN([VERSION_TO_NUMBER], [`$1 | awk 'BEGIN { FS = "."; } { printf "%d", ([$]1* 1000 + [$]2) * 1000 + [$]3;}'`]) + +AC_PATH_PROG(TAGLIB_CONFIG, taglib-config, no) + +if test "x$TAGLIB_CONFIG" = "xno" ; then + soundkonverter_error_notaglib=yes + DO_NOT_COMPILE="$DO_NOT_COMPILE soundkonverter" + no_soundkonverter=yes +else + AC_DEFINE(HAVE_TAGLIB, 1, [have TagLib]) + taglib_includes=[`$TAGLIB_CONFIG --cflags`] + taglib_libs=[`$TAGLIB_CONFIG --libs`] + taglib_version=[`$TAGLIB_CONFIG --version`] + + if test VERSION_TO_NUMBER(echo $taglib_version) -lt VERSION_TO_NUMBER(echo $TAGLIB_REQ_VERSION); then + soundkonverter_error_taglibold=yes + DO_NOT_COMPILE="$DO_NOT_COMPILE soundkonverter" + no_soundkonverter=yes + fi +fi + +AC_SUBST(taglib_includes) +AC_SUBST(taglib_libs) + +############################################################################### +# END TAGLIB CHECK +############################################################################### + + +############################################################################### +# BEGIN MP4V2 CHECK +############################################################################### +# m4a/aac tag reading and writing needs libmp4v2 from faad2 or better mpeg4ip + +AC_ARG_WITH(mp4v2, + AC_HELP_STRING([--with-mp4v2],[build soundkonverter with M4A/AAC tag support from mp4v2/faad2]), + [have_mp4v2=$withval], + [have_mp4v2=no] +) + +AC_ARG_WITH(mp4v2-dir, + AC_HELP_STRING([--with-mp4v2-dir],[path to mp4v2 [default=/usr]]), + [mp4v2_dir="$withval"], + [mp4v2_dir=/usr] +) + +if test "$have_mp4v2" != "no"; then + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + ac_cxxflags_save=$CXXFLAGS + CXXFLAGS="$CXXFLAGS -I$mp4v2_dir/include" + ac_ldflags_save=$LDFLAGS + LDFLAGS="$LDFLAGS -L$mp4v2_dir/lib" + + # not even everyone using faad2 has + if ! test -f config.h; then + echo "#include \"confdefs.h\"" > config.h + fi + ac_cppflags_save=$CPPFLAGS + CPPFLAGS="$CPPFLAGS -I." + AC_CHECK_HEADERS(systems.h) + AC_CHECK_HEADERS([mp4.h], [have_mp4_h=yes], [], + [#ifdef HAVE_SYSTEMS_H + # include + #endif + ]) + + AC_CHECK_LIB( mp4v2, MP4Read, have_mp4v2=yes, have_mp4v2=no ) + + if test "$have_mp4v2" = "yes" -a "$have_mp4_h" = "yes"; then + AC_DEFINE(HAVE_MP4V2, 1, [have mp4v2]) + MP4V2_INCLUDES="-I$mp4v2_dir/include" + MP4V2_LIBS="-L$mp4v2_dir/lib -lmp4v2" + else + have_mp4v2=no + fi + + CPPFLAGS=$ac_cppflags_save + CXXFLAGS=$ac_cxxflags_save + LDFLAGS=$ac_ldflags_save + AC_LANG_RESTORE +fi + +AC_SUBST(MP4V2_INCLUDES) +AC_SUBST(MP4V2_LIBS) + +AM_CONDITIONAL(with_mp4v2, [test x$have_mp4v2 != xno ]) + +############################################################################### +# END MP4V2 CHECK +############################################################################### + diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 0000000..24dcee7 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,6 @@ +# the SUBDIRS is filled automatically by am_edit. If files are +# in this directory they are installed into the english dir + +KDE_LANG = en +KDE_DOCS = soundkonverter +SUBDIRS = $(AUTODIRS) diff --git a/doc/en/Makefile.am b/doc/en/Makefile.am new file mode 100644 index 0000000..4906905 --- /dev/null +++ b/doc/en/Makefile.am @@ -0,0 +1,2 @@ +KDE_DOCS = soundkonverter +KDE_LANG = en diff --git a/doc/en/index.docbook b/doc/en/index.docbook new file mode 100644 index 0000000..3a386a4 --- /dev/null +++ b/doc/en/index.docbook @@ -0,0 +1,209 @@ + +soundKonverter 0.3"> + + + + + + + +]> + + + + + + + + + + + + + + +The &soundkonverter; Handbook + + + + + +Daniel Faust + +
hessijames@gmail.com
+
+
+
+ + + + +2006 +2007 +Daniel Faust + + + +&FDLNotice; + + + +2007-01-08 +0.3 + + + + + +soundKonverter is frontend to various audio converters. + + + + + + +KDE +soundKonverter +audio +convert +transcode +decode +encode + + +
+ + + + +Introduction + + + +soundKonverter is frontend to various audio converters. + +It is extendable by plugins and supports many backends: +lame, oggenc, flac, musepack, faac, mplayer, ffmpeg - just to mention a few. + + +This way you can convert between various audio formats: +mp3, ogg, flac, mpc, aac, m4a, rm and wma, avi, flv (the latter reading only) for example. + +soundKonverter supports reading and writing tags for many formats, so the tags are preserved when converting files. + + +The key features are: Audio conversion, Replay Gain calculation, CD ripping + + +soundKonverter comes with an Amarok script that allows you to easily transcode files when transfering to your media device. + + + + + + +Credits and License + + +&soundkonverter; + + +Program copyright 2007 Daniel Faust hessijames@gmail.com + + + +Documentation copyright 2007 Daniel Faust hessijames@gmail.com + + + + +&underFDL; + + + +&underGPL; + + + + +Installation + + +Compilation and Installation + + +In order to compile soundKonverter, you need: taglib-devel, cdparanoia + + + + + + +&install.compile.documentation; + + + + + +&documentation.index; +
+ + + diff --git a/po/Makefile.am b/po/Makefile.am new file mode 100644 index 0000000..e51520a --- /dev/null +++ b/po/Makefile.am @@ -0,0 +1,3 @@ +POFILES = AUTO +noinst_HEADERS = de.po es.po fr.po hu.po it.po nl.po pl.po pt_BR.po pt_PT.po \ + ru.po diff --git a/po/de.po b/po/de.po new file mode 100644 index 0000000..323e320 --- /dev/null +++ b/po/de.po @@ -0,0 +1,1650 @@ +# translation of de.po to +# This file is put in the public domain. +# +# Daniel Faust , 2006, 2007, 2008. +msgid "" +msgstr "" +"Project-Id-Version: de\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-02-25 17:22+0100\n" +"PO-Revision-Date: 2008-02-25 17:44+0100\n" +"Last-Translator: Daniel Faust \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: KBabel 1.11.4\n" + +#: _translatorinfo.cpp:1 +msgid "" +"_: NAME OF TRANSLATORS\n" +"Your names" +msgstr "Daniel Faust" + +#: _translatorinfo.cpp:3 +msgid "" +"_: EMAIL OF TRANSLATORS\n" +"Your emails" +msgstr "hessijames@gmail.com" + +#: cddb.cpp:368 +msgid "No Title" +msgstr "Kein Titel" + +#: cddb.cpp:372 cdmanager.cpp:97 convert.cpp:513 convert.cpp:514 +#: convert.cpp:515 convert.cpp:517 convert.cpp:519 convert.cpp:520 +#: convert.cpp:1547 convert.cpp:1557 convert.cpp:1571 +#: replaygainfilelist.cpp:136 replaygainfilelist.cpp:137 +#: replaygainfilelist.cpp:144 replaygainfilelist.cpp:150 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:666 +#: replaygainfilelist.cpp:672 replaygainfilelist.cpp:701 +#: replaygainfilelist.cpp:707 replaygainfilelist.cpp:731 +#: replaygainfilelist.cpp:737 replaygainfilelist.cpp:945 +msgid "Unknown" +msgstr "Unbekannt" + +#: cddb.cpp:380 +msgid "Track %1" +msgstr "Stück %1" + +#: cddb.cpp:479 +msgid "Searching local cddb entry ..." +msgstr "Suche nach lokalem CDDB Eintrag ..." + +#: cddb.cpp:504 +msgid "Searching remote cddb entry ..." +msgstr "Suche nach entferntemCDDB Eintrag ..." + +#: cddb.cpp:528 +msgid "Found exact match cddb entry ..." +msgstr "CDDB Eintrag mit exakter Übereinstimmung gefunden ..." + +#: cddb.cpp:585 +msgid "Found close cddb entry ..." +msgstr "CDDB Eintrag mit naher Übereinstimmung gefunden ..." + +#: cddb.cpp:608 +msgid "CDDB Matches" +msgstr "CDDB Übereinstimmungen" + +#: cddb.cpp:608 +msgid "Several close CDDB entries found. Choose one:" +msgstr "Mehrere CDDB Einträge gefunden. Bitte wählen Sie einen:" + +#: cdmanager.cpp:46 filelist.cpp:618 +msgid "Audio CD" +msgstr "Audio CD" + +#: cdmanager.cpp:46 +msgid "Several audio CDs found. Choose one:" +msgstr "Mehrere Audio CDs gefunden. Bitte wählen Sie eine:" + +#: cdmanager.cpp:104 +msgid "No audio CD found." +msgstr "Keine Audio CD gefunden" + +#: cdopener.cpp:41 +msgid "Add CD tracks" +msgstr "CD Stücke hinzufügen" + +#: cdopener.cpp:52 cdopener.cpp:178 optionseditor.cpp:123 +msgid "Artist:" +msgstr "Interpret:" + +#: cdopener.cpp:57 cdopener.cpp:480 cdopener.cpp:485 cdopener.cpp:538 +#: cdopener.cpp:567 cdopener.cpp:682 cdopener.cpp:697 +msgid "Various Artists" +msgstr "Verschiedene Interpreten" + +#: cdopener.cpp:66 cdopener.cpp:193 optionseditor.cpp:138 +msgid "Composer:" +msgstr "Komponist:" + +#: cdopener.cpp:71 cdopener.cpp:496 cdopener.cpp:501 cdopener.cpp:548 +#: cdopener.cpp:579 cdopener.cpp:683 cdopener.cpp:698 +msgid "Various Composer" +msgstr "Verschiedene Komponisten" + +#: cdopener.cpp:83 optionseditor.cpp:158 +msgid "Album:" +msgstr "Album:" + +#: cdopener.cpp:91 optionseditor.cpp:178 +msgid "Disc No.:" +msgstr "CD Nr.:" + +#: cdopener.cpp:96 optionseditor.cpp:194 +msgid "Year:" +msgstr "Jahr:" + +#: cdopener.cpp:100 optionseditor.cpp:210 +msgid "Genre:" +msgstr "Genre:" + +#: cdopener.cpp:114 cdopener.cpp:532 filelist.cpp:578 filelist.cpp:587 +#: replaygainfilelist.cpp:136 replaygainfilelist.cpp:141 +#: replaygainfilelist.cpp:144 replaygainfilelist.cpp:178 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:663 +#: replaygainfilelist.cpp:666 replaygainfilelist.cpp:698 +#: replaygainfilelist.cpp:701 replaygainfilelist.cpp:728 +#: replaygainfilelist.cpp:731 +msgid "Track" +msgstr "Stück" + +#: cdopener.cpp:115 cdopener.cpp:568 cdopener.cpp:571 cdopener.cpp:607 +msgid "Artist" +msgstr "Interpret" + +#: cdopener.cpp:116 cdopener.cpp:580 cdopener.cpp:583 cdopener.cpp:620 +msgid "Composer" +msgstr "Komponist" + +#: cdopener.cpp:117 cdopener.cpp:594 +msgid "Title" +msgstr "Titel" + +#: cdopener.cpp:118 +msgid "Time" +msgstr "Zeit" + +#: cdopener.cpp:131 +msgid "No track selected" +msgstr "Keine Stücke ausgewählt" + +#: cdopener.cpp:159 optionseditor.cpp:88 +msgid "Title:" +msgstr "Titel:" + +#: cdopener.cpp:212 optionseditor.cpp:235 +msgid "Comment:" +msgstr "Kommentar:" + +#: cdopener.cpp:242 +msgid "Save cuesheet ..." +msgstr "Cue-Datei speichern ..." + +#: cdopener.cpp:250 +msgid "Add all tracks" +msgstr "Alle Stücke hinzufügen" + +#: cdopener.cpp:251 +msgid "Add selected tracks" +msgstr "Ausgewählte Stücke hinzufügen" + +#: cdopener.cpp:253 +msgid "Add full CD as one file" +msgstr "Ganze CD als ein Stück hinzufügen" + +#: cdopener.cpp:440 +msgid "All tracks" +msgstr "Alle Stücke" + +#: cdopener.cpp:443 +msgid "Tracks" +msgstr "Stücke" + +#: cdopener.cpp:742 +msgid "" +"A file with this name already exists.\n" +"\n" +"Do you want to overwrite the existing one?" +msgstr "" +"Eine Datei mit diesem Namen existiert bereits.\n" +"\n" +"Wollen Sie diese überschreiben?" + +#: cdopener.cpp:743 +msgid "File already exists" +msgstr "Datei existiert bereits" + +#: config.cpp:103 config.cpp:104 config.cpp:1197 config.cpp:1206 +#: config.cpp:1237 configgeneralpage.cpp:37 configgeneralpage.cpp:60 +#: configgeneralpage.cpp:62 configgeneralpage.cpp:269 +#: configgeneralpage.cpp:273 configgeneralpage.cpp:297 +#: configgeneralpage.cpp:306 configgeneralpage.cpp:316 options.cpp:153 +#: optionsdetailed.cpp:363 optionssimple.cpp:49 optionssimple.cpp:221 +#: optionssimple.cpp:518 soundkonverter.cpp:308 soundkonverter.cpp:309 +msgid "Last used" +msgstr "Zuletzt benutzt" + +#: config.cpp:508 +msgid "Convert with soundKonverter ..." +msgstr "Mit soundKonverter konvertieren ..." + +#: config.cpp:543 +msgid "Add Replay Gain with soundKonverter ..." +msgstr "Replay Gain mit soundKonverter hinzufügen ..." + +#: config.cpp:1228 config.cpp:1229 configgeneralpage.cpp:57 +#: configgeneralpage.cpp:302 convert.cpp:431 filelist.cpp:1379 +#: optionsdetailed.cpp:361 optionsdetailed.cpp:427 optionsdetailed.cpp:477 +#: optionsdetailed.cpp:527 optionsdetailed.cpp:604 optionssimple.cpp:46 +#: optionssimple.cpp:140 optionssimple.cpp:180 optionssimple.cpp:218 +#: optionssimple.cpp:407 optionssimple.cpp:515 optionssimple.cpp:535 +msgid "Lossless" +msgstr "Verlustfrei" + +#: config.cpp:1232 config.cpp:1233 configgeneralpage.cpp:58 +#: configgeneralpage.cpp:312 convert.cpp:434 convert.cpp:1378 +#: filelist.cpp:1382 optionsdetailed.cpp:362 optionsdetailed.cpp:480 +#: optionsdetailed.cpp:618 optionssimple.cpp:47 optionssimple.cpp:141 +#: optionssimple.cpp:185 optionssimple.cpp:219 optionssimple.cpp:421 +#: optionssimple.cpp:430 optionssimple.cpp:516 optionssimple.cpp:544 +msgid "Hybrid" +msgstr "Hybrid" + +#: config.cpp:1245 config.cpp:1252 config.cpp:1259 config.cpp:1266 +#: config.cpp:1273 convert.cpp:403 convert.cpp:995 convert.cpp:1567 +#: filelist.cpp:139 filelist.cpp:752 filelist.cpp:1270 filelist.cpp:1351 +#: optionsdetailed.cpp:246 optionsdetailed.cpp:467 optionsdetailed.cpp:582 +#: optionsdetailed.cpp:641 optionssimple.cpp:38 optionssimple.cpp:283 +#: optionssimple.cpp:312 optionssimple.cpp:340 optionssimple.cpp:367 +#: optionssimple.cpp:394 +msgid "Quality" +msgstr "Qualität" + +#: config.cpp:1248 config.cpp:1285 convert.cpp:450 filelist.cpp:1398 +#: optionsdetailed.cpp:538 optionssimple.cpp:294 +msgid "Mono" +msgstr "Mono" + +#: config.cpp:1250 config.cpp:1287 configgeneralpage.cpp:52 +#: configgeneralpage.cpp:289 optionsdetailed.cpp:356 optionssimple.cpp:41 +#: optionssimple.cpp:135 optionssimple.cpp:155 optionssimple.cpp:213 +#: optionssimple.cpp:269 optionssimple.cpp:510 optionssimple.cpp:525 +msgid "Very low" +msgstr "Sehr niedrig" + +#: config.cpp:1257 config.cpp:1294 configgeneralpage.cpp:53 +#: configgeneralpage.cpp:111 configgeneralpage.cpp:290 optionsdetailed.cpp:357 +#: optionssimple.cpp:42 optionssimple.cpp:136 optionssimple.cpp:160 +#: optionssimple.cpp:214 optionssimple.cpp:298 optionssimple.cpp:511 +#: optionssimple.cpp:525 +msgid "Low" +msgstr "Niedrig" + +#: config.cpp:1264 config.cpp:1301 configgeneralpage.cpp:54 +#: configgeneralpage.cpp:291 optionsdetailed.cpp:358 optionseditor.cpp:713 +#: optionssimple.cpp:43 optionssimple.cpp:137 optionssimple.cpp:165 +#: optionssimple.cpp:215 optionssimple.cpp:326 optionssimple.cpp:512 +#: optionssimple.cpp:526 +msgid "Medium" +msgstr "Mittel" + +#: config.cpp:1271 config.cpp:1308 configgeneralpage.cpp:55 +#: configgeneralpage.cpp:292 optionsdetailed.cpp:359 optionssimple.cpp:44 +#: optionssimple.cpp:138 optionssimple.cpp:170 optionssimple.cpp:216 +#: optionssimple.cpp:353 optionssimple.cpp:513 optionssimple.cpp:526 +msgid "High" +msgstr "Hoch" + +#: config.cpp:1278 config.cpp:1315 configgeneralpage.cpp:56 +#: configgeneralpage.cpp:293 optionsdetailed.cpp:360 optionssimple.cpp:45 +#: optionssimple.cpp:139 optionssimple.cpp:175 optionssimple.cpp:217 +#: optionssimple.cpp:380 optionssimple.cpp:514 optionssimple.cpp:527 +msgid "Very high" +msgstr "Sehr hoch" + +#: config.cpp:1282 config.cpp:1289 config.cpp:1296 config.cpp:1303 +#: config.cpp:1310 convert.cpp:387 convert.cpp:996 convert.cpp:997 +#: convert.cpp:1568 convert.cpp:1569 filelist.cpp:1234 filelist.cpp:1245 +#: filelist.cpp:1255 filelist.cpp:1335 optionsdetailed.cpp:246 +#: optionsdetailed.cpp:470 optionsdetailed.cpp:560 optionssimple.cpp:287 +#: optionssimple.cpp:316 optionssimple.cpp:344 optionssimple.cpp:371 +#: optionssimple.cpp:398 +msgid "Bitrate" +msgstr "Bitrate" + +#: config.cpp:1351 optionsdetailed.cpp:365 optionssimple.cpp:51 +#: optionssimple.cpp:142 optionssimple.cpp:190 optionssimple.cpp:223 +#: optionssimple.cpp:435 optionssimple.cpp:454 optionssimple.cpp:458 +#: optionssimple.cpp:468 optionssimple.cpp:472 optionssimple.cpp:520 +#: optionssimple.cpp:552 +msgid "User defined" +msgstr "Benutzerdefiniert" + +#: config.cpp:1394 config.cpp:1407 config.cpp:1411 config.cpp:1457 +#: config.cpp:1461 +msgid "files" +msgstr "Dateien" + +#: config.cpp:1419 config.cpp:1469 +msgid "all supported formats" +msgstr "alle unterstützten Formate" + +#: config.cpp:1419 config.cpp:1469 +msgid "all formats" +msgstr "alle Formate" + +#: configbackendspage.cpp:42 +msgid "Legend" +msgstr "Legende" + +#: configbackendspage.cpp:45 +msgid "Full support" +msgstr "Voll unterstützt" + +#: configbackendspage.cpp:48 +msgid "Most supported" +msgstr "Gut unterstützt" + +#: configbackendspage.cpp:51 +msgid "Basic support" +msgstr "Grob unterstützt" + +#: configbackendspage.cpp:57 +msgid "CD Ripper" +msgstr "CD Ripper" + +#: configbackendspage.cpp:243 +msgid "Encoder" +msgstr "Kodierer" + +#: configbackendspage.cpp:256 +msgid "Strength" +msgstr "Stärke" + +#: configbackendspage.cpp:263 +msgid "" +"Set the compression strength:\n" +"\n" +"Left = fast conversion\n" +"Right = good resultant file" +msgstr "" +"Wählen Sie die Kompressionsstärke:\n" +"\n" +"Links = schnelle Konvertierung\n" +"Rechts = gute resultierende Datei" + +#: configbackendspage.cpp:272 +msgid "Decoder" +msgstr "Dekodierer" + +#: configbackendspage.cpp:286 convert.cpp:593 convert.cpp:1580 +#: optionsdetailed.cpp:168 +msgid "Replay Gain" +msgstr "Replay Gain" + +#: configbackendspage.cpp:295 +msgid "Use internal Replay Gain" +msgstr "Internes Replay Gain verwenden" + +#: configbackendspage.cpp:296 +msgid "Use the internal Replay Gain calculator of the encoder" +msgstr "Verwende internen Replay Gain-Rechner des Kodierers" + +#: configbackendspage.cpp:320 +msgid "KDE audio CD protocol" +msgstr "KDE Audio CD Protokoll" + +#: configdialog.cpp:31 +msgid "Settings" +msgstr "Einstellungen" + +#: configdialog.cpp:56 +msgid "General" +msgstr "Generell" + +#: configdialog.cpp:68 +msgid "Plugins" +msgstr "Plugins" + +#: configdialog.cpp:80 +msgid "Environment" +msgstr "Umgebung" + +#: configdialog.cpp:92 +msgid "Backends" +msgstr "Backends" + +#: configenvironmentpage.cpp:32 +msgid "Directories to be scanned" +msgstr "Verzeichnisse zum Durchsuchen" + +#: configenvironmentpage.cpp:50 +msgid "" +"Move selected directory one position up.\n" +"This effects which backend will be chosen, if there are several versions." +msgstr "" +"Verschiebe ausgewählte Verzeichnisse eine Position nach Oben.\n" +"Dies beeinflusst, welches Backend ausgewählt wird, sollten mehere gefunden " +"werden." + +#: configenvironmentpage.cpp:60 +msgid "" +"Move selected directory one position down.\n" +"This effects which backend will be chosen, if there are several versions." +msgstr "" +"Verschiebe ausgewählte Verzeichnisse eine Position nach Unten.\n" +"Dies beeinflusst, welches Backend ausgewählt wird, sollten mehere gefunden " +"werden." + +#: configenvironmentpage.cpp:67 configpluginspage.cpp:50 +msgid "Add ..." +msgstr "Hinzufügen ..." + +#: configenvironmentpage.cpp:87 +msgid "Programs found" +msgstr "Gefundene Programme" + +#: configenvironmentpage.cpp:96 +msgid "Programs not found" +msgstr "Nicht gefundene Programme" + +#: configgeneralpage.cpp:34 +msgid "Start in Mode" +msgstr "Starte in Modus" + +#: configgeneralpage.cpp:38 options.cpp:36 +msgid "Simple" +msgstr "Einfach" + +#: configgeneralpage.cpp:39 options.cpp:41 +msgid "Detailed" +msgstr "Detailiert" + +#: configgeneralpage.cpp:49 +msgid "Default profile" +msgstr "Standardprofil" + +#: configgeneralpage.cpp:72 +msgid "Default format" +msgstr "Standardformat" + +#: configgeneralpage.cpp:107 +msgid "Process priority of the backends" +msgstr "Prozesspriorität der Backends" + +#: configgeneralpage.cpp:110 +msgid "Normal" +msgstr "Normal" + +#: configgeneralpage.cpp:122 +msgid "Use FAT compatible output file names" +msgstr "Benutze FAT kompatible Ausgabedateinamen" + +#: configgeneralpage.cpp:123 +msgid "Replaces some special characters like '?' by '_'." +msgstr "Ersetzt einige besondere Zeichen wie '?' durch '_'." + +#: configgeneralpage.cpp:133 +msgid "Conflict handling" +msgstr "Konfliktbehandlung" + +#: configgeneralpage.cpp:136 +msgid "Do that if the output file already exists" +msgstr "Tue dies, wenn die Zieldatei bereits existiert" + +#: configgeneralpage.cpp:137 +msgid "Generate new file name" +msgstr "Neuen Dateinamen generieren" + +#: configgeneralpage.cpp:138 +msgid "Skip file" +msgstr "Überspringe Datei" + +#: configgeneralpage.cpp:149 +msgid "Number of files to convert at once" +msgstr "Anzahl an gleichzeitig zu konvertierende Dateien" + +#: configgeneralpage.cpp:160 +msgid "Status update delay (time in msec.)" +msgstr "Status Aktualisierungsintervall (Zeit in msek.)" + +#: configgeneralpage.cpp:163 +msgid "Update the progress bar in this interval (time in milliseconds)" +msgstr "" +"Aktualisiere den Fortschrittsbalken in diesem Intervall (Zeit in " +"Millisekunden)" + +#: configgeneralpage.cpp:172 +msgid "Ask for new options, when adding files from external program" +msgstr "Frage nach neuen Optionen beim Hinzufügen aus externen Programmen" + +#: configgeneralpage.cpp:173 +msgid "" +"If you open a file with soundKonverter and soundKonverter is already " +"running,\n" +"you can either be asked to define new converting options\n" +"or the current settings from the soundKonverter main window are used." +msgstr "" +"Wenn Sie eine Datei mit soundKonverter öffnen und soundKonverter läuft " +"bereits,\n" +"können sie entweder aufgefordert werden, neue Konvertierungsoptionen " +"einzustellen,\n" +"oder es werden die aktuellen Optionen aus dem soundKonverter Hauptfenster " +"verwendet." + +#: configgeneralpage.cpp:183 +msgid "Execute user script (for advanced users)" +msgstr "Benutzerskript ausführen (für erfahrene Benutzer)" + +#: configgeneralpage.cpp:184 +msgid "" +"Executes a script after every finished conversion. Have a look at $KDEDIR/" +"soundkonverter/userscript.sh" +msgstr "" +"Führe einen Skript nach jeder Konvertireung aus. Siehe $KDEDIR/" +"soundkonverter/userscript.sh" + +#: configpluginspage.cpp:39 +msgid "Installed plugins" +msgstr "Installierte Plugins" + +#: configpluginspage.cpp:228 +msgid "*.soundkonverter.xml|Plugins (*.soundkonverter.xml)" +msgstr "*.soundkonverter.xml|Plugins (*.soundkonverter.xml)" + +#: configpluginspage.cpp:228 +msgid "Choose a plugin to add!" +msgstr "Wähle ein Plugin zum Hinzufügen" + +#: configpluginspage.cpp:253 configpluginspage.cpp:546 +msgid "" +"The plugin could not be installed. Please ensure that you have selected a " +"valid soundKonverter plugin file." +msgstr "" +"Das Plugin konnte nicht installiert werden. Bitte versichern Sie sich, dass " +"Sie eine intakte soundKonverter-Plugin Datei ausgewählt haben." + +#: configpluginspage.cpp:254 configpluginspage.cpp:294 +#: configpluginspage.cpp:547 configpluginspage.cpp:587 +msgid "Error while installing plugin" +msgstr "Fehler beim Installieren des Plugins" + +#: configpluginspage.cpp:279 configpluginspage.cpp:572 +msgid "" +"The plugin was installed successfully. Please restart soundKonverter in " +"order to activate it." +msgstr "" +"Das Plugin wurde erfolgreich installiert. Bitte Starten Sie soundKonverter " +"neu, um es zu aktivieren." + +#: configpluginspage.cpp:280 configpluginspage.cpp:573 +msgid "Plugin successfully installed" +msgstr "Plugin erfolgreich installiert" + +#: configpluginspage.cpp:293 configpluginspage.cpp:586 +msgid "" +"The plugin could not be installed. Please ensure that you have write " +"permission on your whole user directory." +msgstr "" +"Das Plugin konnte nicht installiert werden. Bitte versichern Sie sich, dass " +"Sie Schreibberechtigungen für ihr komplettes Heimverzeichnis besitzen." + +#: configpluginspage.cpp:311 configpluginspage.cpp:330 +#: configpluginspage.cpp:349 +msgid "" +"The plugin was removed successfully. Please restart soundKonverter in order " +"to deactivate it." +msgstr "" +"Das Plugin wurde erfolgreich deinstalliert. Bitte Starten Sie soundKonverter " +"neu, um es zu deaktivieren." + +#: configpluginspage.cpp:312 configpluginspage.cpp:331 +#: configpluginspage.cpp:350 +msgid "Plugin successfully removed" +msgstr "Plugin erfolgreich deinstalliert" + +#: configpluginspage.cpp:316 configpluginspage.cpp:335 +#: configpluginspage.cpp:354 +msgid "" +"The plugin could not be removed. Please ensure that you have write " +"permission on your whole user directory." +msgstr "" +"Das Plugin konnte nicht deinstalliert werden. Bitte versichern Sie sich, " +"dass Sie Schreibberechtigungen für ihr komplettes Heimverzeichnis besitzen." + +#: configpluginspage.cpp:317 configpluginspage.cpp:336 +#: configpluginspage.cpp:355 +msgid "Error while removing plugin" +msgstr "Fehler beim Deinstallieren des Plugins" + +#: configpluginspage.cpp:383 configpluginspage.cpp:395 +#: configpluginspage.cpp:407 +msgid "Version" +msgstr "Version" + +#: configpluginspage.cpp:384 configpluginspage.cpp:396 +#: configpluginspage.cpp:408 +msgid "Author" +msgstr "Autor" + +#: configpluginspage.cpp:417 configpluginspage.cpp:472 +msgid "No new plugins available!" +msgstr "Keine neuen Plugins verfügbar!" + +#: configpluginspage.cpp:477 +msgid "" +"The plugin list could not be downloaded. Please ensure, that your internet " +"connection works correct.\n" +"Maybe our server is busy at the moment, please try it again later." +msgstr "" +"Die Pluginsliste konnte nicht heruntergeladen werden. Bitte versichern Sie " +"sich, dass ihre Internetverbindung funktioniert.\n" +"Eventuell hat unser Server momentan eine Störung, bitte versuchen Sie es " +"später noch mal." + +#: configpluginspage.cpp:478 +msgid "Error while loading plugin list" +msgstr "Fehler beim Herunterladen der Pluginliste" + +#: configpluginspage.cpp:626 configpluginspage.cpp:632 +msgid "" +"The plugin info could not be downloaded. Please ensure, that your internet " +"connection works correctly." +msgstr "" +"Die Plugininformationen konnten nicht heruntergeladen werden. Bitte " +"versichern Sie sich, dass ihre Internetverbindung funktioniert.\n" +"Eventuell hat unser Server momentan eine Störung, bitte versuchen Sie es " +"später noch mal." + +#: configpluginspage.cpp:627 configpluginspage.cpp:633 +msgid "Error while loading plugin info" +msgstr "Fehler beim Herunterladen der Plugininformationen" + +#: convert.cpp:83 convert.cpp:86 convert.cpp:1538 +msgid "Getting file" +msgstr "Empfange Datei" + +#: convert.cpp:86 convert.cpp:130 convert.cpp:190 convert.cpp:260 +#: convert.cpp:314 convert.cpp:555 convert.cpp:593 convert.cpp:603 +#: convert.cpp:617 convert.cpp:661 convert.cpp:694 convert.cpp:1538 +#: convert.cpp:1542 convert.cpp:1547 convert.cpp:1551 convert.cpp:1557 +#: convert.cpp:1561 convert.cpp:1571 convert.cpp:1575 convert.cpp:1580 +#: convert.cpp:1583 convert.cpp:1587 filelist.cpp:136 filelist.cpp:638 +#: filelist.cpp:641 filelist.cpp:650 filelist.cpp:651 filelist.cpp:696 +#: filelist.cpp:726 filelist.cpp:729 filelist.cpp:733 filelist.cpp:860 +#: filelist.cpp:861 filelist.cpp:918 filelist.cpp:955 filelist.cpp:956 +msgid "State" +msgstr "Status" + +#: convert.cpp:116 convert.cpp:130 convert.cpp:1542 +msgid "Getting correction file" +msgstr "Empfange Korrekturdatei" + +#: convert.cpp:122 +msgid "Aborting, file does not exist" +msgstr "Breche ab, Datei existiert nicht" + +#: convert.cpp:157 convert.cpp:190 convert.cpp:260 convert.cpp:1547 +#: convert.cpp:1551 +msgid "Ripping" +msgstr "Rippe" + +#: convert.cpp:270 convert.cpp:314 convert.cpp:1557 convert.cpp:1561 +msgid "Decoding" +msgstr "Dekodiere" + +#: convert.cpp:334 convert.cpp:555 convert.cpp:1571 convert.cpp:1575 +msgid "Encoding" +msgstr "Kodiere" + +#: convert.cpp:453 filelist.cpp:1401 optionsdetailed.cpp:541 +msgid "Stereo" +msgstr "Stereo" + +#: convert.cpp:456 filelist.cpp:1404 optionsdetailed.cpp:544 +msgid "Joint-Stereo" +msgstr "Joint-Stereo" + +#: convert.cpp:459 filelist.cpp:1407 optionsdetailed.cpp:547 +msgid "Forced Joint-Stereo" +msgstr "Forced Joint-Stereo" + +#: convert.cpp:462 filelist.cpp:1410 optionsdetailed.cpp:550 +msgid "Dual Channels" +msgstr "Dual Kanäle" + +#: convert.cpp:563 replaygainfilelist.cpp:914 +msgid "Applying Replay Gain" +msgstr "Füge Replay Gain hinzu" + +#: convert.cpp:598 convert.cpp:603 +msgid "Writing tags" +msgstr "Schreibe Metadaten" + +#: convert.cpp:611 convert.cpp:617 convert.cpp:1583 +msgid "Moving file" +msgstr "Verschiebe Datei" + +#: convert.cpp:649 convert.cpp:661 convert.cpp:1587 +msgid "Moving correction file" +msgstr "Verschiebe Korrekturdatei" + +#: convert.cpp:688 convert.cpp:694 +msgid "Running user script" +msgstr "Führe Benutzerskript aus" + +#: convert.cpp:713 +msgid "Executing next step" +msgstr "Führe nächsten Schritt aus" + +#: convert.cpp:857 convert.cpp:874 convert.cpp:1123 convert.cpp:1147 +msgid "Got file" +msgstr "Datei empfangen" + +#: convert.cpp:891 convert.cpp:1204 convert.cpp:1216 +msgid "Could not write to file: `%1'" +msgstr "Konnte nicht in Datei schreiben: '%1'" + +#: convert.cpp:903 convert.cpp:918 convert.cpp:1228 convert.cpp:1255 +msgid "File moved" +msgstr "Datei verschoben" + +#: convert.cpp:941 filelist.cpp:70 filelist.cpp:138 filelist.cpp:750 +#: outputdirectory.cpp:39 replaygainfilelist.cpp:1141 +msgid "Output" +msgstr "Ausgabe" + +#: convert.cpp:1292 +msgid "Adding new item to conversion list: `%1'" +msgstr "Füge neues Element zur Konvertierungsliste hinzu: '`%1'" + +#: convert.cpp:1299 +msgid "Got log ID: %1" +msgstr "Neue Log ID: %1" + +#: convert.cpp:1302 +msgid "Tags successfully read" +msgstr "Metadaten erfolgreich ausgelesen" + +#: convert.cpp:1303 +msgid "Reading tags failed" +msgstr "Metadaten konnten nicht ausgelesen werden" + +#: convert.cpp:1443 convert.cpp:1453 replaygainfilelist.cpp:1025 +msgid "Killing process ..." +msgstr "Beende Prozess ..." + +#: convert.cpp:1446 replaygainfilelist.cpp:1028 +msgid "Killing process failed. Stopping after files are completed ..." +msgstr "Beenden des Prozesses fehlgeschlagen. Stoppe nachdem Dateien fertig sind ..." + +#: convert.cpp:1468 +msgid "Removing file from conversion list. Exit code %1" +msgstr "Entferne Datei von der Konvertierungsliste. Beendigungdcode %1" + +#: convert.cpp:1475 +msgid "Executing command: \"%1\"" +msgstr "Führe Befehl aus: \"%1\"" + +#: cuesheeteditor.cpp:29 +msgid "Cuesheet Editor" +msgstr "Cuesheet Editor" + +#: cuesheeteditor.cpp:76 +msgid "Generate" +msgstr "Generieren" + +#: cuesheeteditor.cpp:82 +msgid "Format" +msgstr "Formatieren" + +#: cuesheeteditor.cpp:88 +msgid "Shift Title/Performer" +msgstr "Titel/Interpreten tauschen" + +#: cuesheeteditor.cpp:113 +msgid "" +"

With this small tool you can process cue files as they are used for " +"burning music mixes and for organizing them in media players like amaroK." +"

You can generate a new file by pasting text into the input area. It " +"must be formated the following way:

Title - Artist [time]
Title - " +"Artist [3:25]
Title - Artist [2:37]
...
A tip: Use kwrite and " +"regular expressions to format it this way.

" +msgstr "" +"

Mit disem kleinen Werkzeug können Sie cue-Dateien, wie sie zum Brennen " +"von Musik-Mixen und zum Verwalten in Mediaplayern, wie amaroK verwendet " +"werden, überarbeiten.

Sie können eine neue Datei generieren lassen, " +"indem Sie Text in das Textfeld einfügen. Dieser muss wie folgt formatiert " +"sein:

Titel - Interpret [Zeit]
Titel - Interpret [3:25]
Titel - " +"Interpret [2:37]
...
Ein Tipp, verwenden Sie kwrite und reguläre " +"Ausdrücke, um eine Liedliste so zu formatieren.

" + +#: cuesheeteditor.cpp:114 +msgid "Cuesheet Editor - Help" +msgstr "Cuesheet Editor - Hilfe" + +#: dirdialog.cpp:24 +msgid "Add folder" +msgstr "Ordner hinzufügen" + +#: dirdialog.cpp:33 +msgid "Directory:" +msgstr "Ordner:" + +#: dirdialog.cpp:63 +msgid "Select all" +msgstr "Alle auswählen" + +#: dirdialog.cpp:69 +msgid "Select none" +msgstr "Keine auswählen" + +#: dirdialog.cpp:75 +msgid "Recursive" +msgstr "Rekursiv" + +#: dirdialog.cpp:106 dirdialog.cpp:133 +msgid "Choose a directory" +msgstr "Wähle ein Verzeichnis" + +#: filelist.cpp:70 filelist.cpp:137 filelist.cpp:736 filelist.cpp:737 +msgid "Input" +msgstr "Eingabe" + +#: filelist.cpp:170 +msgid "Edit options ..." +msgstr "Optionen bearbeiten ..." + +#: filelist.cpp:171 +msgid "Start conversion" +msgstr "Konvertierung starten" + +#: filelist.cpp:172 +msgid "Stop conversion" +msgstr "Konvertierung stoppen" + +#: filelist.cpp:184 +msgid "" +"

File List

Select your desired output options in " +"the form above and add some files.
You can add files by clicking on " +"\"Add files ...\" or dropping them here.
" +msgstr "" +"

Dateiliste

Wählen Sie ihre gewünschten " +"Ausgabeoptionen und fügen Sie Dateien hinzu.
Klicken Sie auf \"Dateien " +"hinzufügen ...\" oder lassen Sie Dateien hier fallen.
" + +#: filelist.cpp:578 filelist.cpp:593 +msgid "Audio CD (%1)" +msgstr "Audio CD (%1)" + +#: filelist.cpp:609 filelist.cpp:624 +msgid "Full audio CD (%1)" +msgstr "Komplette Audio CD (%1)" + +#: filelist.cpp:638 filelist.cpp:650 filelist.cpp:955 +msgid "Stopped" +msgstr "Gestoppt" + +#: filelist.cpp:641 filelist.cpp:650 filelist.cpp:955 +msgid "Failed" +msgstr "Fehlgeschlagen" + +#: filelist.cpp:650 filelist.cpp:726 filelist.cpp:860 filelist.cpp:955 +msgid "Will be skipped" +msgstr "Wird übersprungen" + +#: filelist.cpp:651 filelist.cpp:696 filelist.cpp:729 filelist.cpp:861 +#: filelist.cpp:918 filelist.cpp:956 progressindicator.cpp:49 +msgid "Waiting" +msgstr "Warte" + +#: filelist.cpp:733 +msgid "Converting" +msgstr "Konvertiere" + +#: logger.cpp:136 +msgid "Finished logging" +msgstr "Loggen beendet" + +#: logviewer.cpp:83 +msgid "Log Viewer" +msgstr "Log Betrachter" + +#: logviewer.cpp:90 +msgid "Job/File" +msgstr "Auftrag/Datei" + +#: main.cpp:12 +msgid "soundKonverter is a frontend to various sound en- and decoding programs." +msgstr "soundKonverter ist eine Oberfläche für verschiedene Audio-(De)Kodierer." + +#: main.cpp:18 +msgid "Open the Replay Gain tool an add all given files" +msgstr "Öffne das Replay Gain Werkzeug und füge alle gegeben Dateien hinzu" + +#: main.cpp:20 +msgid "List all tracks on the cd drive , 'auto' will search for a cd" +msgstr "Liste alle Stücke auf CD Laufwerk auf, 'auto' sucht nach einer CD" + +#: main.cpp:21 +msgid "Add all files using the given profile" +msgstr "Füge alle Dateien mit dem gegebenen Profil hinzu" + +#: main.cpp:22 +msgid "Add all files using the given format" +msgstr "Füge alle Dateien mit dem gegebenen Format hinzu" + +#: main.cpp:23 +msgid "Output all files to " +msgstr "Gebe alle Dateien ins Verzeichnis aus" + +#: main.cpp:24 +msgid "Start soundKonverter invisible" +msgstr "Starte soundKonverter unsichtbar" + +#: main.cpp:25 +msgid "" +"Close soundKonverter after all files are converted (enabled when using '--" +"invisible')" +msgstr "" +"Schließe soundKonverter, wenn alle Dateien konvertiert wurden " +"(eingeschaltet, wenn 'invisible' aktiv ist)" + +#: main.cpp:26 +msgid "Execute after each file has been converted" +msgstr "Führe den Befehl aus, nachdem jede Datei konvertiert wurde" + +#: main.cpp:27 +msgid "Audio file(s) to append to the file list" +msgstr "Audio Datei(en) zum Hinzufügen an die Dateiliste" + +#: main.cpp:33 +msgid "soundKonverter" +msgstr "soundKonverter" + +#: options.cpp:127 +msgid "" +"soundKonverter either found new backends or misses some.\n" +"Click on this button in order to open the configuration dialog." +msgstr "" +"soundKonverter hat entweder neune Backends gefunden oder vermisst welche.\n" +"Klicke auf diesen Knopf, um den Konfigurationsdialog zu öffnen." + +#: options.cpp:136 +msgid "Advanced Options" +msgstr "Erweiterte Optionen" + +#: optionsdetailed.cpp:45 +msgid "Convert" +msgstr "Konvertieren" + +#: optionsdetailed.cpp:73 +msgid "" +"vbr - variable bitrate\n" +"abr - average bitrate\n" +"cbr - constant bitrate" +msgstr "" +"vbr - variable Bitrate\n" +"abr - durchschnittliche Bitrate\n" +"cbr - konstante Bitrate" + +#: optionsdetailed.cpp:83 +msgid "Bitrate range" +msgstr "Bitratenbereich" + +#: optionsdetailed.cpp:84 +msgid "Use it only if, you know what you are doing, you could reduce the quality." +msgstr "" +"Benutzen Sie es nur, wenn Sie wissen, was Sie tun, Sie könnten die Qualität " +"reduzieren." + +#: optionsdetailed.cpp:119 +msgid "Resample" +msgstr "Resample" + +#: optionsdetailed.cpp:147 +msgid "Channels" +msgstr "Kanäle" + +#: optionsdetailed.cpp:170 +msgid "Add a Replay Gain tag to the converted file." +msgstr "Füge einen Replay Gain Tag zu der konvertierten Datei hinzu." + +#: optionsdetailed.cpp:171 +msgid "" +"Replay Gain is a volume correction technique. A volume difference is " +"calculated and stored in a tag. This way audio players can automatically " +"adjust the volume and the original music data is not modified (like at " +"normalization)." +msgstr "" +"Replay Gain ist ein Laustärke-Korrektusystem. Es wird eine " +"Lautstärkedifferenz errechnet und als Metainformation in der Datei " +"gespeichert. Aus diese Weise können Musik-Player die Laustärke automatisch " +"regulieren und die original Musikdaten werden nicht modifiziert (wie bei " +"einer Normalisierung)." + +#: optionsdetailed.cpp:192 +msgid "Save current options as a profile" +msgstr "Speichere aktuelle Optionen als Profil" + +#: optionsdetailed.cpp:208 +msgid "Command" +msgstr "Befehl" + +#: optionsdetailed.cpp:219 +#, c-format +msgid "%p: The parameters generated by soundKonverter" +msgstr "%p: Die Parameter, die von soundKonverter generiert werden" + +#: optionsdetailed.cpp:225 +#, c-format +msgid "%i: The input file ; %o: The output file" +msgstr "%i: Die Eingabedatei ; %o: Die Ausgabedatei" + +#: optionsdetailed.cpp:353 +msgid "New profile" +msgstr "Neues Profil" + +#: optionsdetailed.cpp:353 +msgid "Enter a name for the new profile:" +msgstr "Geben Sie den Namen des neuen Profils ein:" + +#: optionsdetailed.cpp:368 +msgid "You cannot overwrite the built-in profiles." +msgstr "Sie können nicht die eingebauten Profile überschreiben." + +#: optionsdetailed.cpp:369 optionsdetailed.cpp:379 +msgid "Profile already exists" +msgstr "Profil existiert bereits" + +#: optionsdetailed.cpp:378 +msgid "" +"A profile with this name already exists.\n" +"\n" +"Do you want to overwrite the existing one?" +msgstr "" +"Es existiert bereits ein Profil mit diesem Namen.\n" +"\n" +"Möchten Sie das bestehende überschreiben?" + +#: optionsdetailed.cpp:473 optionsdetailed.cpp:628 +msgid "Unchanged" +msgstr "Unverändert" + +#: optionsdetailed.cpp:483 optionsdetailed.cpp:604 +msgid "Undefined" +msgstr "Unbestimmt" + +#: optionsdetailed.cpp:561 optionsdetailed.cpp:619 +msgid "Kilobit per second" +msgstr "Kilobit pro Sekunde" + +#: optionsdetailed.cpp:689 +msgid "" +"This is a relative quality between 0 and 100.\n" +"The higher this number the higher is the quality.\n" +"soundKonverter will convert it into the file format's quality format.\n" +"See the \"What's this?\" for more informations.\n" +"\n" +"Current parameter: \"%1\"" +msgstr "" +"Dies ist eine relative Qualität zwischen 0 und 100.\n" +"Je höher die Nummer, desto höher ist die Qualität.\n" +"soundKonverter wird sie in das Qualitätsformat des Dateiformates umwandeln.\n" +"Schauen Sie nach dem \"Was ist das?\" für mehr Informationen.\n" +"\n" +"Current parameter: \"%1\"" + +#: optionseditor.cpp:28 +msgid "Options Editor" +msgstr "Optionen Editor" + +#: optionseditor.cpp:55 +msgid "Conversion" +msgstr "Konvertierung" + +#: optionseditor.cpp:55 +msgid "Conversion options" +msgstr "Konvertierungsoptionen" + +#: optionseditor.cpp:59 +msgid "Choose your prefered output options and click on \"Close\"!" +msgstr "" +"Wählen Sie ihre gewünschten Ausgabeoptionen und klicken Sie auf \"Schließen" +"\"!" + +#: optionseditor.cpp:70 +msgid "Edit conversion options" +msgstr "Bearbeite Konvertierungsoptionen" + +#: optionseditor.cpp:79 +msgid "Tags" +msgstr "Metadaten" + +#: optionseditor.cpp:103 +msgid "Track No.:" +msgstr "Stück Nr.:" + +#: optionseditor.cpp:256 +msgid "Edit tags" +msgstr "Metadaten bearbeiten" + +#: optionseditor.cpp:330 +msgid "No file selected" +msgstr "Keine Datei ausgewählt" + +#: optionseditor.cpp:358 +msgid "" +"The tags could not be read, because this file isn't a local one.\n" +"soundKonverter will try to read the tags, when it is about to convert the " +"file.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags." +msgstr "" +"Die Metadaten konnten nicht eingelesen werden, da die Datei nicht lokal " +"ist.\n" +"soundKonverter wird die Metadaten kurz vor dem Konvertieren einlesen.\n" +"Wenn Sie die Metadaten bearbeiten wollen, können Sie den Knopf unten " +"drücken.\n" +"Aber dann wird soundKonverter nichtmehr versuchen die Metadaten einzulesen." + +#: optionseditor.cpp:367 +msgid "" +"Reading the tags of this file failed.\n" +"soundKonverter will try to read the tags a second time, when it is about to " +"convert the file.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags a second time." +msgstr "" +"Die Metadaten konnten nicht eingelesen werden.\n" +"soundKonverter wird die Metadaten kurz vor dem Konvertieren einlesen.\n" +"Wenn Sie die Metadaten bearbeiten wollen, können Sie den Knopf unten " +"drücken.\n" +"Aber dann wird soundKonverter nichtmehr versuchen die Metadaten einzulesen." + +#: optionseditor.cpp:387 +msgid "%1 Files" +msgstr "%1 Dateien" + +#: optionseditor.cpp:402 +msgid "" +"You have selected multiple files with different conversion options.\n" +"You can change the options of all files by hitting the button below." +msgstr "" +"Sie haben mehrere Dateien mit unterschiedlichen Konvertierungsoptionen " +"ausgewählt.\n" +"Sie können die Optionen von allen Dateien durch Klicken auf den unteren " +"Knopf bearbeiten." + +#: optionseditor.cpp:408 +msgid "" +"Reading the tags of one or more files failed.\n" +"soundKonverter will try to read the tags a second time, when it is about to " +"convert the files.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags a second time." +msgstr "" +"Die Metadaten von einer oder mehreren Dateien konnten nicht eingelesen " +"werden.\n" +"soundKonverter wird die Metadaten kurz vor dem Konvertieren einlesen.\n" +"Wenn Sie die Metadaten bearbeiten wollen, können Sie den Knopf unten " +"drücken.\n" +"Aber dann wird soundKonverter nichtmehr versuchen die Metadaten einzulesen." + +#: optionsrequester.cpp:18 +msgid "Choose output options" +msgstr "Wählen Sie die Ausgabeoptionen" + +#: optionsrequester.cpp:28 +msgid "Click on \"Ok\" to add the files to the list in the main window!" +msgstr "Klicke auf \"Ok\", um die Dateien zur Liste im Hauptfenster hinzuzufügen!" + +#: optionsrequester.cpp:43 +msgid "" +"Warning: If you select \"wav\" as output format, your wav files will not be " +"added to the list." +msgstr "" +"Warnung: Wenn Sie \"wav\" als Ausgabeformat wählen, werden ihre wav Dateien " +"nicht zur Liste hinzugefügt." + +#: optionsrequester.cpp:59 +msgid "Ok" +msgstr "Ok" + +#: optionssimple.cpp:64 +msgid "Remove the selected profile" +msgstr "Entferne das ausgewählte Profil" + +#: optionssimple.cpp:70 optionssimple.cpp:90 +msgid "Info" +msgstr "Info" + +#: optionssimple.cpp:71 +msgid "Information about the selected profile" +msgstr "Informationen über das ausgewählte Profil" + +#: optionssimple.cpp:78 +msgid "Output format" +msgstr "Ausgabeformat" + +#: optionssimple.cpp:91 +msgid "Information about the selected file format" +msgstr "Informationen über das ausgewählte Format" + +#: optionssimple.cpp:157 +msgid "" +"This produces sound files of a very low quality.\n" +"That can be useful, if you have a mobile device, where your memory cell is " +"limited. It is not recommended to save your music in this quality without a " +"copy with higher quality.\n" +"It can also be used to save audio files with voices." +msgstr "" +"Dies produziert Audiodateien mit einer sehr geringen Qualität.\n" +"Dies kann sinnvoll sein, wenn sie ein mobiles Gerät mit geringem " +"Speicherplatz haben. Es wird nicht empfohlen Musik in dieser Qualität zu " +"speichern, ohne eine Sicherung zu haben.\n" +"Auch für Dateien mit Stimmaufzeichnungen kann dies praktisch sein." + +#: optionssimple.cpp:158 optionssimple.cpp:163 optionssimple.cpp:168 +#: optionssimple.cpp:173 optionssimple.cpp:178 optionssimple.cpp:183 +#: optionssimple.cpp:188 optionssimple.cpp:193 +msgid "Profile" +msgstr "Profil" + +#: optionssimple.cpp:162 +msgid "" +"This produces sound files of a low quality.\n" +"That can be useful if you habe a mobile device where your memory cell is " +"limited. It is not recommended to save your music in this quality without a " +"copy with higher quality." +msgstr "" +"Dies produziert Audiodateien mit einer geringen Qualität.\n" +"Dies kann sinnvoll sein, wenn sie ein mobiles Gerät mit geringem " +"Speicherplatz haben. Es wird nicht empfohlen Musik in dieser Qualität zu " +"speichern, ohne eine Sicherung zu haben." + +#: optionssimple.cpp:167 +msgid "" +"This produces sound files of a medium quality.\n" +"If your disc space is limited, you can use this to save your music." +msgstr "" +"Dies produziert Audiodateien mit einer mittleren Qualität.\n" +"Wenn ihnen nur wenig Speicherplatz zur Verfügung steht, benutzen Sie dieses " +"Profil, um ihre Musik zu speichern." + +#: optionssimple.cpp:172 +msgid "" +"This produces sound files of a high quality.\n" +"If you have enough disc space available, you can use this to save your music." +msgstr "" +"Dies produziert Audiodateien mit einer hohen Qualität.\n" +"Wenn ihnen genug Speicherplatz zur Verfügung steht, benutzen Sie dieses " +"Profil, um ihre Musik zu speichern." + +#: optionssimple.cpp:177 +msgid "" +"This produces sound files of a very high quality.\n" +"You should only use this, if you are a quality freak and have enough disc " +"space available." +msgstr "" +"Dies produziert Audiodateien mit einer sehr hohen Qualität.\n" +"Sie sollten dies nur verwenden, wenn sie ein Qualitätsfanatiker sind und " +"genug Speicherplatz zur Verfügung haben." + +#: optionssimple.cpp:182 +msgid "" +"This produces files, that have exact the same quality as the input files.\n" +"This files are very big and definitely only for quality freaks." +msgstr "" +"Dies produziert Audiodateien, welche mit den Ursprungsdateien vollständig " +"übereinstimmen.\n" +"Diese Dateien sind sehr groß und definitiv nur was für Qualitätsfanatiker." + +#: optionssimple.cpp:187 +msgid "" +"This produces two files. One lossy compressed playable file and one " +"correction file.\n" +"Both files together result in a file that is equivalent to the input file." +msgstr "" +"Dies erzeugt zwei Dateien. Eine verlustbehaftete abspielbare Datei und eine " +"Korrekturdatei.\n" +"Beide zusammen ergeben eine Datei, die der Eingabedatei äquivalent ist." + +#: optionssimple.cpp:192 +msgid "You can define your own profile in the \"detailed\" tab." +msgstr "Sie können ihr eigenes Profil im \"Detailliert \" Tab definieren." + +#: optionssimple.cpp:205 +msgid "Do you really want to remove the profile: %1" +msgstr "Möchten Sie wirklich das Profil '%1' entfernen?" + +#: optionssimple.cpp:206 +msgid "Remove profile?" +msgstr "Profil entfernen?" + +#: optionssimple.cpp:234 +msgid "" +"

Wave is a file format, that doesn't compress it's audio data.

\n" +"

So the quality is very high, but the file size is enormous. It is widely " +"spread and should work with every audio player.

\n" +"http://en.wikipedia.org/wiki/" +"Wav" +msgstr "" +"

Wave ist ein Dateiformat, welches die Audiodaten nicht komprimiert.

\n" +"

Dadurch ist die Qualität sehr hoch, die Dateigröße jedoch enorm. Es ist " +"weit verbreitet und sollte mit jedem Audioplayer abspielbar sein.

\n" +"http://de.wikipedia.org/wiki/" +"Wav" + +#: optionssimple.cpp:235 optionssimple.cpp:242 +msgid "File format" +msgstr "Dateiformat" + +#: outputdirectory.cpp:44 +msgid "By meta data" +msgstr "Anhand Metadaten" + +#: outputdirectory.cpp:45 +msgid "Source directory" +msgstr "Ursprungsordner" + +#: outputdirectory.cpp:46 +msgid "Specify output directory" +msgstr "Ordner angeben" + +#: outputdirectory.cpp:47 +msgid "Copy directory structure" +msgstr "Kopiere Ordnerstruktur" + +#: outputdirectory.cpp:61 +msgid "Clear the directory input field" +msgstr "Setzt das Verzeichniseingabefeld zurück." + +#: outputdirectory.cpp:81 outputdirectory.cpp:345 +msgid "Choose an output directory" +msgstr "Wähle ein Ausgabeverzeichnis" + +#: outputdirectory.cpp:87 +msgid "Open Konqueror with the output directory" +msgstr "Öffne Konqueror mit dem Ausgabeverzeichnis." + +#: outputdirectory.cpp:184 +msgid "Unknown Artist" +msgstr "Unbekannter Interpret" + +#: outputdirectory.cpp:188 +msgid "Unknown Album" +msgstr "Unbekanntes Album" + +#: outputdirectory.cpp:192 +msgid "No Comment" +msgstr "Kein Kommentar" + +#: outputdirectory.cpp:199 +msgid "Unknown Genre" +msgstr "Unbekanntes Genre" + +#: outputdirectory.cpp:206 +msgid "Unknown Composer" +msgstr "Unbekannter Komponist" + +#: outputdirectory.cpp:210 +msgid "Unknown Title" +msgstr "Unbekannter Titel" + +#: outputdirectory.cpp:264 +msgid "new" +msgstr "neu" + +#: outputdirectory.cpp:406 +msgid "Name all converted files according to the specified pattern" +msgstr "Benenne alle konvertierten Dateien mit Hilfe der Platzhalter" + +#: outputdirectory.cpp:408 +msgid "" +"

The following strings are wildcards, that will be replaced by the " +"information in the meta data:

%a - Artist
%b - Album
%c - " +"Comment
%d - Disc number
%g - Genre
%n - Track number
%p - " +"Composer
%t - Title
%y - Year
%f - Original file name

" +msgstr "" +"

Die folgenden Zeichenketten sind Platzhalter, sie werden durch die " +"nformationen in den Metadaten ersetzt:

%a - Interpret
%b - Album
" +"%c - Kommentar
%d - CD Nummer
%g - Genre
%n - Stücknummer
%p - " +"Komponist
%t - Titel
%y - Jahr
%f - Original Dateiname

" + +#: outputdirectory.cpp:420 +msgid "Output all converted files into the same directory as the original files" +msgstr "Gebe alle Dateien in das selbe Verzeichnis, wie die Originaldateien aus" + +#: outputdirectory.cpp:434 +msgid "Output all converted files into the specified output directory" +msgstr "Gebe alle Dateien in das angegebene Verzeichnis aus" + +#: outputdirectory.cpp:448 +msgid "Copy the whole directory structure for all converted files" +msgstr "Kopiere die komplette Verzeichnisstruktur für alle konvertierten Dateien" + +#: paranoia.cpp:214 +msgid "MB" +msgstr "MB" + +#: paranoia.cpp:215 +msgid "KB" +msgstr "KB" + +#: paranoia.cpp:216 +msgid "Bytes" +msgstr "Bytes" + +#: progressindicator.cpp:33 +msgid "Speed" +msgstr "Geschwindigkeit" + +#: progressindicator.cpp:41 +msgid "Time remaining" +msgstr "Verbleibende Zeit" + +#: progressindicator.cpp:95 progressindicator.cpp:96 replaygainscanner.cpp:216 +msgid "Finished" +msgstr "Beendet" + +#. i18n: file ./soundkonverterui.rc line 13 +#: rc.cpp:3 +#, no-c-format +msgid "&Conversion" +msgstr "&Konvertierung" + +#: replaygain.cpp:88 +msgid "Executing" +msgstr "Führe aus" + +#: replaygainfilelist.cpp:137 replaygainfilelist.cpp:147 +#: replaygainfilelist.cpp:150 replaygainfilelist.cpp:180 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:669 +#: replaygainfilelist.cpp:672 replaygainfilelist.cpp:704 +#: replaygainfilelist.cpp:707 replaygainfilelist.cpp:734 +#: replaygainfilelist.cpp:737 replaygainfilelist.cpp:940 +msgid "Album" +msgstr "Album" + +#: replaygainfilelist.cpp:213 +msgid "Calculate Replay Gain tags" +msgstr "Berechne Replay Gain Tags" + +#: replaygainfilelist.cpp:214 +msgid "Remove Replay Gain tags" +msgstr "Entferne Replay Gain Tags" + +#: replaygainfilelist.cpp:217 replaygainfilelist.cpp:825 +msgid "New album" +msgstr "Neues Album" + +#: replaygainfilelist.cpp:218 +msgid "Open all albums" +msgstr "Öffne alle Alben" + +#: replaygainfilelist.cpp:219 +msgid "Cloase all albums" +msgstr "Schließe alle Alben" + +#: replaygainfilelist.cpp:223 +msgid "" +"

Replay Gain Tool

With this tool you can add Replay " +"Gain tags to your audio files and remove them.
Replay Gain adds a volume " +"correction information to the files so that they can be played at an equal " +"volume level.
" +msgstr "" +"

Replay Gain Werkzeug

Mit diesem Werkzeug können " +"Sie Replay Gain Tags berechnen und wieder entfernen.
Replay Gain fügt " +"eine Lautstärkekorrektur-Information zu Audiodateien hinzu, sodass diese mit " +"der selben Lautstärke abgespielt werden können.
" + +#: replaygainfilelist.cpp:494 +msgid "You can't place files of different formats in the same 'album'." +msgstr "" +"Sie können nicht Dateien mit verschiedenen Formaten in dem selben Album " +"platzieren." + +#: replaygainfilelist.cpp:494 +msgid "Different file formats" +msgstr "Verschiedene Dateiformate" + +#: replaygainfilelist.cpp:987 +msgid "Removing Replay Gain" +msgstr "Entferne Replay Gain" + +#: replaygainfilelist.cpp:1148 +msgid "built-in" +msgstr "eingebaut" + +#: replaygainscanner.cpp:33 replaygainscanner.cpp:216 +#: replaygainscanner.cpp:231 +msgid "Replay Gain Tool" +msgstr "Replay Gain Werkzeug" + +#: replaygainscanner.cpp:43 +msgid "Add Folder ..." +msgstr "Ordner hinzufügen ..." + +#: replaygainscanner.cpp:44 +msgid "Add Files ..." +msgstr "Dateien hinzufügen ..." + +#: replaygainscanner.cpp:52 +msgid "Force recalculation" +msgstr "Neuberechnung erzwingen" + +#: replaygainscanner.cpp:53 +msgid "" +"Recalculate Replay Gain tag for files that already have a Replay Gain tag " +"set." +msgstr "" +"Berechne Replay Gain Informationen auch für die Dateien neu, die schon " +"welche haben." + +#: replaygainscanner.cpp:102 +msgid "Tag untagged" +msgstr "Replay Gain berechnen" + +#: replaygainscanner.cpp:103 +msgid "" +"Calculate Replay Gain tag for all files in the file list without Replay Gain " +"tag." +msgstr "" +"Berechne den Replay Gain Tag für alle Dateien in der Dateiliste ohne Replay " +"Gain Tag." + +#: replaygainscanner.cpp:109 +msgid "Untag tagged" +msgstr "Replay Gain entfernen" + +#: replaygainscanner.cpp:110 +msgid "Remove the Replay Gain tag from all files in the file list." +msgstr "" +"Entferne den Replay Gain Tag für alle Dateien in der Dateiliste mit Replay " +"Gain Tag." + +#: replaygainscanner.cpp:151 +msgid "Choose files!" +msgstr "Wähle Dateien!" + +#: soundkonverter.cpp:107 +msgid "Choose your prefered output options and click on \"Add files ...\"!" +msgstr "" +"Wählen Sie ihre gewünschten Ausgabeoptionen und klicken Sie auf \"Dateien " +"hinzufügen ...\"!" + +#: soundkonverter.cpp:110 soundkonverter.cpp:405 soundkonverter.cpp:448 +msgid "&Start conversion" +msgstr "Konvertierung &starten" + +#: soundkonverter.cpp:112 +msgid "&Replay Gain Tool ..." +msgstr "&Replay Gain Werkzeug ..." + +#: soundkonverter.cpp:114 +msgid "C&uesheet Editor ..." +msgstr "C&uesheet Editor ..." + +#: soundkonverter.cpp:115 +msgid "Show &Log ..." +msgstr "&Logs anzeigen ..." + +#: soundkonverter.cpp:118 +msgid "S&top after current file is complete" +msgstr "S&toppe, nachdem akuelle Datei komplett ist" + +#: soundkonverter.cpp:119 +msgid "&Continue after current file is complete" +msgstr "Fahre &fort, nachdem aktuelle Datei komplett ist" + +#: soundkonverter.cpp:120 +msgid "Stop &immediately" +msgstr "Stoppe unverzügl&ich" + +#: soundkonverter.cpp:148 +msgid "A&dd Files ..." +msgstr "&Dateien hinzufügen ..." + +#: soundkonverter.cpp:149 +msgid "Add &Folder ..." +msgstr "Ordner hinzu&fügen ..." + +#: soundkonverter.cpp:150 +msgid "Add CD &tracks ..." +msgstr "CD S&tücke hinzufügen ..." + +#: soundkonverter.cpp:151 +msgid "Add &URL ..." +msgstr "&URL hinzufügen ..." + +#: soundkonverter.cpp:154 +msgid "L&oad file list" +msgstr "Dateiliste la&den" + +#: soundkonverter.cpp:155 +msgid "Sa&ve file list" +msgstr "Dateiliste s&peichern" + +#: soundkonverter.cpp:229 +msgid "Add files ..." +msgstr "Dateien hinzufügen ..." + +#: soundkonverter.cpp:230 +msgid "Add folder ..." +msgstr "Ordner hinzufügen ..." + +#: soundkonverter.cpp:231 +msgid "Add CD tracks ..." +msgstr "CD Stücke hinzufügen ..." + +#: soundkonverter.cpp:232 +msgid "Add URL ..." +msgstr "URL hinzufügen ..." + +#: soundkonverter.cpp:240 +msgid "Start" +msgstr "Start" + +#: soundkonverter.cpp:417 +msgid "&Start queue" +msgstr "&Starte Warteschlange" + +#: soundkonverter.cpp:489 +msgid "Choose files to convert" +msgstr "Wähle Dateien zum Konvertieren" + +#: soundkonverter.cpp:617 +msgid "Open URL" +msgstr "Öffne URL" + +#: soundkonverter.cpp:617 +msgid "Enter a URL:" +msgstr "Gib eine URL ein:" + diff --git a/po/es.po b/po/es.po new file mode 100644 index 0000000..7e59a20 --- /dev/null +++ b/po/es.po @@ -0,0 +1,1661 @@ +# translation of es.po to +# This file is put in the public domain. +# +# Adrian Capel , 2007. +# Daniel Faust , 2007. +msgid "" +msgstr "" +"Project-Id-Version: es\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-02-25 17:22+0100\n" +"PO-Revision-Date: 2008-02-23 19:04+0000\n" +"Last-Translator: Julián Alarcón \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2008-04-06 10:52+0000\n" +"X-Generator: Launchpad (build Unknown)\n" + +#~ msgid "Adding new item to conversion list: `%1')" +#~ msgstr "Añadir nuevo elemento a la lista de conversión: %1')" + +#: _translatorinfo.cpp:1 +msgid "Your names" +msgstr "Adrián Capel,,Launchpad Contributions:,HessiJames,Julián Alarcón" + +#: _translatorinfo.cpp:3 +msgid "Your emails" +msgstr "adriancapel@openforyou.com,,,hessijames@gmail.com,alarconj@gmail.com" + +#: cddb.cpp:368 +msgid "No Title" +msgstr "Sin Titulo" + +#: cddb.cpp:372 cdmanager.cpp:97 convert.cpp:513 convert.cpp:514 +#: convert.cpp:515 convert.cpp:517 convert.cpp:519 convert.cpp:520 +#: convert.cpp:1547 convert.cpp:1557 convert.cpp:1571 +#: replaygainfilelist.cpp:136 replaygainfilelist.cpp:137 +#: replaygainfilelist.cpp:144 replaygainfilelist.cpp:150 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:666 +#: replaygainfilelist.cpp:672 replaygainfilelist.cpp:701 +#: replaygainfilelist.cpp:707 replaygainfilelist.cpp:731 +#: replaygainfilelist.cpp:737 replaygainfilelist.cpp:945 +msgid "Unknown" +msgstr "Desconocido" + +#: cddb.cpp:380 +msgid "Track %1" +msgstr "Pista %1" + +#: cddb.cpp:479 +msgid "Searching local cddb entry ..." +msgstr "Buscando la entrada local del cddb ..." + +#: cddb.cpp:504 +msgid "Searching remote cddb entry ..." +msgstr "Buscando la entrada remota del cddb ..." + +#: cddb.cpp:528 +msgid "Found exact match cddb entry ..." +msgstr "Se han encontrado entradas iguales o similares en el cdbd ..." + +#: cddb.cpp:585 +msgid "Found close cddb entry ..." +msgstr "Se han encontrado diferentes entradas en el cddb ..." + +#: cddb.cpp:608 +msgid "CDDB Matches" +msgstr "CDDB Similares" + +#: cddb.cpp:608 +msgid "Several close CDDB entries found. Choose one:" +msgstr "Se encontraron varias entradas CDDB. Seleccione una:" + +#: cdmanager.cpp:46 filelist.cpp:618 +msgid "Audio CD" +msgstr "Audio CD" + +#: cdmanager.cpp:46 +msgid "Several audio CDs found. Choose one:" +msgstr "Se han encontrado varios CDs de audio. Seleccione uno:" + +#: cdmanager.cpp:104 +msgid "No audio CD found." +msgstr "No se ha encontrado CD de audio." + +#: cdopener.cpp:41 +msgid "Add CD tracks" +msgstr "Añadir pistas de CD" + +#: cdopener.cpp:52 cdopener.cpp:178 optionseditor.cpp:123 +msgid "Artist:" +msgstr "Artista:" + +#: cdopener.cpp:57 cdopener.cpp:480 cdopener.cpp:485 cdopener.cpp:538 +#: cdopener.cpp:567 cdopener.cpp:682 cdopener.cpp:697 +msgid "Various Artists" +msgstr "Varios Artistas" + +#: cdopener.cpp:66 cdopener.cpp:193 optionseditor.cpp:138 +msgid "Composer:" +msgstr "Compositor:" + +#: cdopener.cpp:71 cdopener.cpp:496 cdopener.cpp:501 cdopener.cpp:548 +#: cdopener.cpp:579 cdopener.cpp:683 cdopener.cpp:698 +msgid "Various Composer" +msgstr "Varios Compositores" + +#: cdopener.cpp:83 optionseditor.cpp:158 +msgid "Album:" +msgstr "Álbum:" + +#: cdopener.cpp:91 optionseditor.cpp:178 +msgid "Disc No.:" +msgstr "Disco No.:" + +#: cdopener.cpp:96 optionseditor.cpp:194 +msgid "Year:" +msgstr "Año:" + +#: cdopener.cpp:100 optionseditor.cpp:210 +msgid "Genre:" +msgstr "Genero:" + +#: cdopener.cpp:114 cdopener.cpp:532 filelist.cpp:578 filelist.cpp:587 +#: replaygainfilelist.cpp:136 replaygainfilelist.cpp:141 +#: replaygainfilelist.cpp:144 replaygainfilelist.cpp:178 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:663 +#: replaygainfilelist.cpp:666 replaygainfilelist.cpp:698 +#: replaygainfilelist.cpp:701 replaygainfilelist.cpp:728 +#: replaygainfilelist.cpp:731 +msgid "Track" +msgstr "Pista" + +#: cdopener.cpp:115 cdopener.cpp:568 cdopener.cpp:571 cdopener.cpp:607 +msgid "Artist" +msgstr "Artista" + +#: cdopener.cpp:116 cdopener.cpp:580 cdopener.cpp:583 cdopener.cpp:620 +msgid "Composer" +msgstr "Compositor" + +#: cdopener.cpp:117 cdopener.cpp:594 +msgid "Title" +msgstr "Titulo" + +#: cdopener.cpp:118 +msgid "Time" +msgstr "Tiempo" + +#: cdopener.cpp:131 +msgid "No track selected" +msgstr "No hay ninguna pista seleccionada" + +#: cdopener.cpp:159 optionseditor.cpp:88 +msgid "Title:" +msgstr "Titulo:" + +#: cdopener.cpp:212 optionseditor.cpp:235 +msgid "Comment:" +msgstr "Comentario:" + +#: cdopener.cpp:242 +msgid "Save cuesheet ..." +msgstr "Guardar cuesheet ..." + +#: cdopener.cpp:250 +msgid "Add all tracks" +msgstr "Añadir todas las pistas" + +#: cdopener.cpp:251 +msgid "Add selected tracks" +msgstr "Añadir pistas seleccionadas" + +#: cdopener.cpp:253 +msgid "Add full CD as one file" +msgstr "Añadir el CD completo en un único archivo" + +#: cdopener.cpp:440 +msgid "All tracks" +msgstr "Todas las pistas" + +#: cdopener.cpp:443 +msgid "Tracks" +msgstr "Pistas" + +#: cdopener.cpp:742 +msgid "" +"A file with this name already exists.\n" +"\n" +"Do you want to overwrite the existing one?" +msgstr "" +"Ya existe un archivo con este nombre.\n" +"\n" +"¿Desea sobre escribir el archivo?" + +#: cdopener.cpp:743 +msgid "File already exists" +msgstr "El archivo ya existe" + +#: config.cpp:103 config.cpp:104 config.cpp:1197 config.cpp:1206 +#: config.cpp:1237 configgeneralpage.cpp:37 configgeneralpage.cpp:60 +#: configgeneralpage.cpp:62 configgeneralpage.cpp:269 +#: configgeneralpage.cpp:273 configgeneralpage.cpp:297 +#: configgeneralpage.cpp:306 configgeneralpage.cpp:316 options.cpp:153 +#: optionsdetailed.cpp:363 optionssimple.cpp:49 optionssimple.cpp:221 +#: optionssimple.cpp:518 soundkonverter.cpp:308 soundkonverter.cpp:309 +msgid "Last used" +msgstr "Ultimo utilizado" + +#: config.cpp:508 +msgid "Convert with soundKonverter ..." +msgstr "Convertir con soundKonverter ..." + +#: config.cpp:543 +msgid "Add Replay Gain with soundKonverter ..." +msgstr "Añadir Replay Gain con soundKonverter ..." + +#: config.cpp:1228 config.cpp:1229 configgeneralpage.cpp:57 +#: configgeneralpage.cpp:302 convert.cpp:431 filelist.cpp:1379 +#: optionsdetailed.cpp:361 optionsdetailed.cpp:427 optionsdetailed.cpp:477 +#: optionsdetailed.cpp:527 optionsdetailed.cpp:604 optionssimple.cpp:46 +#: optionssimple.cpp:140 optionssimple.cpp:180 optionssimple.cpp:218 +#: optionssimple.cpp:407 optionssimple.cpp:515 optionssimple.cpp:535 +msgid "Lossless" +msgstr "Sin Perdida" + +#: config.cpp:1232 config.cpp:1233 configgeneralpage.cpp:58 +#: configgeneralpage.cpp:312 convert.cpp:434 convert.cpp:1378 +#: filelist.cpp:1382 optionsdetailed.cpp:362 optionsdetailed.cpp:480 +#: optionsdetailed.cpp:618 optionssimple.cpp:47 optionssimple.cpp:141 +#: optionssimple.cpp:185 optionssimple.cpp:219 optionssimple.cpp:421 +#: optionssimple.cpp:430 optionssimple.cpp:516 optionssimple.cpp:544 +msgid "Hybrid" +msgstr "Híbrido" + +#: config.cpp:1245 config.cpp:1252 config.cpp:1259 config.cpp:1266 +#: config.cpp:1273 convert.cpp:403 convert.cpp:995 convert.cpp:1567 +#: filelist.cpp:139 filelist.cpp:752 filelist.cpp:1270 filelist.cpp:1351 +#: optionsdetailed.cpp:246 optionsdetailed.cpp:467 optionsdetailed.cpp:582 +#: optionsdetailed.cpp:641 optionssimple.cpp:38 optionssimple.cpp:283 +#: optionssimple.cpp:312 optionssimple.cpp:340 optionssimple.cpp:367 +#: optionssimple.cpp:394 +msgid "Quality" +msgstr "Calidad" + +#: config.cpp:1248 config.cpp:1285 convert.cpp:450 filelist.cpp:1398 +#: optionsdetailed.cpp:538 optionssimple.cpp:294 +msgid "Mono" +msgstr "Mono" + +#: config.cpp:1250 config.cpp:1287 configgeneralpage.cpp:52 +#: configgeneralpage.cpp:289 optionsdetailed.cpp:356 optionssimple.cpp:41 +#: optionssimple.cpp:135 optionssimple.cpp:155 optionssimple.cpp:213 +#: optionssimple.cpp:269 optionssimple.cpp:510 optionssimple.cpp:525 +msgid "Very low" +msgstr "Muy baja" + +#: config.cpp:1257 config.cpp:1294 configgeneralpage.cpp:53 +#: configgeneralpage.cpp:111 configgeneralpage.cpp:290 optionsdetailed.cpp:357 +#: optionssimple.cpp:42 optionssimple.cpp:136 optionssimple.cpp:160 +#: optionssimple.cpp:214 optionssimple.cpp:298 optionssimple.cpp:511 +#: optionssimple.cpp:525 +msgid "Low" +msgstr "Baja" + +#: config.cpp:1264 config.cpp:1301 configgeneralpage.cpp:54 +#: configgeneralpage.cpp:291 optionsdetailed.cpp:358 optionseditor.cpp:713 +#: optionssimple.cpp:43 optionssimple.cpp:137 optionssimple.cpp:165 +#: optionssimple.cpp:215 optionssimple.cpp:326 optionssimple.cpp:512 +#: optionssimple.cpp:526 +msgid "Medium" +msgstr "Media" + +#: config.cpp:1271 config.cpp:1308 configgeneralpage.cpp:55 +#: configgeneralpage.cpp:292 optionsdetailed.cpp:359 optionssimple.cpp:44 +#: optionssimple.cpp:138 optionssimple.cpp:170 optionssimple.cpp:216 +#: optionssimple.cpp:353 optionssimple.cpp:513 optionssimple.cpp:526 +msgid "High" +msgstr "Alta" + +#: config.cpp:1278 config.cpp:1315 configgeneralpage.cpp:56 +#: configgeneralpage.cpp:293 optionsdetailed.cpp:360 optionssimple.cpp:45 +#: optionssimple.cpp:139 optionssimple.cpp:175 optionssimple.cpp:217 +#: optionssimple.cpp:380 optionssimple.cpp:514 optionssimple.cpp:527 +msgid "Very high" +msgstr "Muy alta" + +#: config.cpp:1282 config.cpp:1289 config.cpp:1296 config.cpp:1303 +#: config.cpp:1310 convert.cpp:387 convert.cpp:996 convert.cpp:997 +#: convert.cpp:1568 convert.cpp:1569 filelist.cpp:1234 filelist.cpp:1245 +#: filelist.cpp:1255 filelist.cpp:1335 optionsdetailed.cpp:246 +#: optionsdetailed.cpp:470 optionsdetailed.cpp:560 optionssimple.cpp:287 +#: optionssimple.cpp:316 optionssimple.cpp:344 optionssimple.cpp:371 +#: optionssimple.cpp:398 +msgid "Bitrate" +msgstr "Tasa de bits" + +#: config.cpp:1351 optionsdetailed.cpp:365 optionssimple.cpp:51 +#: optionssimple.cpp:142 optionssimple.cpp:190 optionssimple.cpp:223 +#: optionssimple.cpp:435 optionssimple.cpp:454 optionssimple.cpp:458 +#: optionssimple.cpp:468 optionssimple.cpp:472 optionssimple.cpp:520 +#: optionssimple.cpp:552 +msgid "User defined" +msgstr "Personalizada" + +#: config.cpp:1394 config.cpp:1407 config.cpp:1411 config.cpp:1457 +#: config.cpp:1461 +msgid "files" +msgstr "archivos" + +#: config.cpp:1419 config.cpp:1469 +msgid "all supported formats" +msgstr "Todos los formatos soportados" + +#: config.cpp:1419 config.cpp:1469 +msgid "all formats" +msgstr "Todos los formatos" + +#: configbackendspage.cpp:42 +msgid "Legend" +msgstr "Leyenda" + +#: configbackendspage.cpp:45 +msgid "Full support" +msgstr "Soporte completo" + +#: configbackendspage.cpp:48 +msgid "Most supported" +msgstr "Soporte medio" + +#: configbackendspage.cpp:51 +msgid "Basic support" +msgstr "Soporte básico" + +#: configbackendspage.cpp:57 +msgid "CD Ripper" +msgstr "CD Ripper" + +#: configbackendspage.cpp:243 +msgid "Encoder" +msgstr "Codificador" + +#: configbackendspage.cpp:256 +msgid "Strength" +msgstr "Nivel" + +#: configbackendspage.cpp:263 +msgid "" +"Set the compression strength:\n" +"\n" +"Left = fast conversion\n" +"Right = good resultant file" +msgstr "" +"Fijar el nivel de compresión:\n" +"\n" +"Izquierda = Conversión rápida (Menor calidad)\n" +"Derecha = Conversión lenta (Mayor calidad)" + +#: configbackendspage.cpp:272 +msgid "Decoder" +msgstr "Decodificador" + +#: configbackendspage.cpp:286 convert.cpp:593 convert.cpp:1580 +#: optionsdetailed.cpp:168 +msgid "Replay Gain" +msgstr "Replay Gain" + +#: configbackendspage.cpp:295 +msgid "Use internal Replay Gain" +msgstr "Usar Replay Gain interno" + +#: configbackendspage.cpp:296 +msgid "Use the internal Replay Gain calculator of the encoder" +msgstr "Usar calculador interno de Replay Gain para la codificación" + +#: configbackendspage.cpp:320 +msgid "KDE audio CD protocol" +msgstr "Protocolo de audio CD de KDE" + +#: configdialog.cpp:31 +msgid "Settings" +msgstr "Preferencias" + +#: configdialog.cpp:56 +msgid "General" +msgstr "General" + +#: configdialog.cpp:68 +msgid "Plugins" +msgstr "Plugins" + +#: configdialog.cpp:80 +msgid "Environment" +msgstr "Entorno" + +#: configdialog.cpp:92 +msgid "Backends" +msgstr "Backends" + +#: configenvironmentpage.cpp:32 +msgid "Directories to be scanned" +msgstr "Directorios que se explorarán" + +#: configenvironmentpage.cpp:50 +msgid "" +"Move selected directory one position up.\n" +"This effects which backend will be chosen, if there are several versions." +msgstr "" +"Mueve el directorio seleccionado una posición hacia arriba.\n" +"Esto afecta sobre la elección del backend, si hay varias versiones." + +#: configenvironmentpage.cpp:60 +msgid "" +"Move selected directory one position down.\n" +"This effects which backend will be chosen, if there are several versions." +msgstr "" +"Mueve el directorio seleccionado una posición hacia abajo.\n" +"Esto afecta sobre la elección del backend, si hay varias versiones." + +#: configenvironmentpage.cpp:67 configpluginspage.cpp:50 +msgid "Add ..." +msgstr "Añadir ..." + +#: configenvironmentpage.cpp:87 +msgid "Programs found" +msgstr "Programas encontrados" + +#: configenvironmentpage.cpp:96 +msgid "Programs not found" +msgstr "Programas no encontrados" + +#: configgeneralpage.cpp:34 +msgid "Start in Mode" +msgstr "Iniciar en Modo" + +#: configgeneralpage.cpp:38 options.cpp:36 +msgid "Simple" +msgstr "Simple" + +#: configgeneralpage.cpp:39 options.cpp:41 +msgid "Detailed" +msgstr "Detallado" + +#: configgeneralpage.cpp:49 +msgid "Default profile" +msgstr "Perfil predeterminado" + +#: configgeneralpage.cpp:72 +msgid "Default format" +msgstr "Formato predeterminado" + +#: configgeneralpage.cpp:107 +msgid "Process priority of the backends" +msgstr "Prioridad de proceso para los backends" + +#: configgeneralpage.cpp:110 +msgid "Normal" +msgstr "Normal" + +#: configgeneralpage.cpp:122 +msgid "Use FAT compatible output file names" +msgstr "Usar nombres para los archivos de salida compatibles con FAT" + +#: configgeneralpage.cpp:123 +msgid "Replaces some special characters like '?' by '_'." +msgstr "Substituye algunos caracteres especiales como “?” por “_”" + +#: configgeneralpage.cpp:133 +msgid "Conflict handling" +msgstr "" + +#: configgeneralpage.cpp:136 +msgid "Do that if the output file already exists" +msgstr "" + +#: configgeneralpage.cpp:137 +msgid "Generate new file name" +msgstr "" + +#: configgeneralpage.cpp:138 +msgid "Skip file" +msgstr "" + +#: configgeneralpage.cpp:149 +msgid "Number of files to convert at once" +msgstr "Numero de archivos a convertir simultáneamente" + +#: configgeneralpage.cpp:160 +msgid "Status update delay (time in msec.)" +msgstr "Tiempo de refresco del estado (en ms.)" + +#: configgeneralpage.cpp:163 +msgid "Update the progress bar in this interval (time in milliseconds)" +msgstr "" +"Intervalo en el que se actualizara la barra de procesos (Tiempo en " +"milisegundos)" + +#: configgeneralpage.cpp:172 +msgid "Ask for new options, when adding files from external program" +msgstr "" +"Pedir nuevas opciones, al agregar archivos desde un programa externo." + +#: configgeneralpage.cpp:173 +msgid "" +"If you open a file with soundKonverter and soundKonverter is already " +"running,\n" +"you can either be asked to define new converting options\n" +"or the current settings from the soundKonverter main window are used." +msgstr "" +"Si usted abre un archivo con soundKonverter y soundKonverter ya está " +"funcionando,\n" +"usted puede definir nuevas opciones para la conversión\n" +"o se utilizaran las opciones actuales de la ventana principal de " +"soundKonverter." + +#: configgeneralpage.cpp:183 +msgid "Execute user script (for advanced users)" +msgstr "" + +#: configgeneralpage.cpp:184 +msgid "" +"Executes a script after every finished conversion. Have a look at " +"$KDEDIR/soundkonverter/userscript.sh" +msgstr "" + +#: configpluginspage.cpp:39 +msgid "Installed plugins" +msgstr "Plugins instalados" + +#: configpluginspage.cpp:228 +msgid "*.soundkonverter.xml|Plugins (*.soundkonverter.xml)" +msgstr "*.soundkonverter.xml|Plugins (*.soundkonverter.xml)" + +#: configpluginspage.cpp:228 +msgid "Choose a plugin to add!" +msgstr "¡Elija un plugin para añadir!" + +#: configpluginspage.cpp:253 configpluginspage.cpp:546 +msgid "" +"The plugin could not be installed. Please ensure that you have selected a " +"valid soundKonverter plugin file." +msgstr "" +"El plugin no ha podido ser instalado. Por favor, asegúrese de que ha " +"seleccionado un plugin valido para soundKonverter." + +#: configpluginspage.cpp:254 configpluginspage.cpp:294 +#: configpluginspage.cpp:547 configpluginspage.cpp:587 +msgid "Error while installing plugin" +msgstr "Error al instalar el plugin" + +#: configpluginspage.cpp:279 configpluginspage.cpp:572 +msgid "" +"The plugin was installed successfully. Please restart soundKonverter in " +"order to activate it." +msgstr "" +"El plugin fue instalado correctamente. Por favor, reinicie soundKonverter " +"para poder activarlo." + +#: configpluginspage.cpp:280 configpluginspage.cpp:573 +msgid "Plugin successfully installed" +msgstr "Plugin correctamente instalado" + +#: configpluginspage.cpp:293 configpluginspage.cpp:586 +msgid "" +"The plugin could not be installed. Please ensure that you have write " +"permission on your whole user directory." +msgstr "" +"El plugin no ha podido ser instalado. Por favor, asegúrese de que tiene " +"permisos de escritura en todo el directorio de su usuario." + +#: configpluginspage.cpp:311 configpluginspage.cpp:330 +#: configpluginspage.cpp:349 +msgid "" +"The plugin was removed successfully. Please restart soundKonverter in order " +"to deactivate it." +msgstr "" +"El plugin fue eliminado correctamente. Por favor, reinicie soundKonverter " +"para poder desactivarlo." + +#: configpluginspage.cpp:312 configpluginspage.cpp:331 +#: configpluginspage.cpp:350 +msgid "Plugin successfully removed" +msgstr "Plugin correctamente eliminado" + +#: configpluginspage.cpp:316 configpluginspage.cpp:335 +#: configpluginspage.cpp:354 +msgid "" +"The plugin could not be removed. Please ensure that you have write " +"permission on your whole user directory." +msgstr "" +"El plugin no se ha podido eliminar. Por favor, asegúrese de que tiene " +"permisos de escritura en todo el directorio de su usuario." + +#: configpluginspage.cpp:317 configpluginspage.cpp:336 +#: configpluginspage.cpp:355 +msgid "Error while removing plugin" +msgstr "Error al eliminar el plugin" + +#: configpluginspage.cpp:383 configpluginspage.cpp:395 +#: configpluginspage.cpp:407 +msgid "Version" +msgstr "Versión" + +#: configpluginspage.cpp:384 configpluginspage.cpp:396 +#: configpluginspage.cpp:408 +msgid "Author" +msgstr "Autor" + +#: configpluginspage.cpp:417 configpluginspage.cpp:472 +msgid "No new plugins available!" +msgstr "¡Ningún plugin nuevo disponible!" + +#: configpluginspage.cpp:477 +msgid "" +"The plugin list could not be downloaded. Please ensure, that your internet " +"connection works correct.\n" +"Maybe our server is busy at the moment, please try it again later." +msgstr "" +"La lista de plugins no ha podido ser descargada. Por favor, asegúrese de que " +"su conexión a Internet esta funcionando correctamente.\n" +"Quizá nuestro servidor este ocupado en este momento, por favor inténtelo más " +"tarde." + +#: configpluginspage.cpp:478 +msgid "Error while loading plugin list" +msgstr "Error al cargaba la lista de plugins" + +#: configpluginspage.cpp:626 configpluginspage.cpp:632 +msgid "" +"The plugin info could not be downloaded. Please ensure, that your internet " +"connection works correctly." +msgstr "" +"El plugin info no ha podido ser descargado. Por favor, asegúrese de que su " +"conexión a Internet funciona correctamente." + +#: configpluginspage.cpp:627 configpluginspage.cpp:633 +msgid "Error while loading plugin info" +msgstr "Error al cargar info plugin" + +#: convert.cpp:83 convert.cpp:86 convert.cpp:1538 +msgid "Getting file" +msgstr "Conseguir el archivo" + +#: convert.cpp:86 convert.cpp:130 convert.cpp:190 convert.cpp:260 +#: convert.cpp:314 convert.cpp:555 convert.cpp:593 convert.cpp:603 +#: convert.cpp:617 convert.cpp:661 convert.cpp:694 convert.cpp:1538 +#: convert.cpp:1542 convert.cpp:1547 convert.cpp:1551 convert.cpp:1557 +#: convert.cpp:1561 convert.cpp:1571 convert.cpp:1575 convert.cpp:1580 +#: convert.cpp:1583 convert.cpp:1587 filelist.cpp:136 filelist.cpp:638 +#: filelist.cpp:641 filelist.cpp:650 filelist.cpp:651 filelist.cpp:696 +#: filelist.cpp:726 filelist.cpp:729 filelist.cpp:733 filelist.cpp:860 +#: filelist.cpp:861 filelist.cpp:918 filelist.cpp:955 filelist.cpp:956 +msgid "State" +msgstr "Estado" + +#: convert.cpp:116 convert.cpp:130 convert.cpp:1542 +msgid "Getting correction file" +msgstr "Conseguir el archivo de la corrección" + +#: convert.cpp:122 +msgid "Aborting, file does not exist" +msgstr "Abortado, el archivo no existe" + +#: convert.cpp:157 convert.cpp:190 convert.cpp:260 convert.cpp:1547 +#: convert.cpp:1551 +msgid "Ripping" +msgstr "Ripeando" + +#: convert.cpp:270 convert.cpp:314 convert.cpp:1557 convert.cpp:1561 +msgid "Decoding" +msgstr "Decodificando" + +#: convert.cpp:334 convert.cpp:555 convert.cpp:1571 convert.cpp:1575 +msgid "Encoding" +msgstr "Codificando" + +#: convert.cpp:453 filelist.cpp:1401 optionsdetailed.cpp:541 +msgid "Stereo" +msgstr "Estéreo" + +#: convert.cpp:456 filelist.cpp:1404 optionsdetailed.cpp:544 +msgid "Joint-Stereo" +msgstr "Joint-Stereo" + +#: convert.cpp:459 filelist.cpp:1407 optionsdetailed.cpp:547 +msgid "Forced Joint-Stereo" +msgstr "Forzar Joint-Stereo" + +#: convert.cpp:462 filelist.cpp:1410 optionsdetailed.cpp:550 +msgid "Dual Channels" +msgstr "Doble Canal (Dual Channels)" + +#: convert.cpp:563 replaygainfilelist.cpp:914 +msgid "Applying Replay Gain" +msgstr "Aplicación de Replay Gain" + +#: convert.cpp:598 convert.cpp:603 +msgid "Writing tags" +msgstr "Escribir etiquetas" + +#: convert.cpp:611 convert.cpp:617 convert.cpp:1583 +msgid "Moving file" +msgstr "Mover archivo" + +#: convert.cpp:649 convert.cpp:661 convert.cpp:1587 +msgid "Moving correction file" +msgstr "Moviendo archivo de la corrección" + +#: convert.cpp:688 convert.cpp:694 +msgid "Running user script" +msgstr "" + +#: convert.cpp:713 +msgid "Executing next step" +msgstr "Ejecutar siguiente paso" + +#: convert.cpp:857 convert.cpp:874 convert.cpp:1123 convert.cpp:1147 +msgid "Got file" +msgstr "Archivo conseguido" + +#: convert.cpp:891 convert.cpp:1204 convert.cpp:1216 +msgid "Could not write to file: `%1'" +msgstr "No se ha podido escribir el archivo: '%1'" + +#: convert.cpp:903 convert.cpp:918 convert.cpp:1228 convert.cpp:1255 +msgid "File moved" +msgstr "Archivo movido" + +#: convert.cpp:941 filelist.cpp:70 filelist.cpp:138 filelist.cpp:750 +#: outputdirectory.cpp:39 replaygainfilelist.cpp:1141 +msgid "Output" +msgstr "Salida" + +#: convert.cpp:1292 +msgid "Adding new item to conversion list: `%1'" +msgstr "" + +#: convert.cpp:1299 +msgid "Got log ID: %1" +msgstr "ID conseguida del registro: %1" + +#: convert.cpp:1302 +msgid "Tags successfully read" +msgstr "Las etiquetas se leyeron correctamente" + +#: convert.cpp:1303 +msgid "Reading tags failed" +msgstr "Fallo al leer etiquetas" + +#: convert.cpp:1443 convert.cpp:1453 replaygainfilelist.cpp:1025 +msgid "Killing process ..." +msgstr "Deteniendo proceso ..." + +#: convert.cpp:1446 replaygainfilelist.cpp:1028 +msgid "Killing process failed. Stopping after files are completed ..." +msgstr "" +"Detención del proceso fallida. Se detendrá después de completar el archivo " +"..." + +#: convert.cpp:1468 +msgid "Removing file from conversion list. Exit code %1" +msgstr "Quitar el archivo de la lista de conversión. Código de salida %1" + +#: convert.cpp:1475 +msgid "Executing command: \"%1\"" +msgstr "Ejecutar comando: \"%1\"" + +#: cuesheeteditor.cpp:29 +msgid "Cuesheet Editor" +msgstr "Editor Cuesheet" + +#: cuesheeteditor.cpp:76 +msgid "Generate" +msgstr "Generar" + +#: cuesheeteditor.cpp:82 +msgid "Format" +msgstr "Formato" + +#: cuesheeteditor.cpp:88 +msgid "Shift Title/Performer" +msgstr "Cambiar Titulo/Autor" + +#: cuesheeteditor.cpp:113 +msgid "" +"

With this small tool you can process cue files as they are used for " +"burning music mixes and for organizing them in media players like " +"amaroK.

You can generate a new file by pasting text into the input " +"area. It must be formated the following way:

Title - Artist " +"[time]
Title - Artist [3:25]
Title - Artist [2:37]
...
A tip: " +"Use kwrite and regular expressions to format it this way.

" +msgstr "" +"

Con esta pequeña herramienta usted puede procesar los archivos cue, estos " +"se utilizan para grabar música mezclada en CD y para organizarlas en los " +"reproductores de medios como amaroK.

Usted puede generar un archivo " +"nuevo pegando el texto en el área de entrada. Debe de ser introducida con el " +"siguiente formato:

Titulo - Artista [Tiempo]
Titulo - Artista " +"[3:25]
Titulo - Artista [2:37]
...
Un consejo: Utilice kwrite y las " +"expresiones regulares para ajustar el formato de esta forma.

" + +#: cuesheeteditor.cpp:114 +msgid "Cuesheet Editor - Help" +msgstr "Editor Cuesheet - Ayuda" + +#: dirdialog.cpp:24 +msgid "Add folder" +msgstr "Añadir directorio" + +#: dirdialog.cpp:33 +msgid "Directory:" +msgstr "Directorio:" + +#: dirdialog.cpp:63 +msgid "Select all" +msgstr "Seleccionar todo" + +#: dirdialog.cpp:69 +msgid "Select none" +msgstr "Seleccionar nada" + +#: dirdialog.cpp:75 +msgid "Recursive" +msgstr "" + +#: dirdialog.cpp:106 dirdialog.cpp:133 +msgid "Choose a directory" +msgstr "Elegir un directorio" + +#: filelist.cpp:70 filelist.cpp:137 filelist.cpp:736 filelist.cpp:737 +msgid "Input" +msgstr "Entrada" + +#: filelist.cpp:170 +msgid "Edit options ..." +msgstr "Editar opciones ..." + +#: filelist.cpp:171 +msgid "Start conversion" +msgstr "Iniciar conversión" + +#: filelist.cpp:172 +msgid "Stop conversion" +msgstr "Detener conversión" + +#: filelist.cpp:184 +msgid "" +"

File List

Select your desired output options in " +"the form above and add some files.
You can add files by clicking on " +"\"Add files ...\" or dropping them here.
" +msgstr "" +"

Lista de Archivos

Seleccione una salida en las " +"opciones de arriba y añada los archivos.
Usted puede añadir archivos " +"haciendo click sobre \"Añadir archivos ...\" o arrastrándolos aquí.
" + +#: filelist.cpp:578 filelist.cpp:593 +msgid "Audio CD (%1)" +msgstr "CD de Audio (%1)" + +#: filelist.cpp:609 filelist.cpp:624 +msgid "Full audio CD (%1)" +msgstr "Todo el CD de audio (%1)" + +#: filelist.cpp:638 filelist.cpp:650 filelist.cpp:955 +msgid "Stopped" +msgstr "Detenido" + +#: filelist.cpp:641 filelist.cpp:650 filelist.cpp:955 +msgid "Failed" +msgstr "Fallo" + +#: filelist.cpp:650 filelist.cpp:726 filelist.cpp:860 filelist.cpp:955 +msgid "Will be skipped" +msgstr "" + +#: filelist.cpp:651 filelist.cpp:696 filelist.cpp:729 filelist.cpp:861 +#: filelist.cpp:918 filelist.cpp:956 progressindicator.cpp:49 +msgid "Waiting" +msgstr "En espera" + +#: filelist.cpp:733 +msgid "Converting" +msgstr "Convirtiendo" + +#: logger.cpp:136 +msgid "Finished logging" +msgstr "Fin de registro" + +#: logviewer.cpp:83 +msgid "Log Viewer" +msgstr "Visor de Registro" + +#: logviewer.cpp:90 +msgid "Job/File" +msgstr "Trabajo / Archivo" + +#: main.cpp:12 +msgid "" +"soundKonverter is a frontend to various sound en- and decoding programs." +msgstr "" +"soundKonverter es un frontend para varios programas de Codificación y " +"Decodificación de sonido." + +#: main.cpp:18 +msgid "Open the Replay Gain tool an add all given files" +msgstr "" +"Abrir la herramienta de Replay Gain y añadir todos los archivos indicados" + +#: main.cpp:20 +msgid "List all tracks on the cd drive , 'auto' will search for a cd" +msgstr "" +"Listar todos las pistas del dispositivo de cd , se buscaran " +"automáticamente en el cd" + +#: main.cpp:21 +msgid "Add all files using the given profile" +msgstr "Añadir todos los archivos usando el perfil indicado" + +#: main.cpp:22 +msgid "Add all files using the given format" +msgstr "Añadir todos los archivos usando el formato indicado" + +#: main.cpp:23 +msgid "Output all files to " +msgstr "Hacer salir todos los archivos a " + +#: main.cpp:24 +msgid "Start soundKonverter invisible" +msgstr "Iniciar soundKonverter invisible" + +#: main.cpp:25 +msgid "" +"Close soundKonverter after all files are converted (enabled when using '--" +"invisible')" +msgstr "" +"Cerrar soundKonverter después de convertir todos los archivos (Permitir al " +"usar '--invisible')" + +#: main.cpp:26 +msgid "Execute after each file has been converted" +msgstr "Ejecutar cuando se hayan convertido todos los archivos" + +#: main.cpp:27 +msgid "Audio file(s) to append to the file list" +msgstr "Archivo(s) de audio a añadir en la lista de archivos" + +#: main.cpp:33 +msgid "soundKonverter" +msgstr "soundKonverter" + +#: options.cpp:127 +msgid "" +"soundKonverter either found new backends or misses some.\n" +"Click on this button in order to open the configuration dialog." +msgstr "" +"soundKonverter encontró nuevos backends o falta alguno.\n" +"Haz click sobre el botón para abrir la ventana de configuración." + +#: options.cpp:136 +msgid "Advanced Options" +msgstr "Opciones Avanzadas" + +#: optionsdetailed.cpp:45 +msgid "Convert" +msgstr "Convertido" + +#: optionsdetailed.cpp:73 +msgid "" +"vbr - variable bitrate\n" +"abr - average bitrate\n" +"cbr - constant bitrate" +msgstr "" +"vbr - Tasa de bits variable\n" +"abr - Tasa de bits media\n" +"cbr - Tasa de bits constante" + +#: optionsdetailed.cpp:83 +msgid "Bitrate range" +msgstr "Rango de tasa de bits" + +#: optionsdetailed.cpp:84 +msgid "" +"Use it only if, you know what you are doing, you could reduce the quality." +msgstr "" +"Úselo solamente si usted sabe lo que está haciendo, podría reducir la " +"calidad." + +#: optionsdetailed.cpp:119 +msgid "Resample" +msgstr "Remuestreo" + +#: optionsdetailed.cpp:147 +msgid "Channels" +msgstr "Canales" + +#: optionsdetailed.cpp:170 +msgid "Add a Replay Gain tag to the converted file." +msgstr "Añadir etiquetas de Replay Gain a los archivos convertidos." + +#: optionsdetailed.cpp:171 +msgid "" +"Replay Gain is a volume correction technique. A volume difference is " +"calculated and stored in a tag. This way audio players can automatically " +"adjust the volume and the original music data is not modified (like at " +"normalization)." +msgstr "" +"El Replay Gain es una técnica para la corrección del volumen. Se calcula la " +"diferencia de volumen y se almacena en una etiqueta. De esta forma los " +"reproductores de audio pueden ajustar automáticamente el volumen sin que los " +"datos originales de la música se modifiquen (como en la normalización)." + +#: optionsdetailed.cpp:192 +msgid "Save current options as a profile" +msgstr "Guardar las opciones actuales como perfil" + +#: optionsdetailed.cpp:208 +msgid "Command" +msgstr "Comando" + +#: optionsdetailed.cpp:219 +#, c-format +msgid "%p: The parameters generated by soundKonverter" +msgstr "%p: Los parámetros generados por soundKonverter" + +#: optionsdetailed.cpp:225 +#, c-format +msgid "%i: The input file ; %o: The output file" +msgstr "%i: Archivo de entrada ; %o: Archivo de salida" + +#: optionsdetailed.cpp:353 +msgid "New profile" +msgstr "Nuevo perfil" + +#: optionsdetailed.cpp:353 +msgid "Enter a name for the new profile:" +msgstr "Introduzca un nombre para el nuevo perfil:" + +#: optionsdetailed.cpp:368 +msgid "You cannot overwrite the built-in profiles." +msgstr "No puede sobreescribir los perfiles incorporados." + +#: optionsdetailed.cpp:369 optionsdetailed.cpp:379 +msgid "Profile already exists" +msgstr "El perfil ya existe" + +#: optionsdetailed.cpp:378 +msgid "" +"A profile with this name already exists.\n" +"\n" +"Do you want to overwrite the existing one?" +msgstr "" +"Ya existe un perfil con este nombre.\n" +"\n" +"¿Desea sobre escribirlo?" + +#: optionsdetailed.cpp:473 optionsdetailed.cpp:628 +msgid "Unchanged" +msgstr "Sin cambios" + +#: optionsdetailed.cpp:483 optionsdetailed.cpp:604 +msgid "Undefined" +msgstr "Indefinido" + +#: optionsdetailed.cpp:561 optionsdetailed.cpp:619 +msgid "Kilobit per second" +msgstr "Kilobit por segundo" + +#: optionsdetailed.cpp:689 +msgid "" +"This is a relative quality between 0 and 100.\n" +"The higher this number the higher is the quality.\n" +"soundKonverter will convert it into the file format's quality format.\n" +"See the \"What's this?\" for more informations.\n" +"\n" +"Current parameter: \"%1\"" +msgstr "" +"Esto es una calidad relativa entre 0 y 100.\n" +"A más alto numero mayor calidad.\n" +"soundKonverter convertirá este valor en la calidad equivalente para el " +"formato de archivo elegido.\n" +"Para más información vea \"¿Que es esto?\".\n" +"\n" +"Parámetro actual: \"%1\"" + +#: optionseditor.cpp:28 +msgid "Options Editor" +msgstr "Editor de Opciones" + +#: optionseditor.cpp:55 +msgid "Conversion" +msgstr "Conversión" + +#: optionseditor.cpp:55 +msgid "Conversion options" +msgstr "Opciones de conversión" + +#: optionseditor.cpp:59 +msgid "Choose your prefered output options and click on \"Close\"!" +msgstr "" +"Elija su configuración de salida preferida y haga click sobre \"Cerrar\"!" + +#: optionseditor.cpp:70 +msgid "Edit conversion options" +msgstr "Editar opciones de conversión" + +#: optionseditor.cpp:79 +msgid "Tags" +msgstr "Etiquetas" + +#: optionseditor.cpp:103 +msgid "Track No.:" +msgstr "Pista No.:" + +#: optionseditor.cpp:256 +msgid "Edit tags" +msgstr "Editar etiquetas" + +#: optionseditor.cpp:330 +msgid "No file selected" +msgstr "Archivo no seleccionado" + +#: optionseditor.cpp:358 +msgid "" +"The tags could not be read, because this file isn't a local one.\n" +"soundKonverter will try to read the tags, when it is about to convert the " +"file.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags." +msgstr "" +"Las etiquetas no pueden ser leídas, porque este archivo no es local.\n" +"soundKonverter intentara leer las etiquetas por segunda vez cuando este " +"sobre los archivos a convertir.\n" +"Si desea corregir las etiquetas puede pulsar sobre el botón, entonces \n" +"soundKonverter no intentara leer las etiquetas." + +#: optionseditor.cpp:367 +msgid "" +"Reading the tags of this file failed.\n" +"soundKonverter will try to read the tags a second time, when it is about to " +"convert the file.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags a second time." +msgstr "" +"La lectura de las etiquetas de este archivos fallo.\n" +"soundKonverter intentara leer las etiquetas por segunda vez cuando este " +"sobre los archivos a convertir.\n" +"Si desea corregir las etiquetas puede pulsar sobre el botón, entonces \n" +"soundKonverter no intentara leer las etiquetas por segunda vez." + +#: optionseditor.cpp:387 +msgid "%1 Files" +msgstr "%1 Archivos" + +#: optionseditor.cpp:402 +msgid "" +"You have selected multiple files with different conversion options.\n" +"You can change the options of all files by hitting the button below." +msgstr "" +"Has seleccionado varios archivos con diversas opciones de conversión.\n" +"Puedes cambiar las opciones de todos los archivos pulsando sobre el botón de " +"abajo." + +#: optionseditor.cpp:408 +msgid "" +"Reading the tags of one or more files failed.\n" +"soundKonverter will try to read the tags a second time, when it is about to " +"convert the files.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags a second time." +msgstr "" +"La lectura de las etiquetas de uno o más archivos fallo.\n" +"soundKonverter intentara leer las etiquetas por segunda vez cuando este " +"sobre los archivos a convertir.\n" +"Si desea corregir las etiquetas puede pulsar sobre el botón, entonces \n" +"soundKonverter no intentara leer las etiquetas por segunda vez." + +#: optionsrequester.cpp:18 +msgid "Choose output options" +msgstr "Elegir las opciones de la salida" + +#: optionsrequester.cpp:28 +msgid "Click on \"Ok\" to add the files to the list in the main window!" +msgstr "" +"¡Pulse sobre \"Aceptar\" para añadir los archivos a la lista de la ventana " +"principal!" + +#: optionsrequester.cpp:43 +msgid "" +"Warning: If you select \"wav\" as output format, your wav files will not be " +"added to the list." +msgstr "" +"Advertencia: Si usted selecciona \"wav\" como formato de la salida, sus " +"archivos wav no serán agregados a la lista." + +#: optionsrequester.cpp:59 +msgid "Ok" +msgstr "Aceptar" + +#: optionssimple.cpp:64 +msgid "Remove the selected profile" +msgstr "Eliminar el perfil seleccionado" + +#: optionssimple.cpp:70 optionssimple.cpp:90 +msgid "Info" +msgstr "Info" + +#: optionssimple.cpp:71 +msgid "Information about the selected profile" +msgstr "Información sobre el perfil seleccionado" + +#: optionssimple.cpp:78 +msgid "Output format" +msgstr "Formato de Salida" + +#: optionssimple.cpp:91 +msgid "Information about the selected file format" +msgstr "Información sobre el formato del archivo seleccionado" + +#: optionssimple.cpp:157 +msgid "" +"This produces sound files of a very low quality.\n" +"That can be useful, if you have a mobile device, where your memory cell is " +"limited. It is not recommended to save your music in this quality without a " +"copy with higher quality.\n" +"It can also be used to save audio files with voices." +msgstr "" +"Esto produce archivos de sonido de muy baja calidad.\n" +"Esto puede ser útil si usted tiene un dispositivo móvil donde está limitada " +"la capacidad de memoria. No es recomendable guardar su música en esta " +"calidad sin tener una copia del archivo con más calidad.\n" +"Puede ser utilizado también para guardar archivos de audio con voces." + +#: optionssimple.cpp:158 optionssimple.cpp:163 optionssimple.cpp:168 +#: optionssimple.cpp:173 optionssimple.cpp:178 optionssimple.cpp:183 +#: optionssimple.cpp:188 optionssimple.cpp:193 +msgid "Profile" +msgstr "Perfil" + +#: optionssimple.cpp:162 +msgid "" +"This produces sound files of a low quality.\n" +"That can be useful if you habe a mobile device where your memory cell is " +"limited. It is not recommended to save your music in this quality without a " +"copy with higher quality." +msgstr "" +"Esto produce archivos de sonido de baja calidad.\n" +"Esto puede ser útil si usted tiene un dispositivo móvil donde está limitada " +"la capacidad de memoria. No es recomendable guardar su música en esta " +"calidad sin tener una copia del archivo con más calidad." + +#: optionssimple.cpp:167 +msgid "" +"This produces sound files of a medium quality.\n" +"If your disc space is limited, you can use this to save your music." +msgstr "" +"Esto produce archivos de sonido de calidad media.\n" +"Si el espacio de su disco es limitado, puede utilizar esta opción para " +"guardar su música." + +#: optionssimple.cpp:172 +msgid "" +"This produces sound files of a high quality.\n" +"If you have enough disc space available, you can use this to save your music." +msgstr "" +"Esto produce archivos de sonido de alta calidad.\n" +"Si usted dispone de bastante espacio disponible en el disco puede utilizar " +"esta opción para guardar su música." + +#: optionssimple.cpp:177 +msgid "" +"This produces sound files of a very high quality.\n" +"You should only use this, if you are a quality freak and have enough disc " +"space available." +msgstr "" +"Esto produce archivos de sonido de muy alta calidad.\n" +"Usted solamente debe utilizar esta opción si necesita de una calidad anormal " +"y dispone de suficiente espacio disponible en el disco." + +#: optionssimple.cpp:182 +msgid "" +"This produces files, that have exact the same quality as the input files.\n" +"This files are very big and definitely only for quality freaks." +msgstr "" +"Esto produce archivos que tienen exactamente la misma calidad que los " +"archivos de entrada.\n" +"Estos archivos son muy grandes y definitivamente es solo para los freaks de " +"la calidad." + +#: optionssimple.cpp:187 +msgid "" +"This produces two files. One lossy compressed playable file and one " +"correction file.\n" +"Both files together result in a file that is equivalent to the input file." +msgstr "" +"Esto produce dos archivos. Un archivo reproducible sin perdida y un archivo " +"de corrección.\n" +"Ambos archivos juntos dan lugar a un archivo que es equivalente al fichero " +"de entrada." + +#: optionssimple.cpp:192 +msgid "You can define your own profile in the \"detailed\" tab." +msgstr "Usted puede definir su propio perfil en la pestaña \"Detallado\"." + +#: optionssimple.cpp:205 +msgid "Do you really want to remove the profile: %1" +msgstr "Realmente desea eliminar el perfil: %1" + +#: optionssimple.cpp:206 +msgid "Remove profile?" +msgstr "¿Eliminar el perfil?" + +#: optionssimple.cpp:234 +msgid "" +"

Wave is a file format, that doesn't compress it's audio data.

\n" +"

So the quality is very high, but the file size is enormous. It is widely " +"spread and should work with every audio player.

\n" +"http://en.wikipedia.org/wiki/Wav" +msgstr "" +"

Wave es un formato de audio sin compresión.

\n" +"

La calidad es muy alta, pero el tamaño del archivo es enorme. Es un " +"formato muy extendido y debería de funcionar con cualquier reproductor de " +"audio.

\n" +"
http://es.wikipedia.org/wiki/WAV" + +#: optionssimple.cpp:235 optionssimple.cpp:242 +msgid "File format" +msgstr "Formato de archivo" + +#: outputdirectory.cpp:44 +msgid "By meta data" +msgstr "Por metadatos" + +#: outputdirectory.cpp:45 +msgid "Source directory" +msgstr "Directorio fuente" + +#: outputdirectory.cpp:46 +msgid "Specify output directory" +msgstr "Especificar el directorio de salida" + +#: outputdirectory.cpp:47 +msgid "Copy directory structure" +msgstr "Copiar la estructura del directorio" + +#: outputdirectory.cpp:61 +msgid "Clear the directory input field" +msgstr "Vacía el campo de entrada del directorio" + +#: outputdirectory.cpp:81 outputdirectory.cpp:345 +msgid "Choose an output directory" +msgstr "Elegir un directorio de salida" + +#: outputdirectory.cpp:87 +msgid "Open Konqueror with the output directory" +msgstr "Abrir con Konqueror el directorio de salida" + +#: outputdirectory.cpp:184 +msgid "Unknown Artist" +msgstr "Artista Desconocido" + +#: outputdirectory.cpp:188 +msgid "Unknown Album" +msgstr "Álbum Desconocido" + +#: outputdirectory.cpp:192 +msgid "No Comment" +msgstr "Ningún Comentario" + +#: outputdirectory.cpp:199 +msgid "Unknown Genre" +msgstr "Genero Desconocido" + +#: outputdirectory.cpp:206 +msgid "Unknown Composer" +msgstr "Compositor Desconocido" + +#: outputdirectory.cpp:210 +msgid "Unknown Title" +msgstr "Título Desconocido" + +#: outputdirectory.cpp:264 +msgid "new" +msgstr "nuevo" + +#: outputdirectory.cpp:406 +msgid "Name all converted files according to the specified pattern" +msgstr "Nombrar todos los archivos según el patrón especificado" + +#: outputdirectory.cpp:408 +msgid "" +"

The following strings are wildcards, that will be replaced by the " +"information in the meta data:

%a - Artist
%b - Album
%c - " +"Comment
%d - Disc number
%g - Genre
%n - Track number
%p - " +"Composer
%t - Title
%y - Year
%f - Original file name

" +msgstr "" +"

Las secuencias siguientes son comodines, que serán substituidos por la " +"información de los metadatos:

%a - Artista
%b - Álbum
%c - " +"Comentario
%d - Numero de disco
%g - Genero
%n - Numero de " +"pista
%p - Compositor
%t - Titulo
%y - Año
%f - Nombre original " +"del archivo

" + +#: outputdirectory.cpp:420 +msgid "" +"Output all converted files into the same directory as the original files" +msgstr "" +"Hacer salir todos los archivos convertidos en el mismo directorio que los " +"archivos originales" + +#: outputdirectory.cpp:434 +msgid "Output all converted files into the specified output directory" +msgstr "" +"Hacer salir todos los archivos convertidos en el directorio especificado" + +#: outputdirectory.cpp:448 +msgid "Copy the whole directory structure for all converted files" +msgstr "" +"Copiar la estructura entera del directorio para todos los archivos " +"convertidos" + +#: paranoia.cpp:214 +msgid "MB" +msgstr "MB" + +#: paranoia.cpp:215 +msgid "KB" +msgstr "KB" + +#: paranoia.cpp:216 +msgid "Bytes" +msgstr "Bytes" + +#: progressindicator.cpp:33 +msgid "Speed" +msgstr "Velocidad" + +#: progressindicator.cpp:41 +msgid "Time remaining" +msgstr "Tiempo restante" + +#: progressindicator.cpp:95 progressindicator.cpp:96 replaygainscanner.cpp:216 +msgid "Finished" +msgstr "Finalizado" + +#. i18n: file ./soundkonverterui.rc line 13 +#: rc.cpp:3 +#, no-c-format +msgid "&Conversion" +msgstr "&Conversión" + +#: replaygain.cpp:88 +msgid "Executing" +msgstr "Ejecutando" + +#: replaygainfilelist.cpp:137 replaygainfilelist.cpp:147 +#: replaygainfilelist.cpp:150 replaygainfilelist.cpp:180 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:669 +#: replaygainfilelist.cpp:672 replaygainfilelist.cpp:704 +#: replaygainfilelist.cpp:707 replaygainfilelist.cpp:734 +#: replaygainfilelist.cpp:737 replaygainfilelist.cpp:940 +msgid "Album" +msgstr "Álbum" + +#: replaygainfilelist.cpp:213 +msgid "Calculate Replay Gain tags" +msgstr "Calcular etiquetas Replay Gain" + +#: replaygainfilelist.cpp:214 +msgid "Remove Replay Gain tags" +msgstr "Eliminar etiquetas Replay Gain" + +#: replaygainfilelist.cpp:217 replaygainfilelist.cpp:825 +msgid "New album" +msgstr "Nuevo álbum" + +#: replaygainfilelist.cpp:218 +msgid "Open all albums" +msgstr "Abrir todos los álbumes" + +#: replaygainfilelist.cpp:219 +msgid "Cloase all albums" +msgstr "Cerrar todos los álbumes" + +#: replaygainfilelist.cpp:223 +msgid "" +"

Replay Gain Tool

With this tool you can add Replay " +"Gain tags to your audio files and remove them.
Replay Gain adds a volume " +"correction information to the files so that they can be played at an equal " +"volume level.
" +msgstr "" +"

Herramienta de Replay Gain

Con esta herramienta " +"puede agregar y quitar etiquetas de Replay Gain de sus archivos de " +"audio.
Replay Gain agrega información sobre el volumen de los archivos " +"para que cuando sean reproducidos el nivel de volumen sea siempre el " +"mismo.
" + +#: replaygainfilelist.cpp:494 +msgid "You can't place files of different formats in the same 'album'." +msgstr "" +"No puede colocar archivos con diferentes formatos en el mismo 'álbum'." + +#: replaygainfilelist.cpp:494 +msgid "Different file formats" +msgstr "Diferentes formatos de archivo" + +#: replaygainfilelist.cpp:987 +msgid "Removing Replay Gain" +msgstr "Quitando Replay Gain" + +#: replaygainfilelist.cpp:1148 +msgid "built-in" +msgstr "incorporado" + +#: replaygainscanner.cpp:33 replaygainscanner.cpp:216 +#: replaygainscanner.cpp:231 +msgid "Replay Gain Tool" +msgstr "Herramienta de Replay Gain" + +#: replaygainscanner.cpp:43 +msgid "Add Folder ..." +msgstr "Añadir Carpeta ..." + +#: replaygainscanner.cpp:44 +msgid "Add Files ..." +msgstr "Añadir Archivos ..." + +#: replaygainscanner.cpp:52 +msgid "Force recalculation" +msgstr "Forzar recalculación" + +#: replaygainscanner.cpp:53 +msgid "" +"Recalculate Replay Gain tag for files that already have a Replay Gain tag " +"set." +msgstr "" +"Recalcular la etiqueta de Replay Gain para aquellos archivos que ya tienen " +"una etiqueta de Replay Gain." + +#: replaygainscanner.cpp:102 +msgid "Tag untagged" +msgstr "Etiquetar" + +#: replaygainscanner.cpp:103 +msgid "" +"Calculate Replay Gain tag for all files in the file list without Replay Gain " +"tag." +msgstr "" +"Calcular la etiqueta de Replay Gain para todos los archivos de la lista que " +"no contengan la etiqueta de Replay Gain." + +#: replaygainscanner.cpp:109 +msgid "Untag tagged" +msgstr "Desetiquetar" + +#: replaygainscanner.cpp:110 +msgid "Remove the Replay Gain tag from all files in the file list." +msgstr "Quitar la etiqueta de Replay Gain de todos los archivos de la lista." + +#: replaygainscanner.cpp:151 +msgid "Choose files!" +msgstr "¡Elija los archivos!" + +#: soundkonverter.cpp:107 +msgid "Choose your prefered output options and click on \"Add files ...\"!" +msgstr "" +"¡Elija sus opciones de salida preferidas y pulse sobre \"Añadir archivos " +"...\"!" + +#: soundkonverter.cpp:110 soundkonverter.cpp:405 soundkonverter.cpp:448 +msgid "&Start conversion" +msgstr "&Iniciar conversión" + +#: soundkonverter.cpp:112 +msgid "&Replay Gain Tool ..." +msgstr "Herramienta de &Replay Gain ..." + +#: soundkonverter.cpp:114 +msgid "C&uesheet Editor ..." +msgstr "Editor C&uesheet ..." + +#: soundkonverter.cpp:115 +msgid "Show &Log ..." +msgstr "Mostrar &Registro ..." + +#: soundkonverter.cpp:118 +msgid "S&top after current file is complete" +msgstr "D&etener después de que el archivo actual sea completado" + +#: soundkonverter.cpp:119 +msgid "&Continue after current file is complete" +msgstr "&Continuar después de que el archivo actual sea completado." + +#: soundkonverter.cpp:120 +msgid "Stop &immediately" +msgstr "Detener &inmediatamente" + +#: soundkonverter.cpp:148 +msgid "A&dd Files ..." +msgstr "A&ñadir Archivos ..." + +#: soundkonverter.cpp:149 +msgid "Add &Folder ..." +msgstr "Añadir &Carpeta ..." + +#: soundkonverter.cpp:150 +msgid "Add CD &tracks ..." +msgstr "Añadir &Pistas de CD ..." + +#: soundkonverter.cpp:151 +msgid "Add &URL ..." +msgstr "Añadir &URL ..." + +#: soundkonverter.cpp:154 +msgid "L&oad file list" +msgstr "Cargar &lista de archivos" + +#: soundkonverter.cpp:155 +msgid "Sa&ve file list" +msgstr "&Guardar lista de archivos" + +#: soundkonverter.cpp:229 +msgid "Add files ..." +msgstr "Añadir archivos ..." + +#: soundkonverter.cpp:230 +msgid "Add folder ..." +msgstr "Añadir directorio ..." + +#: soundkonverter.cpp:231 +msgid "Add CD tracks ..." +msgstr "Añadir pistas de CD ..." + +#: soundkonverter.cpp:232 +msgid "Add URL ..." +msgstr "Añadir URL ..." + +#: soundkonverter.cpp:240 +msgid "Start" +msgstr "Iniciar" + +#: soundkonverter.cpp:417 +msgid "&Start queue" +msgstr "&Iniciar en cola" + +#: soundkonverter.cpp:489 +msgid "Choose files to convert" +msgstr "Elegir los archivos para convertir" + +#: soundkonverter.cpp:617 +msgid "Open URL" +msgstr "Abrir URL" + +#: soundkonverter.cpp:617 +msgid "Enter a URL:" +msgstr "Introduzca la URL:" diff --git a/po/fr.po b/po/fr.po new file mode 100644 index 0000000..0b1caa5 --- /dev/null +++ b/po/fr.po @@ -0,0 +1,1665 @@ +# translation of newfr.po to Français +# translation of fr.po to +# This file is put in the public domain. +# +# Daniel Faust , 2006, 2007. +# Placisfos , 2007. +# Vareille Yoann , 2007. +# Yoann Vareille , 2007. +msgid "" +msgstr "" +"Project-Id-Version: newfr\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-02-25 17:22+0100\n" +"PO-Revision-Date: 2008-03-22 20:13+0000\n" +"Last-Translator: Nicolas Velin \n" +"Language-Team: Français \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2008-04-06 10:52+0000\n" +"X-Generator: Launchpad (build Unknown)\n" + +#: _translatorinfo.cpp:1 +msgid "Your names" +msgstr "" +"Vareille Yoann,,Launchpad Contributions:,Goldy,Jean-Baptiste Gury,Nicolas " +"Velin,placisfos" + +#: _translatorinfo.cpp:3 +msgid "Your emails" +msgstr "" +"placisfos@gmail.com,,,goldy@goldenfish.info,jeanbaptiste.gury@gmail.com,nicol" +"as@velin.fr,placisfos@gmail.com" + +#: cddb.cpp:368 +msgid "No Title" +msgstr "Sans Titre" + +#: cddb.cpp:372 cdmanager.cpp:97 convert.cpp:513 convert.cpp:514 +#: convert.cpp:515 convert.cpp:517 convert.cpp:519 convert.cpp:520 +#: convert.cpp:1547 convert.cpp:1557 convert.cpp:1571 +#: replaygainfilelist.cpp:136 replaygainfilelist.cpp:137 +#: replaygainfilelist.cpp:144 replaygainfilelist.cpp:150 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:666 +#: replaygainfilelist.cpp:672 replaygainfilelist.cpp:701 +#: replaygainfilelist.cpp:707 replaygainfilelist.cpp:731 +#: replaygainfilelist.cpp:737 replaygainfilelist.cpp:945 +msgid "Unknown" +msgstr "Inconnu" + +#: cddb.cpp:380 +msgid "Track %1" +msgstr "Piste %1" + +#: cddb.cpp:479 +msgid "Searching local cddb entry ..." +msgstr "Recherche d'une entrée cddb locale..." + +#: cddb.cpp:504 +msgid "Searching remote cddb entry ..." +msgstr "Recherche d'une entrée cddb distante..." + +#: cddb.cpp:528 +msgid "Found exact match cddb entry ..." +msgstr "A trouvé le résultat de l'entrée exacte de cddb ..." + +#: cddb.cpp:585 +msgid "Found close cddb entry ..." +msgstr "A trouvé une entrée CDDB fermée ..." + +#: cddb.cpp:608 +msgid "CDDB Matches" +msgstr "Correspondances CDDB" + +#: cddb.cpp:608 +msgid "Several close CDDB entries found. Choose one:" +msgstr "Plusieurs entrées CDDB proches ont été trouvées. Choisissez :" + +#: cdmanager.cpp:46 filelist.cpp:618 +msgid "Audio CD" +msgstr "CD audio" + +#: cdmanager.cpp:46 +msgid "Several audio CDs found. Choose one:" +msgstr "Plusieurs CD audio ont été trouvés. Choisissez :" + +#: cdmanager.cpp:104 +msgid "No audio CD found." +msgstr "Aucun CD audio." + +#: cdopener.cpp:41 +msgid "Add CD tracks" +msgstr "Ajoutez des pistes" + +#: cdopener.cpp:52 cdopener.cpp:178 optionseditor.cpp:123 +msgid "Artist:" +msgstr "Artiste :" + +#: cdopener.cpp:57 cdopener.cpp:480 cdopener.cpp:485 cdopener.cpp:538 +#: cdopener.cpp:567 cdopener.cpp:682 cdopener.cpp:697 +msgid "Various Artists" +msgstr "Artistes divers" + +#: cdopener.cpp:66 cdopener.cpp:193 optionseditor.cpp:138 +msgid "Composer:" +msgstr "Compositeur :" + +#: cdopener.cpp:71 cdopener.cpp:496 cdopener.cpp:501 cdopener.cpp:548 +#: cdopener.cpp:579 cdopener.cpp:683 cdopener.cpp:698 +msgid "Various Composer" +msgstr "Compositeurs divers" + +#: cdopener.cpp:83 optionseditor.cpp:158 +msgid "Album:" +msgstr "Album :" + +#: cdopener.cpp:91 optionseditor.cpp:178 +msgid "Disc No.:" +msgstr "Disque n° :" + +#: cdopener.cpp:96 optionseditor.cpp:194 +msgid "Year:" +msgstr "Année :" + +#: cdopener.cpp:100 optionseditor.cpp:210 +msgid "Genre:" +msgstr "Style :" + +#: cdopener.cpp:114 cdopener.cpp:532 filelist.cpp:578 filelist.cpp:587 +#: replaygainfilelist.cpp:136 replaygainfilelist.cpp:141 +#: replaygainfilelist.cpp:144 replaygainfilelist.cpp:178 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:663 +#: replaygainfilelist.cpp:666 replaygainfilelist.cpp:698 +#: replaygainfilelist.cpp:701 replaygainfilelist.cpp:728 +#: replaygainfilelist.cpp:731 +msgid "Track" +msgstr "Piste" + +#: cdopener.cpp:115 cdopener.cpp:568 cdopener.cpp:571 cdopener.cpp:607 +msgid "Artist" +msgstr "Artiste" + +#: cdopener.cpp:116 cdopener.cpp:580 cdopener.cpp:583 cdopener.cpp:620 +msgid "Composer" +msgstr "Compositeur" + +#: cdopener.cpp:117 cdopener.cpp:594 +msgid "Title" +msgstr "Titre" + +#: cdopener.cpp:118 +msgid "Time" +msgstr "Durée" + +#: cdopener.cpp:131 +msgid "No track selected" +msgstr "Aucune piste n'est sélectionnée" + +#: cdopener.cpp:159 optionseditor.cpp:88 +msgid "Title:" +msgstr "Titre :" + +#: cdopener.cpp:212 optionseditor.cpp:235 +msgid "Comment:" +msgstr "Commentaires :" + +#: cdopener.cpp:242 +msgid "Save cuesheet ..." +msgstr "Sauvegarder le cuesheet ..." + +#: cdopener.cpp:250 +msgid "Add all tracks" +msgstr "Ajouter toutes les pistes" + +#: cdopener.cpp:251 +msgid "Add selected tracks" +msgstr "Ajouter les pistes sélectionnées" + +#: cdopener.cpp:253 +msgid "Add full CD as one file" +msgstr "Ajouter le CD entier en tant que fichier unique" + +#: cdopener.cpp:440 +msgid "All tracks" +msgstr "Toutes les pistes" + +#: cdopener.cpp:443 +msgid "Tracks" +msgstr "Pistes" + +#: cdopener.cpp:742 +msgid "" +"A file with this name already exists.\n" +"\n" +"Do you want to overwrite the existing one?" +msgstr "" +"Un fichier portant ce nom existe déjà.\n" +"\n" +"Souhaitez-vous le remplacer ?" + +#: cdopener.cpp:743 +msgid "File already exists" +msgstr "Le fichier existe déjà" + +#: config.cpp:103 config.cpp:104 config.cpp:1197 config.cpp:1206 +#: config.cpp:1237 configgeneralpage.cpp:37 configgeneralpage.cpp:60 +#: configgeneralpage.cpp:62 configgeneralpage.cpp:269 +#: configgeneralpage.cpp:273 configgeneralpage.cpp:297 +#: configgeneralpage.cpp:306 configgeneralpage.cpp:316 options.cpp:153 +#: optionsdetailed.cpp:363 optionssimple.cpp:49 optionssimple.cpp:221 +#: optionssimple.cpp:518 soundkonverter.cpp:308 soundkonverter.cpp:309 +msgid "Last used" +msgstr "Dernier utilisé" + +#: config.cpp:508 +msgid "Convert with soundKonverter ..." +msgstr "Convertir avec soundKonverter..." + +#: config.cpp:543 +msgid "Add Replay Gain with soundKonverter ..." +msgstr "Ajouter Replay Gain avec soundKonverter ..." + +#: config.cpp:1228 config.cpp:1229 configgeneralpage.cpp:57 +#: configgeneralpage.cpp:302 convert.cpp:431 filelist.cpp:1379 +#: optionsdetailed.cpp:361 optionsdetailed.cpp:427 optionsdetailed.cpp:477 +#: optionsdetailed.cpp:527 optionsdetailed.cpp:604 optionssimple.cpp:46 +#: optionssimple.cpp:140 optionssimple.cpp:180 optionssimple.cpp:218 +#: optionssimple.cpp:407 optionssimple.cpp:515 optionssimple.cpp:535 +msgid "Lossless" +msgstr "Sans perte" + +#: config.cpp:1232 config.cpp:1233 configgeneralpage.cpp:58 +#: configgeneralpage.cpp:312 convert.cpp:434 convert.cpp:1378 +#: filelist.cpp:1382 optionsdetailed.cpp:362 optionsdetailed.cpp:480 +#: optionsdetailed.cpp:618 optionssimple.cpp:47 optionssimple.cpp:141 +#: optionssimple.cpp:185 optionssimple.cpp:219 optionssimple.cpp:421 +#: optionssimple.cpp:430 optionssimple.cpp:516 optionssimple.cpp:544 +msgid "Hybrid" +msgstr "Hybride" + +#: config.cpp:1245 config.cpp:1252 config.cpp:1259 config.cpp:1266 +#: config.cpp:1273 convert.cpp:403 convert.cpp:995 convert.cpp:1567 +#: filelist.cpp:139 filelist.cpp:752 filelist.cpp:1270 filelist.cpp:1351 +#: optionsdetailed.cpp:246 optionsdetailed.cpp:467 optionsdetailed.cpp:582 +#: optionsdetailed.cpp:641 optionssimple.cpp:38 optionssimple.cpp:283 +#: optionssimple.cpp:312 optionssimple.cpp:340 optionssimple.cpp:367 +#: optionssimple.cpp:394 +msgid "Quality" +msgstr "Qualité" + +#: config.cpp:1248 config.cpp:1285 convert.cpp:450 filelist.cpp:1398 +#: optionsdetailed.cpp:538 optionssimple.cpp:294 +msgid "Mono" +msgstr "Mono" + +#: config.cpp:1250 config.cpp:1287 configgeneralpage.cpp:52 +#: configgeneralpage.cpp:289 optionsdetailed.cpp:356 optionssimple.cpp:41 +#: optionssimple.cpp:135 optionssimple.cpp:155 optionssimple.cpp:213 +#: optionssimple.cpp:269 optionssimple.cpp:510 optionssimple.cpp:525 +msgid "Very low" +msgstr "Très basse" + +#: config.cpp:1257 config.cpp:1294 configgeneralpage.cpp:53 +#: configgeneralpage.cpp:111 configgeneralpage.cpp:290 optionsdetailed.cpp:357 +#: optionssimple.cpp:42 optionssimple.cpp:136 optionssimple.cpp:160 +#: optionssimple.cpp:214 optionssimple.cpp:298 optionssimple.cpp:511 +#: optionssimple.cpp:525 +msgid "Low" +msgstr "Basse" + +#: config.cpp:1264 config.cpp:1301 configgeneralpage.cpp:54 +#: configgeneralpage.cpp:291 optionsdetailed.cpp:358 optionseditor.cpp:713 +#: optionssimple.cpp:43 optionssimple.cpp:137 optionssimple.cpp:165 +#: optionssimple.cpp:215 optionssimple.cpp:326 optionssimple.cpp:512 +#: optionssimple.cpp:526 +msgid "Medium" +msgstr "Moyenne" + +#: config.cpp:1271 config.cpp:1308 configgeneralpage.cpp:55 +#: configgeneralpage.cpp:292 optionsdetailed.cpp:359 optionssimple.cpp:44 +#: optionssimple.cpp:138 optionssimple.cpp:170 optionssimple.cpp:216 +#: optionssimple.cpp:353 optionssimple.cpp:513 optionssimple.cpp:526 +msgid "High" +msgstr "Haute" + +#: config.cpp:1278 config.cpp:1315 configgeneralpage.cpp:56 +#: configgeneralpage.cpp:293 optionsdetailed.cpp:360 optionssimple.cpp:45 +#: optionssimple.cpp:139 optionssimple.cpp:175 optionssimple.cpp:217 +#: optionssimple.cpp:380 optionssimple.cpp:514 optionssimple.cpp:527 +msgid "Very high" +msgstr "Très haute" + +#: config.cpp:1282 config.cpp:1289 config.cpp:1296 config.cpp:1303 +#: config.cpp:1310 convert.cpp:387 convert.cpp:996 convert.cpp:997 +#: convert.cpp:1568 convert.cpp:1569 filelist.cpp:1234 filelist.cpp:1245 +#: filelist.cpp:1255 filelist.cpp:1335 optionsdetailed.cpp:246 +#: optionsdetailed.cpp:470 optionsdetailed.cpp:560 optionssimple.cpp:287 +#: optionssimple.cpp:316 optionssimple.cpp:344 optionssimple.cpp:371 +#: optionssimple.cpp:398 +msgid "Bitrate" +msgstr "Bitrate" + +#: config.cpp:1351 optionsdetailed.cpp:365 optionssimple.cpp:51 +#: optionssimple.cpp:142 optionssimple.cpp:190 optionssimple.cpp:223 +#: optionssimple.cpp:435 optionssimple.cpp:454 optionssimple.cpp:458 +#: optionssimple.cpp:468 optionssimple.cpp:472 optionssimple.cpp:520 +#: optionssimple.cpp:552 +msgid "User defined" +msgstr "Définie par l'utilisateur" + +#: config.cpp:1394 config.cpp:1407 config.cpp:1411 config.cpp:1457 +#: config.cpp:1461 +msgid "files" +msgstr "fichiers" + +#: config.cpp:1419 config.cpp:1469 +msgid "all supported formats" +msgstr "tous formats supportés" + +#: config.cpp:1419 config.cpp:1469 +msgid "all formats" +msgstr "tous formats" + +#: configbackendspage.cpp:42 +msgid "Legend" +msgstr "Légende" + +#: configbackendspage.cpp:45 +msgid "Full support" +msgstr "Support complet" + +#: configbackendspage.cpp:48 +msgid "Most supported" +msgstr "Généralement supporté" + +#: configbackendspage.cpp:51 +msgid "Basic support" +msgstr "Support basique" + +#: configbackendspage.cpp:57 +msgid "CD Ripper" +msgstr "Extracteur de CD" + +#: configbackendspage.cpp:243 +msgid "Encoder" +msgstr "Encoder" + +#: configbackendspage.cpp:256 +msgid "Strength" +msgstr "Force" + +#: configbackendspage.cpp:263 +msgid "" +"Set the compression strength:\n" +"\n" +"Left = fast conversion\n" +"Right = good resultant file" +msgstr "" +"Choisissez la qualité de compression :\n" +"\n" +"Gauche = rapide\n" +"Droite = meilleur résultat" + +#: configbackendspage.cpp:272 +msgid "Decoder" +msgstr "Décodeur" + +#: configbackendspage.cpp:286 convert.cpp:593 convert.cpp:1580 +#: optionsdetailed.cpp:168 +msgid "Replay Gain" +msgstr "Replay Gain" + +#: configbackendspage.cpp:295 +msgid "Use internal Replay Gain" +msgstr "Utiliser le Replay Gain interne" + +#: configbackendspage.cpp:296 +msgid "Use the internal Replay Gain calculator of the encoder" +msgstr "Utiliser le calculateur Replay Gain interne de l'encodeur" + +#: configbackendspage.cpp:320 +msgid "KDE audio CD protocol" +msgstr "KDE Audio CD Protocole" + +#: configdialog.cpp:31 +msgid "Settings" +msgstr "Paramètres" + +#: configdialog.cpp:56 +msgid "General" +msgstr "Général" + +#: configdialog.cpp:68 +msgid "Plugins" +msgstr "Plugins" + +#: configdialog.cpp:80 +msgid "Environment" +msgstr "Environnement" + +#: configdialog.cpp:92 +msgid "Backends" +msgstr "Backends" + +#: configenvironmentpage.cpp:32 +msgid "Directories to be scanned" +msgstr "Répertoires à analyser" + +#: configenvironmentpage.cpp:50 +msgid "" +"Move selected directory one position up.\n" +"This effects which backend will be chosen, if there are several versions." +msgstr "" +"Déplacer le dossier sélectionné d'une position vers le haut.\n" +"Ceci définit quel backend sera choisi, s'il y a plusieurs versions." + +#: configenvironmentpage.cpp:60 +msgid "" +"Move selected directory one position down.\n" +"This effects which backend will be chosen, if there are several versions." +msgstr "" +"Déplacer le dossier sélectionné d'une position vers le bas.\n" +"Ceci définit quel backend sera choisi, s'il y a plusieurs versions." + +#: configenvironmentpage.cpp:67 configpluginspage.cpp:50 +msgid "Add ..." +msgstr "Ajoutez..." + +#: configenvironmentpage.cpp:87 +msgid "Programs found" +msgstr "Programmes trouvés" + +#: configenvironmentpage.cpp:96 +msgid "Programs not found" +msgstr "Programmes non trouvés" + +#: configgeneralpage.cpp:34 +msgid "Start in Mode" +msgstr "Commencer en Mode" + +#: configgeneralpage.cpp:38 options.cpp:36 +msgid "Simple" +msgstr "Basique" + +#: configgeneralpage.cpp:39 options.cpp:41 +msgid "Detailed" +msgstr "Détaillé" + +#: configgeneralpage.cpp:49 +msgid "Default profile" +msgstr "Profil par défaut" + +#: configgeneralpage.cpp:72 +msgid "Default format" +msgstr "Format par défaut" + +#: configgeneralpage.cpp:107 +msgid "Process priority of the backends" +msgstr "Priorité de processus des backends" + +#: configgeneralpage.cpp:110 +msgid "Normal" +msgstr "Normal" + +#: configgeneralpage.cpp:122 +msgid "Use FAT compatible output file names" +msgstr "Utilisez un nom de fichier compatible avec le système FAT" + +#: configgeneralpage.cpp:123 +msgid "Replaces some special characters like '?' by '_'." +msgstr "Remplacer certains caractères comme '?' par '_'." + +#: configgeneralpage.cpp:133 +msgid "Conflict handling" +msgstr "" + +#: configgeneralpage.cpp:136 +msgid "Do that if the output file already exists" +msgstr "" + +#: configgeneralpage.cpp:137 +msgid "Generate new file name" +msgstr "" + +#: configgeneralpage.cpp:138 +msgid "Skip file" +msgstr "" + +#: configgeneralpage.cpp:149 +msgid "Number of files to convert at once" +msgstr "Nombre de fichiers à convertir d'un coups" + +#: configgeneralpage.cpp:160 +msgid "Status update delay (time in msec.)" +msgstr "Statut du délai de mise à jour (temps en ms.)" + +#: configgeneralpage.cpp:163 +msgid "Update the progress bar in this interval (time in milliseconds)" +msgstr "" +"Rafraichir la bar de progression à cet intervalle (valeur en millisecondes)" + +#: configgeneralpage.cpp:172 +msgid "Ask for new options, when adding files from external program" +msgstr "" +"Demander pour de nouvelles options, lors de l'ajout de fichiers depuis un " +"programme externe" + +#: configgeneralpage.cpp:173 +msgid "" +"If you open a file with soundKonverter and soundKonverter is already " +"running,\n" +"you can either be asked to define new converting options\n" +"or the current settings from the soundKonverter main window are used." +msgstr "" +"Si vous ouvrez un fichier avec soundKonverter et que soundKonverter est déjà " +"en fonctionnement,\n" +"vous pouvez être amené à définir de nouvelles options de conversion,\n" +"ou choisir celles déjà en cours dans la fenêtre principale." + +#: configgeneralpage.cpp:183 +msgid "Execute user script (for advanced users)" +msgstr "" + +#: configgeneralpage.cpp:184 +msgid "" +"Executes a script after every finished conversion. Have a look at " +"$KDEDIR/soundkonverter/userscript.sh" +msgstr "" + +#: configpluginspage.cpp:39 +msgid "Installed plugins" +msgstr "Plugins installés" + +#: configpluginspage.cpp:228 +msgid "*.soundkonverter.xml|Plugins (*.soundkonverter.xml)" +msgstr "*.soundkonverter.xml|Plugins (*.soundkonverter.xml)" + +#: configpluginspage.cpp:228 +msgid "Choose a plugin to add!" +msgstr "Choisissez un plugin à ajouter !" + +#: configpluginspage.cpp:253 configpluginspage.cpp:546 +msgid "" +"The plugin could not be installed. Please ensure that you have selected a " +"valid soundKonverter plugin file." +msgstr "" +"Ce plugins ne peut être installé. Vérifiez d'avoir bien sélectionné un " +"plugin soundKonverter valide." + +#: configpluginspage.cpp:254 configpluginspage.cpp:294 +#: configpluginspage.cpp:547 configpluginspage.cpp:587 +msgid "Error while installing plugin" +msgstr "Erreur lors de l'installation du plugin." + +#: configpluginspage.cpp:279 configpluginspage.cpp:572 +msgid "" +"The plugin was installed successfully. Please restart soundKonverter in " +"order to activate it." +msgstr "" +"Le plugin a été installé. Veuillez relancer soudKonverter pour l'activer." + +#: configpluginspage.cpp:280 configpluginspage.cpp:573 +msgid "Plugin successfully installed" +msgstr "Plugin installé." + +#: configpluginspage.cpp:293 configpluginspage.cpp:586 +msgid "" +"The plugin could not be installed. Please ensure that you have write " +"permission on your whole user directory." +msgstr "" +"Ce plugin n'a pas été installé. Veuillez vous assurer que vous avez la " +"permission d'écriture complète dans votre dossier personnel." + +#: configpluginspage.cpp:311 configpluginspage.cpp:330 +#: configpluginspage.cpp:349 +msgid "" +"The plugin was removed successfully. Please restart soundKonverter in order " +"to deactivate it." +msgstr "" +"Le plugin a été correctement désinstallé. Veuillez relancer soundKonverter " +"pour le désactiver." + +#: configpluginspage.cpp:312 configpluginspage.cpp:331 +#: configpluginspage.cpp:350 +msgid "Plugin successfully removed" +msgstr "Plugin correctement désinstallé." + +#: configpluginspage.cpp:316 configpluginspage.cpp:335 +#: configpluginspage.cpp:354 +msgid "" +"The plugin could not be removed. Please ensure that you have write " +"permission on your whole user directory." +msgstr "" +"Ce plugin n'a pas été désinstallé. Veuillez vous assurer que vous avez la " +"permission d'écriture complète dans votre dossier personnel." + +#: configpluginspage.cpp:317 configpluginspage.cpp:336 +#: configpluginspage.cpp:355 +msgid "Error while removing plugin" +msgstr "Erreur lors de la désinstallation du plugin" + +#: configpluginspage.cpp:383 configpluginspage.cpp:395 +#: configpluginspage.cpp:407 +msgid "Version" +msgstr "Version" + +#: configpluginspage.cpp:384 configpluginspage.cpp:396 +#: configpluginspage.cpp:408 +msgid "Author" +msgstr "Auteur" + +#: configpluginspage.cpp:417 configpluginspage.cpp:472 +msgid "No new plugins available!" +msgstr "Il n'y a pas de nouveaux plugins de disponible !" + +#: configpluginspage.cpp:477 +msgid "" +"The plugin list could not be downloaded. Please ensure, that your internet " +"connection works correct.\n" +"Maybe our server is busy at the moment, please try it again later." +msgstr "" +"La liste des plugins n'a pas pu être téléchargé. Veuillez vérifier l'état de " +"votre connexion internet." + +#: configpluginspage.cpp:478 +msgid "Error while loading plugin list" +msgstr "Erreur lors du chargement de la liste des plugins." + +#: configpluginspage.cpp:626 configpluginspage.cpp:632 +msgid "" +"The plugin info could not be downloaded. Please ensure, that your internet " +"connection works correctly." +msgstr "" +"Les informations sur le plugin ne peuvent pas être téléchargés. Veuillez " +"vérifier l'état de votre connexion internet." + +#: configpluginspage.cpp:627 configpluginspage.cpp:633 +msgid "Error while loading plugin info" +msgstr "Erreur lors du chargement des informations sur le plugin" + +#: convert.cpp:83 convert.cpp:86 convert.cpp:1538 +msgid "Getting file" +msgstr "Obtention du fichier" + +#: convert.cpp:86 convert.cpp:130 convert.cpp:190 convert.cpp:260 +#: convert.cpp:314 convert.cpp:555 convert.cpp:593 convert.cpp:603 +#: convert.cpp:617 convert.cpp:661 convert.cpp:694 convert.cpp:1538 +#: convert.cpp:1542 convert.cpp:1547 convert.cpp:1551 convert.cpp:1557 +#: convert.cpp:1561 convert.cpp:1571 convert.cpp:1575 convert.cpp:1580 +#: convert.cpp:1583 convert.cpp:1587 filelist.cpp:136 filelist.cpp:638 +#: filelist.cpp:641 filelist.cpp:650 filelist.cpp:651 filelist.cpp:696 +#: filelist.cpp:726 filelist.cpp:729 filelist.cpp:733 filelist.cpp:860 +#: filelist.cpp:861 filelist.cpp:918 filelist.cpp:955 filelist.cpp:956 +msgid "State" +msgstr "État" + +#: convert.cpp:116 convert.cpp:130 convert.cpp:1542 +msgid "Getting correction file" +msgstr "Obtention de la correction du fichier" + +#: convert.cpp:122 +msgid "Aborting, file does not exist" +msgstr "Abandon, le fichier n'existe pas." + +#: convert.cpp:157 convert.cpp:190 convert.cpp:260 convert.cpp:1547 +#: convert.cpp:1551 +msgid "Ripping" +msgstr "Encodage" + +#: convert.cpp:270 convert.cpp:314 convert.cpp:1557 convert.cpp:1561 +msgid "Decoding" +msgstr "Décodage" + +#: convert.cpp:334 convert.cpp:555 convert.cpp:1571 convert.cpp:1575 +msgid "Encoding" +msgstr "Encodage" + +#: convert.cpp:453 filelist.cpp:1401 optionsdetailed.cpp:541 +msgid "Stereo" +msgstr "Stéréo" + +#: convert.cpp:456 filelist.cpp:1404 optionsdetailed.cpp:544 +msgid "Joint-Stereo" +msgstr "Stéréo-Joint" + +#: convert.cpp:459 filelist.cpp:1407 optionsdetailed.cpp:547 +msgid "Forced Joint-Stereo" +msgstr "Stéréo jointe forcée" + +#: convert.cpp:462 filelist.cpp:1410 optionsdetailed.cpp:550 +msgid "Dual Channels" +msgstr "Double Canaux" + +#: convert.cpp:563 replaygainfilelist.cpp:914 +msgid "Applying Replay Gain" +msgstr "Appliquer Replay Gain" + +#: convert.cpp:598 convert.cpp:603 +msgid "Writing tags" +msgstr "Ecriture des tags" + +#: convert.cpp:611 convert.cpp:617 convert.cpp:1583 +msgid "Moving file" +msgstr "Déplacement du fichier" + +#: convert.cpp:649 convert.cpp:661 convert.cpp:1587 +msgid "Moving correction file" +msgstr "Déplacement de la correction des fichiers" + +#: convert.cpp:688 convert.cpp:694 +msgid "Running user script" +msgstr "" + +#: convert.cpp:713 +msgid "Executing next step" +msgstr "Lancement de l'étape suivante" + +#: convert.cpp:857 convert.cpp:874 convert.cpp:1123 convert.cpp:1147 +msgid "Got file" +msgstr "Obtention du fichier" + +#: convert.cpp:891 convert.cpp:1204 convert.cpp:1216 +msgid "Could not write to file: `%1'" +msgstr "Impossible d'écrire vers le fichier : `%1'" + +#: convert.cpp:903 convert.cpp:918 convert.cpp:1228 convert.cpp:1255 +msgid "File moved" +msgstr "Fichier déplacé" + +#: convert.cpp:941 filelist.cpp:70 filelist.cpp:138 filelist.cpp:750 +#: outputdirectory.cpp:39 replaygainfilelist.cpp:1141 +msgid "Output" +msgstr "Sortie" + +#: convert.cpp:1292 +msgid "Adding new item to conversion list: `%1'" +msgstr "" + +#: convert.cpp:1299 +msgid "Got log ID: %1" +msgstr "Obtention du Log ID: %1" + +#: convert.cpp:1302 +msgid "Tags successfully read" +msgstr "Tags luent avec succès" + +#: convert.cpp:1303 +msgid "Reading tags failed" +msgstr "Erreur lors de la lecture des tags" + +#: convert.cpp:1443 convert.cpp:1453 replaygainfilelist.cpp:1025 +msgid "Killing process ..." +msgstr "Tue le processus..." + +#: convert.cpp:1446 replaygainfilelist.cpp:1028 +msgid "Killing process failed. Stopping after files are completed ..." +msgstr "Fin du processus échoué. Arrêt après la conversion des fichiers ..." + +#: convert.cpp:1468 +msgid "Removing file from conversion list. Exit code %1" +msgstr "" +"Effacement du fichier depuis la liste de conversion. Code de sortie %1" + +#: convert.cpp:1475 +msgid "Executing command: \"%1\"" +msgstr "Execution de la commande : \"%1\"" + +#: cuesheeteditor.cpp:29 +msgid "Cuesheet Editor" +msgstr "Editeur de la file d'attente" + +#: cuesheeteditor.cpp:76 +msgid "Generate" +msgstr "Génère" + +#: cuesheeteditor.cpp:82 +msgid "Format" +msgstr "Format" + +#: cuesheeteditor.cpp:88 +msgid "Shift Title/Performer" +msgstr "Décaler Titre/Interprète" + +#: cuesheeteditor.cpp:113 +msgid "" +"

With this small tool you can process cue files as they are used for " +"burning music mixes and for organizing them in media players like " +"amaroK.

You can generate a new file by pasting text into the input " +"area. It must be formated the following way:

Title - Artist " +"[time]
Title - Artist [3:25]
Title - Artist [2:37]
...
A tip: " +"Use kwrite and regular expressions to format it this way.

" +msgstr "" +"

Avec ce petit outil vous pouvez traiter les dossiers sélectionnés comme " +"s'ils étaient utilisés pour graver les mixs de musique et pour les organiser " +"dans les lecteurs multimédia comme AmaroK.

Vous pouvez créer un " +"nouveau dossier en collant le texte dans la zone d'entrée. Il doit être " +"formaté de la manière suivante:

Titre - Artiste [time]
Titre - " +"Artiste [3:25]
Titre - Artiste [2:37]
...
Astuce: Utilisez KWrite " +"et des expressions communes pour formater ce chemin.

" + +#: cuesheeteditor.cpp:114 +msgid "Cuesheet Editor - Help" +msgstr "Cuesheet Editor - Hilfe" + +#: dirdialog.cpp:24 +msgid "Add folder" +msgstr "Ajouter un dossier" + +#: dirdialog.cpp:33 +msgid "Directory:" +msgstr "Répertoire:" + +#: dirdialog.cpp:63 +msgid "Select all" +msgstr "Tout sélectionner" + +#: dirdialog.cpp:69 +msgid "Select none" +msgstr "Ne rien sélectionner" + +#: dirdialog.cpp:75 +msgid "Recursive" +msgstr "" + +#: dirdialog.cpp:106 dirdialog.cpp:133 +msgid "Choose a directory" +msgstr "Choisir un dossier" + +#: filelist.cpp:70 filelist.cpp:137 filelist.cpp:736 filelist.cpp:737 +msgid "Input" +msgstr "Entrée" + +#: filelist.cpp:170 +msgid "Edit options ..." +msgstr "Editer les options ..." + +#: filelist.cpp:171 +msgid "Start conversion" +msgstr "Démarrer la conversion" + +#: filelist.cpp:172 +msgid "Stop conversion" +msgstr "Arrêtez la conversion" + +#: filelist.cpp:184 +msgid "" +"

File List

Select your desired output options in " +"the form above and add some files.
You can add files by clicking on " +"\"Add files ...\" or dropping them here.
" +msgstr "" +"

Liste de fichiers

Sélectionnez vos préférences de " +"sortie et ajoutez des fichiers
Vous pouvez ajouter des fichiers en " +"cliquant sur \"Ajouter des fichiers...\" ou en les y déposant.
" + +#: filelist.cpp:578 filelist.cpp:593 +msgid "Audio CD (%1)" +msgstr "CD audio (%1)" + +#: filelist.cpp:609 filelist.cpp:624 +msgid "Full audio CD (%1)" +msgstr "CD Audio complet(%1)" + +#: filelist.cpp:638 filelist.cpp:650 filelist.cpp:955 +msgid "Stopped" +msgstr "Arrêté" + +#: filelist.cpp:641 filelist.cpp:650 filelist.cpp:955 +msgid "Failed" +msgstr "Echecs" + +#: filelist.cpp:650 filelist.cpp:726 filelist.cpp:860 filelist.cpp:955 +msgid "Will be skipped" +msgstr "" + +#: filelist.cpp:651 filelist.cpp:696 filelist.cpp:729 filelist.cpp:861 +#: filelist.cpp:918 filelist.cpp:956 progressindicator.cpp:49 +msgid "Waiting" +msgstr "Veuillez patienter" + +#: filelist.cpp:733 +msgid "Converting" +msgstr "Conversion" + +#: logger.cpp:136 +msgid "Finished logging" +msgstr "Notation finie" + +#: logviewer.cpp:83 +msgid "Log Viewer" +msgstr "Visionneur de journal" + +#: logviewer.cpp:90 +msgid "Job/File" +msgstr "Travail/Fichiers" + +#: main.cpp:12 +msgid "" +"soundKonverter is a frontend to various sound en- and decoding programs." +msgstr "" +"soundKonverter est une interface graphique à divers programmes " +"d'encodage/décodage." + +#: main.cpp:18 +msgid "Open the Replay Gain tool an add all given files" +msgstr "Ouvrir l'outil ReplayGain et ajouter tous les fichiers sélectionnés." + +#: main.cpp:20 +msgid "List all tracks on the cd drive , 'auto' will search for a cd" +msgstr "" +"Lister toutes les pistes sur le lecteur CD 'auto' va rechercher la " +"présence d'un CD" + +#: main.cpp:21 +msgid "Add all files using the given profile" +msgstr "Ajouter tous les fichiers en utilisant le profil donné" + +#: main.cpp:22 +msgid "Add all files using the given format" +msgstr "Ajouter tous les fichiers en utilisant le format donné" + +#: main.cpp:23 +msgid "Output all files to " +msgstr "Extraire tous les fichiers vers " + +#: main.cpp:24 +msgid "Start soundKonverter invisible" +msgstr "Démarrer soundKonverter caché" + +#: main.cpp:25 +msgid "" +"Close soundKonverter after all files are converted (enabled when using '--" +"invisible')" +msgstr "" +"Fermer soundKonverter après la conversion de tous les fichiers (Permis " +"pendant l'utilisation du mode '--invisible')" + +#: main.cpp:26 +msgid "Execute after each file has been converted" +msgstr "Exécuter après que chaque fichier ait été converti" + +#: main.cpp:27 +msgid "Audio file(s) to append to the file list" +msgstr "Fichier(s) audio à apposer à la liste de fichier" + +#: main.cpp:33 +msgid "soundKonverter" +msgstr "soundKonverter" + +#: options.cpp:127 +msgid "" +"soundKonverter either found new backends or misses some.\n" +"Click on this button in order to open the configuration dialog." +msgstr "" +"soundKonverter a soit trouvé de nouveaux backends, soit en a perdu " +"certains.\n" +"Cliquez sur ce bouton afin d'ouvrir la boite de configuration." + +#: options.cpp:136 +msgid "Advanced Options" +msgstr "Options avancées" + +#: optionsdetailed.cpp:45 +msgid "Convert" +msgstr "Convertir" + +#: optionsdetailed.cpp:73 +msgid "" +"vbr - variable bitrate\n" +"abr - average bitrate\n" +"cbr - constant bitrate" +msgstr "" +"vbr - Bitrate variable\n" +"abr - Bitrate moyen\n" +"cbr - Bitrate contant" + +#: optionsdetailed.cpp:83 +msgid "Bitrate range" +msgstr "Gamme de débit" + +#: optionsdetailed.cpp:84 +msgid "" +"Use it only if, you know what you are doing, you could reduce the quality." +msgstr "" +"Utilisez ceci seulement si vous savez ce que vous faites car vous pouvez " +"réduire" + +#: optionsdetailed.cpp:119 +msgid "Resample" +msgstr "Resample" + +#: optionsdetailed.cpp:147 +msgid "Channels" +msgstr "Canaux" + +#: optionsdetailed.cpp:170 +msgid "Add a Replay Gain tag to the converted file." +msgstr "Ajouter un tag Replay Gain au fichier converti." + +#: optionsdetailed.cpp:171 +msgid "" +"Replay Gain is a volume correction technique. A volume difference is " +"calculated and stored in a tag. This way audio players can automatically " +"adjust the volume and the original music data is not modified (like at " +"normalization)." +msgstr "" +"Replay Gain est une technique de correction du volume.Une différence de " +"volume est calculée et stocké dans un tag. Les lecteurs audio compatibles " +"peuvent ajuster automatiquement le volume, ainsi les données du fichier ne " +"sont pas modifiée (contrairement à une normalisation)." + +#: optionsdetailed.cpp:192 +msgid "Save current options as a profile" +msgstr "Sauver les options courantes dans un profil" + +#: optionsdetailed.cpp:208 +msgid "Command" +msgstr "Commande" + +#: optionsdetailed.cpp:219 +#, c-format +msgid "%p: The parameters generated by soundKonverter" +msgstr "%p: Les paramètres générés par soundKonverter" + +#: optionsdetailed.cpp:225 +#, c-format +msgid "%i: The input file ; %o: The output file" +msgstr "%i: Le fichier d'entrée ; %o: Le fichier de sortie" + +#: optionsdetailed.cpp:353 +msgid "New profile" +msgstr "Nouveau profil" + +#: optionsdetailed.cpp:353 +msgid "Enter a name for the new profile:" +msgstr "Entrez un nom pour ce nouveau profil" + +#: optionsdetailed.cpp:368 +msgid "You cannot overwrite the built-in profiles." +msgstr "Il est impossible d'écraser les profils intégrés." + +#: optionsdetailed.cpp:369 optionsdetailed.cpp:379 +msgid "Profile already exists" +msgstr "Ce profil existe déjà." + +#: optionsdetailed.cpp:378 +msgid "" +"A profile with this name already exists.\n" +"\n" +"Do you want to overwrite the existing one?" +msgstr "" +"Un profil avec ce nom existe déjà.\n" +"\n" +"Souhaitez-vous le remplacer ?" + +#: optionsdetailed.cpp:473 optionsdetailed.cpp:628 +msgid "Unchanged" +msgstr "Non modifié" + +#: optionsdetailed.cpp:483 optionsdetailed.cpp:604 +msgid "Undefined" +msgstr "Non défini" + +#: optionsdetailed.cpp:561 optionsdetailed.cpp:619 +msgid "Kilobit per second" +msgstr "Kilobit par secondes" + +#: optionsdetailed.cpp:689 +msgid "" +"This is a relative quality between 0 and 100.\n" +"The higher this number the higher is the quality.\n" +"soundKonverter will convert it into the file format's quality format.\n" +"See the \"What's this?\" for more informations.\n" +"\n" +"Current parameter: \"%1\"" +msgstr "" +"Ceci est une qualité relative entre 0 et 100.\n" +"Le nombre le plus élevé correspond à la qualité la plus élevée.\n" +"soundKonverter le convertira dans le format de la qualité du format de " +"fichier.\n" +"Veuillez regarder \"Qu'est-ce que c'est?\" pour plus d'informations.\n" +"\n" +"Paramètres courants: \"%1\"" + +#: optionseditor.cpp:28 +msgid "Options Editor" +msgstr "Editeur d'options" + +#: optionseditor.cpp:55 +msgid "Conversion" +msgstr "Conversion" + +#: optionseditor.cpp:55 +msgid "Conversion options" +msgstr "Options de conversion" + +#: optionseditor.cpp:59 +msgid "Choose your prefered output options and click on \"Close\"!" +msgstr "Choisissez vos options de sortie préférés et cliquez sur \"Fermer\"!" + +#: optionseditor.cpp:70 +msgid "Edit conversion options" +msgstr "Éditer les options de conversion" + +#: optionseditor.cpp:79 +msgid "Tags" +msgstr "Tags" + +#: optionseditor.cpp:103 +msgid "Track No.:" +msgstr "Piste N°.:" + +#: optionseditor.cpp:256 +msgid "Edit tags" +msgstr "Éditer les tags" + +#: optionseditor.cpp:330 +msgid "No file selected" +msgstr "Aucun fichier sélectionné" + +#: optionseditor.cpp:358 +msgid "" +"The tags could not be read, because this file isn't a local one.\n" +"soundKonverter will try to read the tags, when it is about to convert the " +"file.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags." +msgstr "" +"Les tags ne peuvent-être lus, car ce fichier n'est pas un fichier local.\n" +"soundKonverter essaiera de lire les tags, lors de la conversion du fichier.\n" +"Pour éditer les tags, appuyer sur le bouton ci-dessous mais alors " +"soundKonverter n'essaiera pas\n" +". de lire les tags." + +#: optionseditor.cpp:367 +msgid "" +"Reading the tags of this file failed.\n" +"soundKonverter will try to read the tags a second time, when it is about to " +"convert the file.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags a second time." +msgstr "" +"La lecture des tags de ce fichier à échoué.\n" +"soundKonverter essaiera de lire les tags une seconde fois lors de la " +"conversion du fichier.\n" +"Pour éditer les tags, appuyer sur le bouton ci-dessous mais alors " +"soundKonverter n'essaiera pas\n" +". de lire les tags une seconde fois." + +#: optionseditor.cpp:387 +msgid "%1 Files" +msgstr "%1 Fichiers" + +#: optionseditor.cpp:402 +msgid "" +"You have selected multiple files with different conversion options.\n" +"You can change the options of all files by hitting the button below." +msgstr "" +"Vous avez sélectionné de multiples fichiers avec des options de conversion " +"différentes.\n" +"Vous pouvez changer les options de tous les fichiers en .appuyant sur le " +"bouton ci-dessous." + +#: optionseditor.cpp:408 +msgid "" +"Reading the tags of one or more files failed.\n" +"soundKonverter will try to read the tags a second time, when it is about to " +"convert the files.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags a second time." +msgstr "" +"La lecture des tags d'un fichier ou plus à échoué.\n" +"soundKonverter essaiera de lire les tags une seconde fois lors de la " +"conversion du fichier.\n" +"Pour éditer les tags, appuyer sur le bouton ci-dessous mais alors " +"soundKonverter n'essaiera pas\n" +". de lire les tags une seconde fois." + +#: optionsrequester.cpp:18 +msgid "Choose output options" +msgstr "Choisir les options de sortie" + +#: optionsrequester.cpp:28 +msgid "Click on \"Ok\" to add the files to the list in the main window!" +msgstr "" +"Cliquer sur \"Ok\" pour ajouter les fichiers à la liste dans la fenêtre " +"principale!" + +#: optionsrequester.cpp:43 +msgid "" +"Warning: If you select \"wav\" as output format, your wav files will not be " +"added to the list." +msgstr "" +"Attention: si vous sélectionnez \"wav\" comme format de sortie, vos fichiers " +"wav ne seront pas ajoutés à la liste." + +#: optionsrequester.cpp:59 +msgid "Ok" +msgstr "Ok" + +#: optionssimple.cpp:64 +msgid "Remove the selected profile" +msgstr "Supprimer le profil sélectionné" + +#: optionssimple.cpp:70 optionssimple.cpp:90 +msgid "Info" +msgstr "Info" + +#: optionssimple.cpp:71 +msgid "Information about the selected profile" +msgstr "Informations à propos du profil sélectionné" + +#: optionssimple.cpp:78 +msgid "Output format" +msgstr "Format de sortie" + +#: optionssimple.cpp:91 +msgid "Information about the selected file format" +msgstr "Informations à propos du format de fichier sélectionné" + +#: optionssimple.cpp:157 +msgid "" +"This produces sound files of a very low quality.\n" +"That can be useful, if you have a mobile device, where your memory cell is " +"limited. It is not recommended to save your music in this quality without a " +"copy with higher quality.\n" +"It can also be used to save audio files with voices." +msgstr "" +"Ceci produit un fichier son de très basse qualité.\n" +"Celà peut-être utile, si vous avez un appareil mobile, dans lequel votre " +"mémoire est limitée.\n" +"Il n'est pas recommandé d'enregistrer votre musique dans cette qualité sans " +"une sauvegarde avec une meilleure qualité.\n" +"Celà peut aussi être utilisé pour enregistrer des fichiers audio avec des " +"voix." + +#: optionssimple.cpp:158 optionssimple.cpp:163 optionssimple.cpp:168 +#: optionssimple.cpp:173 optionssimple.cpp:178 optionssimple.cpp:183 +#: optionssimple.cpp:188 optionssimple.cpp:193 +msgid "Profile" +msgstr "Profil" + +#: optionssimple.cpp:162 +msgid "" +"This produces sound files of a low quality.\n" +"That can be useful if you habe a mobile device where your memory cell is " +"limited. It is not recommended to save your music in this quality without a " +"copy with higher quality." +msgstr "" +"Ceci produit un fichier son de basse qualité.\n" +"Celà peut-être utile, si vous avez un appareil mobile, dans lequel votre " +"mémoire est limitée.\n" +"Il n'est pas recommandé d'enregistrer votre musique dans cette qualité sans " +"une sauvegarde avec une meilleure qualité." + +#: optionssimple.cpp:167 +msgid "" +"This produces sound files of a medium quality.\n" +"If your disc space is limited, you can use this to save your music." +msgstr "" +"Ceci produit un fichier son de qualité moyenne.\n" +"Si votre espace disque est limité, vous pouvez l'utiliser pour sauvegarder " +"votre musique." + +#: optionssimple.cpp:172 +msgid "" +"This produces sound files of a high quality.\n" +"If you have enough disc space available, you can use this to save your music." +msgstr "" +"Ceci produit un fichier son de haute qualité.\n" +"Si votre espace disque est limité, vous pouvez l'utiliser pour sauvegarder " +"votre musique." + +#: optionssimple.cpp:177 +msgid "" +"This produces sound files of a very high quality.\n" +"You should only use this, if you are a quality freak and have enough disc " +"space available." +msgstr "" +"Ceci produit un fichier son de très haute qualité.\n" +"Si votre espace disque est limité, vous pouvez l'utiliser pour sauvegarder " +"votre musique." + +#: optionssimple.cpp:182 +msgid "" +"This produces files, that have exact the same quality as the input files.\n" +"This files are very big and definitely only for quality freaks." +msgstr "" +"Ceci produit des fichiers de même qualité que l'original.\n" +"Ces fichiers sont très lourds et certainement utilisés pour obtenir des " +"qualités exceptionnelles." + +#: optionssimple.cpp:187 +msgid "" +"This produces two files. One lossy compressed playable file and one " +"correction file.\n" +"Both files together result in a file that is equivalent to the input file." +msgstr "" +"Ceci produit deux fichiers. Un fichier jouable compressé avec pertes, et un " +"fichier de correction.\n" +"Le résultat des deux fichiers donne un fichier qui est équivalent au fichier " +"original." + +#: optionssimple.cpp:192 +msgid "You can define your own profile in the \"detailed\" tab." +msgstr "Vous pouvez définir votre propre profil dans l'onglet \"Détaillé \"." + +#: optionssimple.cpp:205 +msgid "Do you really want to remove the profile: %1" +msgstr "Voulez-vous vraiment supprimer le profil '%1' ?" + +#: optionssimple.cpp:206 +msgid "Remove profile?" +msgstr "Supprimer le profil ?" + +#: optionssimple.cpp:234 +msgid "" +"

Wave is a file format, that doesn't compress it's audio data.

\n" +"

So the quality is very high, but the file size is enormous. It is widely " +"spread and should work with every audio player.

\n" +"
http://en.wikipedia.org/wiki/Wav" +msgstr "" +"

Wav est un format de fichiers qui ne compresse pas les données " +"audio.

\n" +"

La qualité est très élevée, mais la taille du fichier est énorme. Ce " +"format est largement diffusé et doit fonctionner avec chaque lecteur " +"audio.

\n" +"
http://fr.wikiped" +"ia.org/wiki/WAVEform_audio_format" + +#: optionssimple.cpp:235 optionssimple.cpp:242 +msgid "File format" +msgstr "Format de fichier" + +#: outputdirectory.cpp:44 +msgid "By meta data" +msgstr "Par méta-données" + +#: outputdirectory.cpp:45 +msgid "Source directory" +msgstr "Répertoire source" + +#: outputdirectory.cpp:46 +msgid "Specify output directory" +msgstr "Définir le répertoire de sortie" + +#: outputdirectory.cpp:47 +msgid "Copy directory structure" +msgstr "Copier la structure du dossier" + +#: outputdirectory.cpp:61 +msgid "Clear the directory input field" +msgstr "Effacer le champ d'entrée du répertoire." + +#: outputdirectory.cpp:81 outputdirectory.cpp:345 +msgid "Choose an output directory" +msgstr "Choisir un dossier de sortie" + +#: outputdirectory.cpp:87 +msgid "Open Konqueror with the output directory" +msgstr "Ouvrir. Konqueror avec le dossier de sortie" + +#: outputdirectory.cpp:184 +msgid "Unknown Artist" +msgstr "Artiste Inconnu" + +#: outputdirectory.cpp:188 +msgid "Unknown Album" +msgstr "Album Inconnu" + +#: outputdirectory.cpp:192 +msgid "No Comment" +msgstr "Aucun commentaire" + +#: outputdirectory.cpp:199 +msgid "Unknown Genre" +msgstr "Genre Inconnu" + +#: outputdirectory.cpp:206 +msgid "Unknown Composer" +msgstr "Compositeur Inconnu" + +#: outputdirectory.cpp:210 +msgid "Unknown Title" +msgstr "Titre Inconnu" + +#: outputdirectory.cpp:264 +msgid "new" +msgstr "Nouveau" + +#: outputdirectory.cpp:406 +msgid "Name all converted files according to the specified pattern" +msgstr "Nommer tous les fichiers convertis selon le modèle indiqué" + +#: outputdirectory.cpp:408 +msgid "" +"

The following strings are wildcards, that will be replaced by the " +"information in the meta data:

%a - Artist
%b - Album
%c - " +"Comment
%d - Disc number
%g - Genre
%n - Track number
%p - " +"Composer
%t - Title
%y - Year
%f - Original file name

" +msgstr "" +"

Les cordes suivantes sont des wildcards, ce qui remplacera les " +"informations dans les méta-données:

%a - Artiste
%b - Album
%c - " +"Commentaires
%d - Numero de disque
%g - Genre
%n - Numéro de " +"piste
%p - Compositeur
%t - Titre
%y - Année
%f - Nom de fichier " +"original

" + +#: outputdirectory.cpp:420 +msgid "" +"Output all converted files into the same directory as the original files" +msgstr "" +"Envoyer tous les fichiers convertis dans le même dossier que les fichiers " +"originaux" + +#: outputdirectory.cpp:434 +msgid "Output all converted files into the specified output directory" +msgstr "Envoyer tous les fichiers convertis dans le dossier spécifié" + +#: outputdirectory.cpp:448 +msgid "Copy the whole directory structure for all converted files" +msgstr "" +"Kopiere die komplette Verzeichnisstruktur für alle konvertierten Dateien" + +#: paranoia.cpp:214 +msgid "MB" +msgstr "Mo" + +#: paranoia.cpp:215 +msgid "KB" +msgstr "Ko" + +#: paranoia.cpp:216 +msgid "Bytes" +msgstr "Octets" + +#: progressindicator.cpp:33 +msgid "Speed" +msgstr "Vitesse" + +#: progressindicator.cpp:41 +msgid "Time remaining" +msgstr "Temps restant" + +#: progressindicator.cpp:95 progressindicator.cpp:96 replaygainscanner.cpp:216 +msgid "Finished" +msgstr "Terminé" + +#. i18n: file ./soundkonverterui.rc line 13 +#: rc.cpp:3 +#, no-c-format +msgid "&Conversion" +msgstr "&Conversion" + +#: replaygain.cpp:88 +msgid "Executing" +msgstr "Exécution" + +#: replaygainfilelist.cpp:137 replaygainfilelist.cpp:147 +#: replaygainfilelist.cpp:150 replaygainfilelist.cpp:180 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:669 +#: replaygainfilelist.cpp:672 replaygainfilelist.cpp:704 +#: replaygainfilelist.cpp:707 replaygainfilelist.cpp:734 +#: replaygainfilelist.cpp:737 replaygainfilelist.cpp:940 +msgid "Album" +msgstr "Album" + +#: replaygainfilelist.cpp:213 +msgid "Calculate Replay Gain tags" +msgstr "Calcul les tags Replay Gain" + +#: replaygainfilelist.cpp:214 +msgid "Remove Replay Gain tags" +msgstr "Effacer les tags Replay Gain" + +#: replaygainfilelist.cpp:217 replaygainfilelist.cpp:825 +msgid "New album" +msgstr "Nouvel album" + +#: replaygainfilelist.cpp:218 +msgid "Open all albums" +msgstr "Ouvrir tous les albums" + +#: replaygainfilelist.cpp:219 +msgid "Cloase all albums" +msgstr "Fermer tous les albums" + +#: replaygainfilelist.cpp:223 +msgid "" +"

Replay Gain Tool

With this tool you can add Replay " +"Gain tags to your audio files and remove them.
Replay Gain adds a volume " +"correction information to the files so that they can be played at an equal " +"volume level.
" +msgstr "" +"

Outil Replay Gain

Avec cet outil vous pouvez " +"ajouter ou effacer des tags Replay Gain à vos fichiers audio.
Replay Gain " +"ajoute une information de correction du volume dans vos fichiers qui peuvent " +"ainsi être joués au même niveau de volume.
" + +#: replaygainfilelist.cpp:494 +msgid "You can't place files of different formats in the same 'album'." +msgstr "" +"Vous pouvez placer des fichiers de formats différents dans le même 'album'." + +#: replaygainfilelist.cpp:494 +msgid "Different file formats" +msgstr "Différents formats de fichiers" + +#: replaygainfilelist.cpp:987 +msgid "Removing Replay Gain" +msgstr "Suppression de Replay Gain" + +#: replaygainfilelist.cpp:1148 +msgid "built-in" +msgstr "intégré" + +#: replaygainscanner.cpp:33 replaygainscanner.cpp:216 +#: replaygainscanner.cpp:231 +msgid "Replay Gain Tool" +msgstr "Outil Replay Gain" + +#: replaygainscanner.cpp:43 +msgid "Add Folder ..." +msgstr "Ajouter un dossier ..." + +#: replaygainscanner.cpp:44 +msgid "Add Files ..." +msgstr "Ajouter des fichiers..." + +#: replaygainscanner.cpp:52 +msgid "Force recalculation" +msgstr "Forcer à recalculer" + +#: replaygainscanner.cpp:53 +msgid "" +"Recalculate Replay Gain tag for files that already have a Replay Gain tag " +"set." +msgstr "" +"Recalculer les tags Replay Gain pour les fichiers qui contiennent déjà des " +"tags Replay Gain." + +#: replaygainscanner.cpp:102 +msgid "Tag untagged" +msgstr "" +"Ajouter les tags Replay Gain dans les fichiers qui ne sont pas déjà taggés " +"avec Replay Gain." + +#: replaygainscanner.cpp:103 +msgid "" +"Calculate Replay Gain tag for all files in the file list without Replay Gain " +"tag." +msgstr "" +"Calculer le Replay Gain dans tous les fichiers de la liste qui ne sont pas " +"déjà taggés avec Replay Gain." + +#: replaygainscanner.cpp:109 +msgid "Untag tagged" +msgstr "" +"Enlever les tags Replay Gain dans les fichiers déjà taggés avec Replay Gain." + +#: replaygainscanner.cpp:110 +msgid "Remove the Replay Gain tag from all files in the file list." +msgstr "Supprimer les tags Replay Gain dans tous les fichiers de la liste." + +#: replaygainscanner.cpp:151 +msgid "Choose files!" +msgstr "Choisir des fichiers!" + +#: soundkonverter.cpp:107 +msgid "Choose your prefered output options and click on \"Add files ...\"!" +msgstr "" +"Choisissez vos options de sortie préférées et cliquez sur \"Ajouter " +"fichiers...\"!" + +#: soundkonverter.cpp:110 soundkonverter.cpp:405 soundkonverter.cpp:448 +msgid "&Start conversion" +msgstr "&Démarrer la conversion" + +#: soundkonverter.cpp:112 +msgid "&Replay Gain Tool ..." +msgstr "&Outil Replay Gain" + +#: soundkonverter.cpp:114 +msgid "C&uesheet Editor ..." +msgstr "Editeur C&uesheet ..." + +#: soundkonverter.cpp:115 +msgid "Show &Log ..." +msgstr "Montrez le &Log..." + +#: soundkonverter.cpp:118 +msgid "S&top after current file is complete" +msgstr "A&rrêter après que le fichier courant soit complet" + +#: soundkonverter.cpp:119 +msgid "&Continue after current file is complete" +msgstr "&Continuer après que le fichier courant soit complet" + +#: soundkonverter.cpp:120 +msgid "Stop &immediately" +msgstr "Arrêter &immédiatement" + +#: soundkonverter.cpp:148 +msgid "A&dd Files ..." +msgstr "A&jouter des fichiers" + +#: soundkonverter.cpp:149 +msgid "Add &Folder ..." +msgstr "Ajouter un &dossier" + +#: soundkonverter.cpp:150 +msgid "Add CD &tracks ..." +msgstr "Ajouter des &pistes de CD" + +#: soundkonverter.cpp:151 +msgid "Add &URL ..." +msgstr "Ajouter une &URL ..." + +#: soundkonverter.cpp:154 +msgid "L&oad file list" +msgstr "Ch&arger la liste de fichiers" + +#: soundkonverter.cpp:155 +msgid "Sa&ve file list" +msgstr "Sau&vegarder la liste de fichiers" + +#: soundkonverter.cpp:229 +msgid "Add files ..." +msgstr "Ajouter des fichiers" + +#: soundkonverter.cpp:230 +msgid "Add folder ..." +msgstr "Ajouter un dossier" + +#: soundkonverter.cpp:231 +msgid "Add CD tracks ..." +msgstr "Ajouter des pistes de CD" + +#: soundkonverter.cpp:232 +msgid "Add URL ..." +msgstr "Ajouter une URL..." + +#: soundkonverter.cpp:240 +msgid "Start" +msgstr "Démarrer" + +#: soundkonverter.cpp:417 +msgid "&Start queue" +msgstr "&Démarrer la liste d'attente" + +#: soundkonverter.cpp:489 +msgid "Choose files to convert" +msgstr "Choisir des fichiers à convertir" + +#: soundkonverter.cpp:617 +msgid "Open URL" +msgstr "Ouvrir une URL" + +#: soundkonverter.cpp:617 +msgid "Enter a URL:" +msgstr "Entrer une URL" diff --git a/po/hu.po b/po/hu.po new file mode 100644 index 0000000..d7864af --- /dev/null +++ b/po/hu.po @@ -0,0 +1,1690 @@ +# translation of hu.po to +# This file is put in the public domain. +# +# Adam Pongracz , 2006. +msgid "" +msgstr "" +"Project-Id-Version: hu\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-02-25 17:22+0100\n" +"PO-Revision-Date: 2008-03-05 00:32+0000\n" +"Last-Translator: Pittmann Tamás \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2008-04-06 10:52+0000\n" +"X-Generator: Launchpad (build Unknown)\n" + +#~ msgid "Available plugins" +#~ msgstr "Elérhető kiegészítők" + +#~ msgid "Refresh" +#~ msgstr "Frissítés" + +#~ msgid "Download the latest list of available plugins." +#~ msgstr "Az elérhető kiegészítők listájának frissítése." + +#~ msgid "Install" +#~ msgstr "Telepítés" + +#~ msgid "" +#~ "Download the selected plugin and install it into the soundKonverter " +#~ "directory." +#~ msgstr "Kiválasztott kiegészítők telepítése a soundKonverter könyvtárába." + +#~ msgid "Check for new plugins on every startup" +#~ msgstr "Minden indításnál új kiegészítők keresése" + +#~ msgid "Adding new item to conversion list: `%1')" +#~ msgstr "Új elem hozzáadása a konvertálási listához: '`%1')" + +#~ msgid "Choose a directory!" +#~ msgstr "Válassza ki a könyvtárat!" + +#~ msgid "" +#~ "There are new plugin updates available.\n" +#~ "Click on this button in order to open the configuration dialog." +#~ msgstr "" +#~ "Új kiegészítő frissítések érhetőek el.\n" +#~ "Kattintson erre a gombra, a konfigurációs párbeszédablak megnyitásához." + +#~ msgid "Strenght" +#~ msgstr "Mérték" + +#~ msgid "Leállítva" +#~ msgstr "Leállítva" + +#~ msgid "" +#~ " A volume difference is calculated and stored in a tag. This way audio " +#~ "players can automatically adjust the volume and the original music data is " +#~ "not modified (like at normalization)." +#~ msgstr "" +#~ " A Replay Gain egy hangerő javító technika. Kiszámítja a hangerőkülönbséget " +#~ "és egy meta adatban tárolja. Erre a zenelejátszók automatikusan beállítják a " +#~ "kötetet és az eredeti zenei adatokat nem módosítják (mint a normalizálás)." + +#: _translatorinfo.cpp:1 +msgid "Your names" +msgstr "" +"Adam Pongracz,,Launchpad Contributions:,Adam Pongracz,Gabor SUVEG,Pittmann " +"Tamás,Pongracz Adam,sipiatti" + +#: _translatorinfo.cpp:3 +msgid "Your emails" +msgstr "" +"pongadam@gmail.com,,,,gabor@suveg.hu,zaivaldi@gmail.com,pongadam@freeweb.hu,s" +"ipiatti@gmail.com" + +#: cddb.cpp:368 +msgid "No Title" +msgstr "Nincs cím" + +#: cddb.cpp:372 cdmanager.cpp:97 convert.cpp:513 convert.cpp:514 +#: convert.cpp:515 convert.cpp:517 convert.cpp:519 convert.cpp:520 +#: convert.cpp:1547 convert.cpp:1557 convert.cpp:1571 +#: replaygainfilelist.cpp:136 replaygainfilelist.cpp:137 +#: replaygainfilelist.cpp:144 replaygainfilelist.cpp:150 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:666 +#: replaygainfilelist.cpp:672 replaygainfilelist.cpp:701 +#: replaygainfilelist.cpp:707 replaygainfilelist.cpp:731 +#: replaygainfilelist.cpp:737 replaygainfilelist.cpp:945 +msgid "Unknown" +msgstr "Ismeretlen" + +#: cddb.cpp:380 +msgid "Track %1" +msgstr "%1 szám" + +#: cddb.cpp:479 +msgid "Searching local cddb entry ..." +msgstr "Helyi CDDB-bejegyzések keresése..." + +#: cddb.cpp:504 +msgid "Searching remote cddb entry ..." +msgstr "Távoli CDDB-bejegyzések keresése..." + +#: cddb.cpp:528 +msgid "Found exact match cddb entry ..." +msgstr "Pontosan illeszkedő CDDB-találatok..." + +#: cddb.cpp:585 +msgid "Found close cddb entry ..." +msgstr "Majdnem illeszkedő CDDB-bejegyzés..." + +#: cddb.cpp:608 +msgid "CDDB Matches" +msgstr "CDDB-találatok" + +#: cddb.cpp:608 +msgid "Several close CDDB entries found. Choose one:" +msgstr "" +"Több majdnem illeszkedő CDDB-bejegyzés található, válasszon ki egyet:" + +#: cdmanager.cpp:46 filelist.cpp:618 +msgid "Audio CD" +msgstr "Audió CD" + +#: cdmanager.cpp:46 +msgid "Several audio CDs found. Choose one:" +msgstr "Több audió CD-t találtam. Válasszon egyet:" + +#: cdmanager.cpp:104 +msgid "No audio CD found." +msgstr "Nem található audió CD." + +#: cdopener.cpp:41 +msgid "Add CD tracks" +msgstr "CD szám hozzáadása" + +#: cdopener.cpp:52 cdopener.cpp:178 optionseditor.cpp:123 +msgid "Artist:" +msgstr "Előadó:" + +#: cdopener.cpp:57 cdopener.cpp:480 cdopener.cpp:485 cdopener.cpp:538 +#: cdopener.cpp:567 cdopener.cpp:682 cdopener.cpp:697 +msgid "Various Artists" +msgstr "Különböző előadók" + +#: cdopener.cpp:66 cdopener.cpp:193 optionseditor.cpp:138 +msgid "Composer:" +msgstr "Zeneszerző:" + +#: cdopener.cpp:71 cdopener.cpp:496 cdopener.cpp:501 cdopener.cpp:548 +#: cdopener.cpp:579 cdopener.cpp:683 cdopener.cpp:698 +msgid "Various Composer" +msgstr "Többi zeneszerző" + +#: cdopener.cpp:83 optionseditor.cpp:158 +msgid "Album:" +msgstr "Album:" + +#: cdopener.cpp:91 optionseditor.cpp:178 +msgid "Disc No.:" +msgstr "CD Nr.:" + +#: cdopener.cpp:96 optionseditor.cpp:194 +msgid "Year:" +msgstr "Év:" + +#: cdopener.cpp:100 optionseditor.cpp:210 +msgid "Genre:" +msgstr "Műfaj:" + +#: cdopener.cpp:114 cdopener.cpp:532 filelist.cpp:578 filelist.cpp:587 +#: replaygainfilelist.cpp:136 replaygainfilelist.cpp:141 +#: replaygainfilelist.cpp:144 replaygainfilelist.cpp:178 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:663 +#: replaygainfilelist.cpp:666 replaygainfilelist.cpp:698 +#: replaygainfilelist.cpp:701 replaygainfilelist.cpp:728 +#: replaygainfilelist.cpp:731 +msgid "Track" +msgstr "Szám" + +#: cdopener.cpp:115 cdopener.cpp:568 cdopener.cpp:571 cdopener.cpp:607 +msgid "Artist" +msgstr "Előadó" + +#: cdopener.cpp:116 cdopener.cpp:580 cdopener.cpp:583 cdopener.cpp:620 +msgid "Composer" +msgstr "Zeneszerző" + +#: cdopener.cpp:117 cdopener.cpp:594 +msgid "Title" +msgstr "Cím" + +#: cdopener.cpp:118 +msgid "Time" +msgstr "Idő" + +#: cdopener.cpp:131 +msgid "No track selected" +msgstr "Nincs szám kiválasztva" + +#: cdopener.cpp:159 optionseditor.cpp:88 +msgid "Title:" +msgstr "Cím:" + +#: cdopener.cpp:212 optionseditor.cpp:235 +msgid "Comment:" +msgstr "Megjegyzés:" + +#: cdopener.cpp:242 +msgid "Save cuesheet ..." +msgstr "Cue információk mentése ..." + +#: cdopener.cpp:250 +msgid "Add all tracks" +msgstr "Összes szám hozzáadása" + +#: cdopener.cpp:251 +msgid "Add selected tracks" +msgstr "Kiválasztott számok hozzáadása" + +#: cdopener.cpp:253 +msgid "Add full CD as one file" +msgstr "Egész CD összeadása egy fájlba" + +#: cdopener.cpp:440 +msgid "All tracks" +msgstr "Összes szám" + +#: cdopener.cpp:443 +msgid "Tracks" +msgstr "Számok" + +#: cdopener.cpp:742 +msgid "" +"A file with this name already exists.\n" +"\n" +"Do you want to overwrite the existing one?" +msgstr "" +"Már használatban van egy ilyen nevű fájl.\n" +"\n" +"Szeretné, hogy felülírjam?" + +#: cdopener.cpp:743 +msgid "File already exists" +msgstr "Már létezik ez a fájl" + +#: config.cpp:103 config.cpp:104 config.cpp:1197 config.cpp:1206 +#: config.cpp:1237 configgeneralpage.cpp:37 configgeneralpage.cpp:60 +#: configgeneralpage.cpp:62 configgeneralpage.cpp:269 +#: configgeneralpage.cpp:273 configgeneralpage.cpp:297 +#: configgeneralpage.cpp:306 configgeneralpage.cpp:316 options.cpp:153 +#: optionsdetailed.cpp:363 optionssimple.cpp:49 optionssimple.cpp:221 +#: optionssimple.cpp:518 soundkonverter.cpp:308 soundkonverter.cpp:309 +msgid "Last used" +msgstr "Legutóbb használt" + +#: config.cpp:508 +msgid "Convert with soundKonverter ..." +msgstr "Konvertálás soundKonverter-rel ..." + +#: config.cpp:543 +msgid "Add Replay Gain with soundKonverter ..." +msgstr "Replay Gain hozzáadása soundKonverter-rel ..." + +#: config.cpp:1228 config.cpp:1229 configgeneralpage.cpp:57 +#: configgeneralpage.cpp:302 convert.cpp:431 filelist.cpp:1379 +#: optionsdetailed.cpp:361 optionsdetailed.cpp:427 optionsdetailed.cpp:477 +#: optionsdetailed.cpp:527 optionsdetailed.cpp:604 optionssimple.cpp:46 +#: optionssimple.cpp:140 optionssimple.cpp:180 optionssimple.cpp:218 +#: optionssimple.cpp:407 optionssimple.cpp:515 optionssimple.cpp:535 +msgid "Lossless" +msgstr "Veszteségmentes" + +#: config.cpp:1232 config.cpp:1233 configgeneralpage.cpp:58 +#: configgeneralpage.cpp:312 convert.cpp:434 convert.cpp:1378 +#: filelist.cpp:1382 optionsdetailed.cpp:362 optionsdetailed.cpp:480 +#: optionsdetailed.cpp:618 optionssimple.cpp:47 optionssimple.cpp:141 +#: optionssimple.cpp:185 optionssimple.cpp:219 optionssimple.cpp:421 +#: optionssimple.cpp:430 optionssimple.cpp:516 optionssimple.cpp:544 +msgid "Hybrid" +msgstr "Hibrid" + +#: config.cpp:1245 config.cpp:1252 config.cpp:1259 config.cpp:1266 +#: config.cpp:1273 convert.cpp:403 convert.cpp:995 convert.cpp:1567 +#: filelist.cpp:139 filelist.cpp:752 filelist.cpp:1270 filelist.cpp:1351 +#: optionsdetailed.cpp:246 optionsdetailed.cpp:467 optionsdetailed.cpp:582 +#: optionsdetailed.cpp:641 optionssimple.cpp:38 optionssimple.cpp:283 +#: optionssimple.cpp:312 optionssimple.cpp:340 optionssimple.cpp:367 +#: optionssimple.cpp:394 +msgid "Quality" +msgstr "Minőség" + +#: config.cpp:1248 config.cpp:1285 convert.cpp:450 filelist.cpp:1398 +#: optionsdetailed.cpp:538 optionssimple.cpp:294 +msgid "Mono" +msgstr "Monó" + +#: config.cpp:1250 config.cpp:1287 configgeneralpage.cpp:52 +#: configgeneralpage.cpp:289 optionsdetailed.cpp:356 optionssimple.cpp:41 +#: optionssimple.cpp:135 optionssimple.cpp:155 optionssimple.cpp:213 +#: optionssimple.cpp:269 optionssimple.cpp:510 optionssimple.cpp:525 +msgid "Very low" +msgstr "Nagyon alacsony" + +#: config.cpp:1257 config.cpp:1294 configgeneralpage.cpp:53 +#: configgeneralpage.cpp:111 configgeneralpage.cpp:290 optionsdetailed.cpp:357 +#: optionssimple.cpp:42 optionssimple.cpp:136 optionssimple.cpp:160 +#: optionssimple.cpp:214 optionssimple.cpp:298 optionssimple.cpp:511 +#: optionssimple.cpp:525 +msgid "Low" +msgstr "Alacsony" + +#: config.cpp:1264 config.cpp:1301 configgeneralpage.cpp:54 +#: configgeneralpage.cpp:291 optionsdetailed.cpp:358 optionseditor.cpp:713 +#: optionssimple.cpp:43 optionssimple.cpp:137 optionssimple.cpp:165 +#: optionssimple.cpp:215 optionssimple.cpp:326 optionssimple.cpp:512 +#: optionssimple.cpp:526 +msgid "Medium" +msgstr "Közepes" + +#: config.cpp:1271 config.cpp:1308 configgeneralpage.cpp:55 +#: configgeneralpage.cpp:292 optionsdetailed.cpp:359 optionssimple.cpp:44 +#: optionssimple.cpp:138 optionssimple.cpp:170 optionssimple.cpp:216 +#: optionssimple.cpp:353 optionssimple.cpp:513 optionssimple.cpp:526 +msgid "High" +msgstr "Magas" + +#: config.cpp:1278 config.cpp:1315 configgeneralpage.cpp:56 +#: configgeneralpage.cpp:293 optionsdetailed.cpp:360 optionssimple.cpp:45 +#: optionssimple.cpp:139 optionssimple.cpp:175 optionssimple.cpp:217 +#: optionssimple.cpp:380 optionssimple.cpp:514 optionssimple.cpp:527 +msgid "Very high" +msgstr "Nagyon magas" + +#: config.cpp:1282 config.cpp:1289 config.cpp:1296 config.cpp:1303 +#: config.cpp:1310 convert.cpp:387 convert.cpp:996 convert.cpp:997 +#: convert.cpp:1568 convert.cpp:1569 filelist.cpp:1234 filelist.cpp:1245 +#: filelist.cpp:1255 filelist.cpp:1335 optionsdetailed.cpp:246 +#: optionsdetailed.cpp:470 optionsdetailed.cpp:560 optionssimple.cpp:287 +#: optionssimple.cpp:316 optionssimple.cpp:344 optionssimple.cpp:371 +#: optionssimple.cpp:398 +msgid "Bitrate" +msgstr "Bitráta" + +#: config.cpp:1351 optionsdetailed.cpp:365 optionssimple.cpp:51 +#: optionssimple.cpp:142 optionssimple.cpp:190 optionssimple.cpp:223 +#: optionssimple.cpp:435 optionssimple.cpp:454 optionssimple.cpp:458 +#: optionssimple.cpp:468 optionssimple.cpp:472 optionssimple.cpp:520 +#: optionssimple.cpp:552 +msgid "User defined" +msgstr "Egyéni" + +#: config.cpp:1394 config.cpp:1407 config.cpp:1411 config.cpp:1457 +#: config.cpp:1461 +msgid "files" +msgstr "fájlok" + +#: config.cpp:1419 config.cpp:1469 +msgid "all supported formats" +msgstr "összes támogatott formátum" + +#: config.cpp:1419 config.cpp:1469 +msgid "all formats" +msgstr "összes formátum" + +#: configbackendspage.cpp:42 +msgid "Legend" +msgstr "Felirat" + +#: configbackendspage.cpp:45 +msgid "Full support" +msgstr "Teljes támogatás" + +#: configbackendspage.cpp:48 +msgid "Most supported" +msgstr "Jó támogatás" + +#: configbackendspage.cpp:51 +msgid "Basic support" +msgstr "Alacsony támogatás" + +#: configbackendspage.cpp:57 +msgid "CD Ripper" +msgstr "CD Ripper" + +#: configbackendspage.cpp:243 +msgid "Encoder" +msgstr "Kodoló" + +#: configbackendspage.cpp:256 +msgid "Strength" +msgstr "Mérték" + +#: configbackendspage.cpp:263 +msgid "" +"Set the compression strength:\n" +"\n" +"Left = fast conversion\n" +"Right = good resultant file" +msgstr "" +"Válassza ki a tömörítés mértéket:\n" +"\n" +"Bal = gyors konvertálás\n" +"Jobb = jó minőségű fájl" + +#: configbackendspage.cpp:272 +msgid "Decoder" +msgstr "Dekódoló" + +#: configbackendspage.cpp:286 convert.cpp:593 convert.cpp:1580 +#: optionsdetailed.cpp:168 +msgid "Replay Gain" +msgstr "Replay Gain" + +#: configbackendspage.cpp:295 +msgid "Use internal Replay Gain" +msgstr "Belső Replay Gain használata" + +#: configbackendspage.cpp:296 +msgid "Use the internal Replay Gain calculator of the encoder" +msgstr "Belső Replay Gain számológép használata a kódoláshoz" + +#: configbackendspage.cpp:320 +msgid "KDE audio CD protocol" +msgstr "KDE audió CD protokoll" + +#: configdialog.cpp:31 +msgid "Settings" +msgstr "Beállítások" + +#: configdialog.cpp:56 +msgid "General" +msgstr "Általános" + +#: configdialog.cpp:68 +msgid "Plugins" +msgstr "Kiegészítők" + +#: configdialog.cpp:80 +msgid "Environment" +msgstr "Környezet" + +#: configdialog.cpp:92 +msgid "Backends" +msgstr "Kiszolgálók" + +#: configenvironmentpage.cpp:32 +msgid "Directories to be scanned" +msgstr "Könyvtárak vizsgálata" + +#: configenvironmentpage.cpp:50 +msgid "" +"Move selected directory one position up.\n" +"This effects which backend will be chosen, if there are several versions." +msgstr "" +"Kiválasztott könyvtár mogatása felfelé.\n" +"Ki lehet választani, hogy ezek a hatások melyik kiszolgálót használják, ha " +"több verzió van." + +#: configenvironmentpage.cpp:60 +msgid "" +"Move selected directory one position down.\n" +"This effects which backend will be chosen, if there are several versions." +msgstr "" +"Kiválasztott könyvtár mozgatása lefelé.\n" +"Ki lehet választani, hogy ezek a hatások melyik kiszolgálót használják, ha " +"több verzió van." + +#: configenvironmentpage.cpp:67 configpluginspage.cpp:50 +msgid "Add ..." +msgstr "Hozzáadás ..." + +#: configenvironmentpage.cpp:87 +msgid "Programs found" +msgstr "Programokat találtam" + +#: configenvironmentpage.cpp:96 +msgid "Programs not found" +msgstr "Nem találtam programokat" + +#: configgeneralpage.cpp:34 +msgid "Start in Mode" +msgstr "Indítás ebben a módban:" + +#: configgeneralpage.cpp:38 options.cpp:36 +msgid "Simple" +msgstr "Egyszerű" + +#: configgeneralpage.cpp:39 options.cpp:41 +msgid "Detailed" +msgstr "Részletes" + +#: configgeneralpage.cpp:49 +msgid "Default profile" +msgstr "Alapértelmezett profil" + +#: configgeneralpage.cpp:72 +msgid "Default format" +msgstr "Alapértelmezett formátum" + +#: configgeneralpage.cpp:107 +msgid "Process priority of the backends" +msgstr "A háttérprogramok eljárásprioritása" + +#: configgeneralpage.cpp:110 +msgid "Normal" +msgstr "Szokványos" + +#: configgeneralpage.cpp:122 +msgid "Use FAT compatible output file names" +msgstr "FAT kompatibilis kimeneti fájlnevek használata" + +#: configgeneralpage.cpp:123 +msgid "Replaces some special characters like '?' by '_'." +msgstr "A speciális karakterek mint a '?' és a '_' helyettesítése." + +#: configgeneralpage.cpp:133 +msgid "Conflict handling" +msgstr "Konfliktus kezelés" + +#: configgeneralpage.cpp:136 +msgid "Do that if the output file already exists" +msgstr "Tegye ezt, ha a kimeneti fájl már létezik" + +#: configgeneralpage.cpp:137 +msgid "Generate new file name" +msgstr "Új fájlnév létrehozása" + +#: configgeneralpage.cpp:138 +msgid "Skip file" +msgstr "Fájl kihagyása" + +#: configgeneralpage.cpp:149 +msgid "Number of files to convert at once" +msgstr "Az azonnal konvertálandó fájlok száma" + +#: configgeneralpage.cpp:160 +msgid "Status update delay (time in msec.)" +msgstr "Állapotfrissítés késik(idő mpercben)" + +#: configgeneralpage.cpp:163 +msgid "Update the progress bar in this interval (time in milliseconds)" +msgstr "" +"A folyamatjelző frissítése ezekben az időközökben (idő milliszekundumokban)" + +#: configgeneralpage.cpp:172 +msgid "Ask for new options, when adding files from external program" +msgstr "Kérdés az új opciók után, mikor külső programból ad hozzá fájlokat" + +#: configgeneralpage.cpp:173 +msgid "" +"If you open a file with soundKonverter and soundKonverter is already " +"running,\n" +"you can either be asked to define new converting options\n" +"or the current settings from the soundKonverter main window are used." +msgstr "" +"Ha megnyitott egy fájlt soundKonverter-rel és a soundKonverter már fut,\n" +" akkor bármelyikkel meg lehet határozni új konvertáló opciókat\n" +" vagy az aktuális beállításokat a soundKonverter fő ablakából használhatják." + +#: configgeneralpage.cpp:183 +msgid "Execute user script (for advanced users)" +msgstr "Felhasználói parancsfájl futtatása (haladó felhasználóknak)" + +#: configgeneralpage.cpp:184 +msgid "" +"Executes a script after every finished conversion. Have a look at " +"$KDEDIR/soundkonverter/userscript.sh" +msgstr "" +"Parancsfájl lefuttatása minden konvertálás után. Nézzen rá erre: " +"$KDEDIR/soundkonverter/userscript.sh" + +#: configpluginspage.cpp:39 +msgid "Installed plugins" +msgstr "Telepített kiegészítők" + +#: configpluginspage.cpp:228 +msgid "*.soundkonverter.xml|Plugins (*.soundkonverter.xml)" +msgstr "*.soundkonverter.xml|Plugins (*.soundkonverter.xml)" + +#: configpluginspage.cpp:228 +msgid "Choose a plugin to add!" +msgstr "Válassza ki a telepítendő kiegészítőt!" + +#: configpluginspage.cpp:253 configpluginspage.cpp:546 +msgid "" +"The plugin could not be installed. Please ensure that you have selected a " +"valid soundKonverter plugin file." +msgstr "" +"A kiegészítőt nem lehet telepíteni. Bizonyosodjon meg róla, hogy érvényes " +"soundKonverter kiegészítőt választott ki." + +#: configpluginspage.cpp:254 configpluginspage.cpp:294 +#: configpluginspage.cpp:547 configpluginspage.cpp:587 +msgid "Error while installing plugin" +msgstr "Hiba a kiegészítő telepítése közben" + +#: configpluginspage.cpp:279 configpluginspage.cpp:572 +msgid "" +"The plugin was installed successfully. Please restart soundKonverter in " +"order to activate it." +msgstr "" +"A kiegészítő sikeresen telepítve. Indítsa újra a soundKonverter-t az " +"engedélyezéshez ." + +#: configpluginspage.cpp:280 configpluginspage.cpp:573 +msgid "Plugin successfully installed" +msgstr "A kiegészítő sikeresen telepítve" + +#: configpluginspage.cpp:293 configpluginspage.cpp:586 +msgid "" +"The plugin could not be installed. Please ensure that you have write " +"permission on your whole user directory." +msgstr "" +"A kiegészítőt nem lehet telepíteni. Bizonyosodjon meg róla, hogy van " +"megfelelő írási jogosultsága a felhasználói könyvtárához." + +#: configpluginspage.cpp:311 configpluginspage.cpp:330 +#: configpluginspage.cpp:349 +msgid "" +"The plugin was removed successfully. Please restart soundKonverter in order " +"to deactivate it." +msgstr "" +"A kiegészítő sikeresen eltávolítva. Indítsa újra a soundKonverter-t a " +"tiltásához." + +#: configpluginspage.cpp:312 configpluginspage.cpp:331 +#: configpluginspage.cpp:350 +msgid "Plugin successfully removed" +msgstr "A kiegészítő sikeresen eltávolítva" + +#: configpluginspage.cpp:316 configpluginspage.cpp:335 +#: configpluginspage.cpp:354 +msgid "" +"The plugin could not be removed. Please ensure that you have write " +"permission on your whole user directory." +msgstr "" +"A kiegészítőt nem lehet eltávolítani. Bizonyosodjon meg róla, hogy van " +"megfelelő írási jogosultsága a felhasználói könyvtárához." + +#: configpluginspage.cpp:317 configpluginspage.cpp:336 +#: configpluginspage.cpp:355 +msgid "Error while removing plugin" +msgstr "Hiba a kiegészítő eltávolítása közben" + +#: configpluginspage.cpp:383 configpluginspage.cpp:395 +#: configpluginspage.cpp:407 +msgid "Version" +msgstr "Verzió" + +#: configpluginspage.cpp:384 configpluginspage.cpp:396 +#: configpluginspage.cpp:408 +msgid "Author" +msgstr "Szerző" + +#: configpluginspage.cpp:417 configpluginspage.cpp:472 +msgid "No new plugins available!" +msgstr "Nincs új elérhető kiegészítő!" + +#: configpluginspage.cpp:477 +msgid "" +"The plugin list could not be downloaded. Please ensure, that your internet " +"connection works correct.\n" +"Maybe our server is busy at the moment, please try it again later." +msgstr "" +"A kiegészítők listáját nem lehet letölteni. Bizonyosodjon meg róla, hogy az " +"internetkapcsolat működik.\n" +"Lehet, hogy a szerverünk pillanatnyilag nem elérhető, később próbálja újra." + +#: configpluginspage.cpp:478 +msgid "Error while loading plugin list" +msgstr "Hiba a kiegészítők listájának letöltésekor" + +#: configpluginspage.cpp:626 configpluginspage.cpp:632 +msgid "" +"The plugin info could not be downloaded. Please ensure, that your internet " +"connection works correctly." +msgstr "" +"A kiegészítőkről információt nem lehet letölteni. Bizonyosodjon meg róla, " +"hogy az internetkapcsolat működik." + +#: configpluginspage.cpp:627 configpluginspage.cpp:633 +msgid "Error while loading plugin info" +msgstr "Hiba a kiegészítők infomációinak letöltésekor" + +#: convert.cpp:83 convert.cpp:86 convert.cpp:1538 +msgid "Getting file" +msgstr "Fájl letöltése" + +#: convert.cpp:86 convert.cpp:130 convert.cpp:190 convert.cpp:260 +#: convert.cpp:314 convert.cpp:555 convert.cpp:593 convert.cpp:603 +#: convert.cpp:617 convert.cpp:661 convert.cpp:694 convert.cpp:1538 +#: convert.cpp:1542 convert.cpp:1547 convert.cpp:1551 convert.cpp:1557 +#: convert.cpp:1561 convert.cpp:1571 convert.cpp:1575 convert.cpp:1580 +#: convert.cpp:1583 convert.cpp:1587 filelist.cpp:136 filelist.cpp:638 +#: filelist.cpp:641 filelist.cpp:650 filelist.cpp:651 filelist.cpp:696 +#: filelist.cpp:726 filelist.cpp:729 filelist.cpp:733 filelist.cpp:860 +#: filelist.cpp:861 filelist.cpp:918 filelist.cpp:955 filelist.cpp:956 +msgid "State" +msgstr "Állapot" + +#: convert.cpp:116 convert.cpp:130 convert.cpp:1542 +msgid "Getting correction file" +msgstr "Javítófájl letöltése" + +#: convert.cpp:122 +msgid "Aborting, file does not exist" +msgstr "Megszakítva, a fájl nem elérhető" + +#: convert.cpp:157 convert.cpp:190 convert.cpp:260 convert.cpp:1547 +#: convert.cpp:1551 +msgid "Ripping" +msgstr "Rippelés" + +#: convert.cpp:270 convert.cpp:314 convert.cpp:1557 convert.cpp:1561 +msgid "Decoding" +msgstr "Dekódolás" + +#: convert.cpp:334 convert.cpp:555 convert.cpp:1571 convert.cpp:1575 +msgid "Encoding" +msgstr "Kódolás" + +#: convert.cpp:453 filelist.cpp:1401 optionsdetailed.cpp:541 +msgid "Stereo" +msgstr "Sztereó" + +#: convert.cpp:456 filelist.cpp:1404 optionsdetailed.cpp:544 +msgid "Joint-Stereo" +msgstr "Joint-Sztereó" + +#: convert.cpp:459 filelist.cpp:1407 optionsdetailed.cpp:547 +msgid "Forced Joint-Stereo" +msgstr "Erőltetett Joint-Stereo" + +#: convert.cpp:462 filelist.cpp:1410 optionsdetailed.cpp:550 +msgid "Dual Channels" +msgstr "Két csatorna" + +#: convert.cpp:563 replaygainfilelist.cpp:914 +msgid "Applying Replay Gain" +msgstr "Replay Gain alkalmazása" + +#: convert.cpp:598 convert.cpp:603 +msgid "Writing tags" +msgstr "Meta adatok írása" + +#: convert.cpp:611 convert.cpp:617 convert.cpp:1583 +msgid "Moving file" +msgstr "Fájl áthelyezése" + +#: convert.cpp:649 convert.cpp:661 convert.cpp:1587 +msgid "Moving correction file" +msgstr "Javítófájl áthelyezése" + +#: convert.cpp:688 convert.cpp:694 +msgid "Running user script" +msgstr "Futó felhasználói parancsfájl" + +#: convert.cpp:713 +msgid "Executing next step" +msgstr "Következő lépés végrehajtása" + +#: convert.cpp:857 convert.cpp:874 convert.cpp:1123 convert.cpp:1147 +msgid "Got file" +msgstr "Fájl letöltése" + +#: convert.cpp:891 convert.cpp:1204 convert.cpp:1216 +msgid "Could not write to file: `%1'" +msgstr "A fájl nem írható: '%1'" + +#: convert.cpp:903 convert.cpp:918 convert.cpp:1228 convert.cpp:1255 +msgid "File moved" +msgstr "Fájl áthelyezve" + +#: convert.cpp:941 filelist.cpp:70 filelist.cpp:138 filelist.cpp:750 +#: outputdirectory.cpp:39 replaygainfilelist.cpp:1141 +msgid "Output" +msgstr "Kimenet" + +#: convert.cpp:1292 +msgid "Adding new item to conversion list: `%1'" +msgstr "Új elem hozzáadása a konvertálandók listájára: `%1'" + +#: convert.cpp:1299 +msgid "Got log ID: %1" +msgstr "Új napló ID: %1" + +#: convert.cpp:1302 +msgid "Tags successfully read" +msgstr "Meta adatok elolvasása kész" + +#: convert.cpp:1303 +msgid "Reading tags failed" +msgstr "A meta adatokat nem lehet elolvasni" + +#: convert.cpp:1443 convert.cpp:1453 replaygainfilelist.cpp:1025 +msgid "Killing process ..." +msgstr "Folyamat befejezése ..." + +#: convert.cpp:1446 replaygainfilelist.cpp:1028 +msgid "Killing process failed. Stopping after files are completed ..." +msgstr "" +"Hiba a folyamat befejezésekor. A fájlok elkészülése után lehet megállítani " +"..." + +#: convert.cpp:1468 +msgid "Removing file from conversion list. Exit code %1" +msgstr "Fájl eltávolítása a konvertálási listáról. Kilépési kód %1" + +#: convert.cpp:1475 +msgid "Executing command: \"%1\"" +msgstr "Végrehajtandó parancs: \"%1\"" + +#: cuesheeteditor.cpp:29 +msgid "Cuesheet Editor" +msgstr "Cue információ szerkesztő" + +#: cuesheeteditor.cpp:76 +msgid "Generate" +msgstr "Elkészítés" + +#: cuesheeteditor.cpp:82 +msgid "Format" +msgstr "Formátum" + +#: cuesheeteditor.cpp:88 +msgid "Shift Title/Performer" +msgstr "Cím/Előadó megcserélése" + +#: cuesheeteditor.cpp:113 +msgid "" +"

With this small tool you can process cue files as they are used for " +"burning music mixes and for organizing them in media players like " +"amaroK.

You can generate a new file by pasting text into the input " +"area. It must be formated the following way:

Title - Artist " +"[time]
Title - Artist [3:25]
Title - Artist [2:37]
...
A tip: " +"Use kwrite and regular expressions to format it this way.

" +msgstr "" +"

Ezzel a kicsi eszközzel cue fájlokat tudsz szerkeszteni, ezt zenék " +"keverésére és szervezésére használják, médiák lejátszására inkább az amaroK-" +"ot.

Létre tudsz hozni egy új fájlt úgy, hogy szöveget írsz az " +"beviteli területbe. Ezt a következő módon kell megformázni:

Cím - " +"Művész [idő]
Cím - Művész [3:25]
Cím - Művész [2:37]
...
Egy " +"tipp:Használd a kwrite-ot és reguláris kifejezéseket arra, hogy így " +"formázzák a szöveget.

" + +#: cuesheeteditor.cpp:114 +msgid "Cuesheet Editor - Help" +msgstr "Cue információ szerkesztő - Súgó" + +#: dirdialog.cpp:24 +msgid "Add folder" +msgstr "Mappa hozzáadása" + +#: dirdialog.cpp:33 +msgid "Directory:" +msgstr "Könyvtár:" + +#: dirdialog.cpp:63 +msgid "Select all" +msgstr "Mindet kijelöl" + +#: dirdialog.cpp:69 +msgid "Select none" +msgstr "Nincs kijelölés" + +#: dirdialog.cpp:75 +msgid "Recursive" +msgstr "Rekurzívan" + +#: dirdialog.cpp:106 dirdialog.cpp:133 +msgid "Choose a directory" +msgstr "Válasszon egy könyvtárat" + +#: filelist.cpp:70 filelist.cpp:137 filelist.cpp:736 filelist.cpp:737 +msgid "Input" +msgstr "Bemenet" + +#: filelist.cpp:170 +msgid "Edit options ..." +msgstr "Opciók szerkesztése ..." + +#: filelist.cpp:171 +msgid "Start conversion" +msgstr "Konvertálás indítása" + +#: filelist.cpp:172 +msgid "Stop conversion" +msgstr "Konvertálás leállítása" + +#: filelist.cpp:184 +msgid "" +"

File List

Select your desired output options in " +"the form above and add some files.
You can add files by clicking on " +"\"Add files ...\" or dropping them here.
" +msgstr "" +"

Fájllista

Válassza ki a kívánt kimeneti opciókat " +"és adja hozzá a fájlokhoz.
Kattintson a \"Fájlok hozzáadása ...\" gombra " +"vagy húzza a fájlokat ide.
" + +#: filelist.cpp:578 filelist.cpp:593 +msgid "Audio CD (%1)" +msgstr "Audió CD (%1)" + +#: filelist.cpp:609 filelist.cpp:624 +msgid "Full audio CD (%1)" +msgstr "Teljes audió CD (%1)" + +#: filelist.cpp:638 filelist.cpp:650 filelist.cpp:955 +msgid "Stopped" +msgstr "Megállítva" + +#: filelist.cpp:641 filelist.cpp:650 filelist.cpp:955 +msgid "Failed" +msgstr "Hiba" + +#: filelist.cpp:650 filelist.cpp:726 filelist.cpp:860 filelist.cpp:955 +msgid "Will be skipped" +msgstr "Ki lesz hagyva" + +#: filelist.cpp:651 filelist.cpp:696 filelist.cpp:729 filelist.cpp:861 +#: filelist.cpp:918 filelist.cpp:956 progressindicator.cpp:49 +msgid "Waiting" +msgstr "Kérem várjon" + +#: filelist.cpp:733 +msgid "Converting" +msgstr "Konvertálás" + +#: logger.cpp:136 +msgid "Finished logging" +msgstr "Naplózás befejezve" + +#: logviewer.cpp:83 +msgid "Log Viewer" +msgstr "Naplómegjelenítő" + +#: logviewer.cpp:90 +msgid "Job/File" +msgstr "Feladat/Fájl" + +#: main.cpp:12 +msgid "" +"soundKonverter is a frontend to various sound en- and decoding programs." +msgstr "" +"A soundKonverter egy grafikus felület a különböző audió-(de)kódoló " +"programokhoz." + +#: main.cpp:18 +msgid "Open the Replay Gain tool an add all given files" +msgstr "" +"A Replay Gain eszköz megnyitása és az összes adott fájlhoz hozzáfűzése" + +#: main.cpp:20 +msgid "List all tracks on the cd drive , 'auto' will search for a cd" +msgstr "" +"A cd meghajtón található összes szám listája, 'auto' CD-t keres" + +#: main.cpp:21 +msgid "Add all files using the given profile" +msgstr "Minden fájl hozzáadása ami használja az adott profilt" + +#: main.cpp:22 +msgid "Add all files using the given format" +msgstr "Minden fájl hozzáadása ami használja az adott formátumot" + +#: main.cpp:23 +msgid "Output all files to " +msgstr "Összes kimeneti fájl mentése a könyvtárba" + +#: main.cpp:24 +msgid "Start soundKonverter invisible" +msgstr "soundKonverter indítása láthatatlanként" + +#: main.cpp:25 +msgid "" +"Close soundKonverter after all files are converted (enabled when using '--" +"invisible')" +msgstr "" +"A soundKonverter bezárása, ha az összes fájl konvertálása kész " +"(engedélyezve, ha a 'láthatatlan' mód aktív)" + +#: main.cpp:26 +msgid "Execute after each file has been converted" +msgstr "" +"Az parancs végrehajtása, miután az összes fájl konvertálása kész" + +#: main.cpp:27 +msgid "Audio file(s) to append to the file list" +msgstr "Audió fájl(ok) hozzáadása a fájllistához" + +#: main.cpp:33 +msgid "soundKonverter" +msgstr "soundKonverter" + +#: options.cpp:127 +msgid "" +"soundKonverter either found new backends or misses some.\n" +"Click on this button in order to open the configuration dialog." +msgstr "" +"A soundKonverter vagy új kiszolgálókat talált vagy eldobott valamennyit.\n" +"Kattintson erre a gombra, a konfigurációs párbeszédablak megnyitásához." + +#: options.cpp:136 +msgid "Advanced Options" +msgstr "Haladó beállítások" + +#: optionsdetailed.cpp:45 +msgid "Convert" +msgstr "Konvertálás" + +#: optionsdetailed.cpp:73 +msgid "" +"vbr - variable bitrate\n" +"abr - average bitrate\n" +"cbr - constant bitrate" +msgstr "" +"vbr - változó bitráta\n" +"abr - átlagos bitráta\n" +"cbr - állandó bitráta" + +#: optionsdetailed.cpp:83 +msgid "Bitrate range" +msgstr "Bitráta tartomány" + +#: optionsdetailed.cpp:84 +msgid "" +"Use it only if, you know what you are doing, you could reduce the quality." +msgstr "" +"Csak akkor használja, ha tudja, hogy mit tesz, csökkenthetné a minőséget." + +#: optionsdetailed.cpp:119 +msgid "Resample" +msgstr "Resample" + +#: optionsdetailed.cpp:147 +msgid "Channels" +msgstr "Csatornák" + +#: optionsdetailed.cpp:170 +msgid "Add a Replay Gain tag to the converted file." +msgstr "Replay Gain címke hozzáadása a konvertált fájlhoz." + +#: optionsdetailed.cpp:171 +msgid "" +"Replay Gain is a volume correction technique. A volume difference is " +"calculated and stored in a tag. This way audio players can automatically " +"adjust the volume and the original music data is not modified (like at " +"normalization)." +msgstr "" +"A Replay Gain egy hangerő javító technika. Kiszámítja a hangerőkülönbséget " +"és egy meta adatban tárolja. Erre a zenelejátszók automatikusan beállítják a " +"kötetet, de az eredeti zenei adatokat nem módosítják (mint a normalizálás)." + +#: optionsdetailed.cpp:192 +msgid "Save current options as a profile" +msgstr "A profil jelenlegi beállításainak mentése" + +#: optionsdetailed.cpp:208 +msgid "Command" +msgstr "Parancs" + +#: optionsdetailed.cpp:219 +#, c-format +msgid "%p: The parameters generated by soundKonverter" +msgstr "%p: A paramétereket a soundKonverter generálta" + +#: optionsdetailed.cpp:225 +#, c-format +msgid "%i: The input file ; %o: The output file" +msgstr "%i: A forrásfájl ; %o: A célfájl" + +#: optionsdetailed.cpp:353 +msgid "New profile" +msgstr "Új profil" + +#: optionsdetailed.cpp:353 +msgid "Enter a name for the new profile:" +msgstr "Adja meg az új profil nevét:" + +#: optionsdetailed.cpp:368 +msgid "You cannot overwrite the built-in profiles." +msgstr "Nem lehet felülírni a beépített profilokat." + +#: optionsdetailed.cpp:369 optionsdetailed.cpp:379 +msgid "Profile already exists" +msgstr "A profil már létezik" + +#: optionsdetailed.cpp:378 +msgid "" +"A profile with this name already exists.\n" +"\n" +"Do you want to overwrite the existing one?" +msgstr "" +"Egy profil már létezik egy ilyen névvel.\n" +"\n" +"Szeretné, hogy felülírjam?" + +#: optionsdetailed.cpp:473 optionsdetailed.cpp:628 +msgid "Unchanged" +msgstr "Változatlan" + +#: optionsdetailed.cpp:483 optionsdetailed.cpp:604 +msgid "Undefined" +msgstr "Meghatározatlan" + +#: optionsdetailed.cpp:561 optionsdetailed.cpp:619 +msgid "Kilobit per second" +msgstr "Kilobit per másodperc" + +#: optionsdetailed.cpp:689 +msgid "" +"This is a relative quality between 0 and 100.\n" +"The higher this number the higher is the quality.\n" +"soundKonverter will convert it into the file format's quality format.\n" +"See the \"What's this?\" for more informations.\n" +"\n" +"Current parameter: \"%1\"" +msgstr "" +"Ez 0 és 100 között egy viszonylagos minőség. \n" +"A magasabb szám, jelenti a magasabb minőséget.\n" +"A soundKonverter át fogja alakítani ezt az állományformátumot minőségi " +"formátumúvá\n" +"Nézze meg a \"Mi ez?\" gombot több információért.\n" +"\n" +"Current parameter: \"%1\"" + +#: optionseditor.cpp:28 +msgid "Options Editor" +msgstr "Beállítás szerkesztő" + +#: optionseditor.cpp:55 +msgid "Conversion" +msgstr "Konvertálás" + +#: optionseditor.cpp:55 +msgid "Conversion options" +msgstr "Konvertálás beállításai" + +#: optionseditor.cpp:59 +msgid "Choose your prefered output options and click on \"Close\"!" +msgstr "" +"Válassza ki a kívánt kimeneti opciókat és kattintson a \"Bezárás\" gombra!" + +#: optionseditor.cpp:70 +msgid "Edit conversion options" +msgstr "Konvertálás beállításinak szerkesztése" + +#: optionseditor.cpp:79 +msgid "Tags" +msgstr "Meta adatok" + +#: optionseditor.cpp:103 +msgid "Track No.:" +msgstr "Szám Nr.:" + +#: optionseditor.cpp:256 +msgid "Edit tags" +msgstr "Meta adatok szerkesztése" + +#: optionseditor.cpp:330 +msgid "No file selected" +msgstr "Nincs fájl kiválasztva" + +#: optionseditor.cpp:358 +msgid "" +"The tags could not be read, because this file isn't a local one.\n" +"soundKonverter will try to read the tags, when it is about to convert the " +"file.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags." +msgstr "" +"A meta adatokat nem lehet elolvasni, ha a fájl nem helyi.\n" +"A soundKonverter meg fogja próbálni olvasni a meta adatokat mikor, " +"konvertálja a fájlt.\n" +"Ha szerkeszteni szeretné a meta adatokat, akkor kattintson a gombra.\n" +"De akkor a soundKonverter már nem keres meta adatokat az elolvasáshoz." + +#: optionseditor.cpp:367 +msgid "" +"Reading the tags of this file failed.\n" +"soundKonverter will try to read the tags a second time, when it is about to " +"convert the file.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags a second time." +msgstr "" +"A meta adatokat nem lehet elolvasni.\n" +"A soundKonverter meg fogja próbálni olvasni a meta adatokat mikor, " +"konvertálja a fájlt.\n" +"Ha szerkeszteni szeretné a meta adatokat, akkor kattintson a gombra.\n" +"De akkor a soundKonverter már nem keres meta adatokat az elolvasáshoz." + +#: optionseditor.cpp:387 +msgid "%1 Files" +msgstr "%1 Fájl" + +#: optionseditor.cpp:402 +msgid "" +"You have selected multiple files with different conversion options.\n" +"You can change the options of all files by hitting the button below." +msgstr "" +"Különböző átalakítási opciókkal választott ki több fájlt.\n" +"Meg tudja változtatni minden fájl opcióit azáltal, hogy a gombra kattint." + +#: optionseditor.cpp:408 +msgid "" +"Reading the tags of one or more files failed.\n" +"soundKonverter will try to read the tags a second time, when it is about to " +"convert the files.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags a second time." +msgstr "" +"A meta adatokat egy vagy több fájlnál nem lehet elolvasni.\n" +"A soundKonverter meg fogja próbálni olvasni a meta adatokat mikor, " +"konvertálja a fájlt.\n" +"Ha szerkeszteni szeretné a meta adatokat, akkor kattintson a gombra.\n" +"De akkor a soundKonverter már nem keres meta adatokat az elolvasáshoz." + +#: optionsrequester.cpp:18 +msgid "Choose output options" +msgstr "Válassza ki a kimenetei opciókat" + +#: optionsrequester.cpp:28 +msgid "Click on \"Ok\" to add the files to the list in the main window!" +msgstr "Kattintson az \"Ok\" gomra, a fájlok listához adásához a főablakban!" + +#: optionsrequester.cpp:43 +msgid "" +"Warning: If you select \"wav\" as output format, your wav files will not be " +"added to the list." +msgstr "" +"Figyelmeztetés: Ha a \"wav\" kimeneti formátumot választotta, akkor nem " +"lehet a wav fájl a listához hozzáadni" + +#: optionsrequester.cpp:59 +msgid "Ok" +msgstr "Ok" + +#: optionssimple.cpp:64 +msgid "Remove the selected profile" +msgstr "A kijelölt profil törlése" + +#: optionssimple.cpp:70 optionssimple.cpp:90 +msgid "Info" +msgstr "Információ" + +#: optionssimple.cpp:71 +msgid "Information about the selected profile" +msgstr "Információ a kiválasztott profilokról" + +#: optionssimple.cpp:78 +msgid "Output format" +msgstr "Célformátum" + +#: optionssimple.cpp:91 +msgid "Information about the selected file format" +msgstr "Információk a kiválasztott formátumokról" + +#: optionssimple.cpp:157 +msgid "" +"This produces sound files of a very low quality.\n" +"That can be useful, if you have a mobile device, where your memory cell is " +"limited. It is not recommended to save your music in this quality without a " +"copy with higher quality.\n" +"It can also be used to save audio files with voices." +msgstr "" +"Ez nagyon alacsony minőséget produkál hangállományokhoz.\n" +"Az hasznos lehet, ha van egy mobil eszköz, aminek korlátozott a kapacitása. " +"Nem ajánlott magasabb minőséggel elmenteni a zenét ebben a minőségben " +"másolat nélkül.\n" +"Szintén hasznos tud lenni hangokkal elmenteni hangállományokat." + +#: optionssimple.cpp:158 optionssimple.cpp:163 optionssimple.cpp:168 +#: optionssimple.cpp:173 optionssimple.cpp:178 optionssimple.cpp:183 +#: optionssimple.cpp:188 optionssimple.cpp:193 +msgid "Profile" +msgstr "Profil" + +#: optionssimple.cpp:162 +msgid "" +"This produces sound files of a low quality.\n" +"That can be useful if you habe a mobile device where your memory cell is " +"limited. It is not recommended to save your music in this quality without a " +"copy with higher quality." +msgstr "" +"Ez alacsony minőséget produkál hangállományokhoz.\n" +"Az hasznos lehet, ha van egy mobil eszköz, aminek korlátozott a kapacitása. " +"Nem ajánlott magasabb minőséggel elmenteni a zenét ebben a minőségben " +"másolat nélkül." + +#: optionssimple.cpp:167 +msgid "" +"This produces sound files of a medium quality.\n" +"If your disc space is limited, you can use this to save your music." +msgstr "" +"Ez közepes minőséget produkál hangállományokhoz.\n" +"Ha nincs elég lemezterülete, akkor használja ezt a zenék mentésére." + +#: optionssimple.cpp:172 +msgid "" +"This produces sound files of a high quality.\n" +"If you have enough disc space available, you can use this to save your music." +msgstr "" +"Ez magas minőséget produkál hangállományokhoz.\n" +"Akkor használja ezt az zenék mentésére, ha elég lemezterület áll " +"rendelkezésére." + +#: optionssimple.cpp:177 +msgid "" +"This produces sound files of a very high quality.\n" +"You should only use this, if you are a quality freak and have enough disc " +"space available." +msgstr "" +"Ez nagyon magas minőséget produkál hangállományokhoz.\n" +"Akkor használja ezt az zenék mentésére, ha fontos a minőség és elég " +"lemezterület áll rendelkezésére." + +#: optionssimple.cpp:182 +msgid "" +"This produces files, that have exact the same quality as the input files.\n" +"This files are very big and definitely only for quality freaks." +msgstr "" +"Ez hasonló minőséget produkál a bemeneti fájlokéval.\n" +"Ezek a fájlok nagyon nagy méretűek és csak akkor használjuk, ha nagyon " +"fontos a minőség." + +#: optionssimple.cpp:187 +msgid "" +"This produces two files. One lossy compressed playable file and one " +"correction file.\n" +"Both files together result in a file that is equivalent to the input file." +msgstr "" +"Ez két fájlt produkál. Egy veszteségesen tömörítettet és egy javító fájlt.\n" +"Ha mindkét fájlt megőrizzük, akkor az egyenértékű a bemeneti állománnyal." + +#: optionssimple.cpp:192 +msgid "You can define your own profile in the \"detailed\" tab." +msgstr "Meg tudod határozni a saját profilodat a \"Részletes\" fülön." + +#: optionssimple.cpp:205 +msgid "Do you really want to remove the profile: %1" +msgstr "Valóban törölni szeretné a(z) '%1' profilt?" + +#: optionssimple.cpp:206 +msgid "Remove profile?" +msgstr "Profil törlése?" + +#: optionssimple.cpp:234 +msgid "" +"

Wave is a file format, that doesn't compress it's audio data.

\n" +"

So the quality is very high, but the file size is enormous. It is widely " +"spread and should work with every audio player.

\n" +"http://en.wikipedia.org/wiki/Wav" +msgstr "" +"

A wav egy fájlformátum, amivel nem lehet audió fájlokat tömöríteni.

\n" +"

Ezért a minősége nagyon magas, ettől a fájlméret is. Széles körben " +"elterjedt és minden zenelejátszóval működik.

\n" +"
http://hu.wikipedia.org/wiki/Wav" + +#: optionssimple.cpp:235 optionssimple.cpp:242 +msgid "File format" +msgstr "Fájlformátum" + +#: outputdirectory.cpp:44 +msgid "By meta data" +msgstr "Meta adatok által" + +#: outputdirectory.cpp:45 +msgid "Source directory" +msgstr "Forráskönyvtár" + +#: outputdirectory.cpp:46 +msgid "Specify output directory" +msgstr "Célkönyvtár részletezése" + +#: outputdirectory.cpp:47 +msgid "Copy directory structure" +msgstr "Könyvtárstruktúra másolása" + +#: outputdirectory.cpp:61 +msgid "Clear the directory input field" +msgstr "Könyvtár bemeneti mező törlése" + +#: outputdirectory.cpp:81 outputdirectory.cpp:345 +msgid "Choose an output directory" +msgstr "Válassza ki a célkönyvtárat" + +#: outputdirectory.cpp:87 +msgid "Open Konqueror with the output directory" +msgstr "Célkönyvtár megnyitása a Konqueror-ral." + +#: outputdirectory.cpp:184 +msgid "Unknown Artist" +msgstr "Ismeretlen előadó" + +#: outputdirectory.cpp:188 +msgid "Unknown Album" +msgstr "Ismeretlen album" + +#: outputdirectory.cpp:192 +msgid "No Comment" +msgstr "Nincs megjegyzés" + +#: outputdirectory.cpp:199 +msgid "Unknown Genre" +msgstr "Imeretlen műfaj" + +#: outputdirectory.cpp:206 +msgid "Unknown Composer" +msgstr "Ismeretlen zeneszerző" + +#: outputdirectory.cpp:210 +msgid "Unknown Title" +msgstr "Ismeretlen cím" + +#: outputdirectory.cpp:264 +msgid "new" +msgstr "új" + +#: outputdirectory.cpp:406 +msgid "Name all converted files according to the specified pattern" +msgstr "Minden konvertált fájl elnevezése a részletezett minta szerint" + +#: outputdirectory.cpp:408 +msgid "" +"

The following strings are wildcards, that will be replaced by the " +"information in the meta data:

%a - Artist
%b - Album
%c - " +"Comment
%d - Disc number
%g - Genre
%n - Track number
%p - " +"Composer
%t - Title
%y - Year
%f - Original file name

" +msgstr "" +"

A következő sztringek helyettesítők, ezeket fel fogják váltani az " +"információk a meta adatokban:

%a - Művész
%b - Album
%c - " +"Megjegyzés
%d - CD sorszáma
%g - Műfaj
%n - Darab sorszáma
%p - " +"Zeneszerző
%t - Cím
%y - Év
%f - Eredeti fájlnév

" + +#: outputdirectory.cpp:420 +msgid "" +"Output all converted files into the same directory as the original files" +msgstr "Az összes konvertált fájl mentése az eredeti fájlok könyvtárába" + +#: outputdirectory.cpp:434 +msgid "Output all converted files into the specified output directory" +msgstr "Az összes konvertált fájl mentése a megadott könyvtárba" + +#: outputdirectory.cpp:448 +msgid "Copy the whole directory structure for all converted files" +msgstr "Az egész könyvtárszerkezetet mentése az összes konvertált fájlhoz" + +#: paranoia.cpp:214 +msgid "MB" +msgstr "MB" + +#: paranoia.cpp:215 +msgid "KB" +msgstr "KB" + +#: paranoia.cpp:216 +msgid "Bytes" +msgstr "Bájt" + +#: progressindicator.cpp:33 +msgid "Speed" +msgstr "Sebesség" + +#: progressindicator.cpp:41 +msgid "Time remaining" +msgstr "Hátralévő idő" + +#: progressindicator.cpp:95 progressindicator.cpp:96 replaygainscanner.cpp:216 +msgid "Finished" +msgstr "Kész" + +#. i18n: file ./soundkonverterui.rc line 13 +#: rc.cpp:3 +#, no-c-format +msgid "&Conversion" +msgstr "&Konvertálás" + +#: replaygain.cpp:88 +msgid "Executing" +msgstr "Végrehajtás" + +#: replaygainfilelist.cpp:137 replaygainfilelist.cpp:147 +#: replaygainfilelist.cpp:150 replaygainfilelist.cpp:180 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:669 +#: replaygainfilelist.cpp:672 replaygainfilelist.cpp:704 +#: replaygainfilelist.cpp:707 replaygainfilelist.cpp:734 +#: replaygainfilelist.cpp:737 replaygainfilelist.cpp:940 +msgid "Album" +msgstr "Album" + +#: replaygainfilelist.cpp:213 +msgid "Calculate Replay Gain tags" +msgstr "Replay Gain adatok kiszámítása" + +#: replaygainfilelist.cpp:214 +msgid "Remove Replay Gain tags" +msgstr "Replay Gain adatok eltávolítása" + +#: replaygainfilelist.cpp:217 replaygainfilelist.cpp:825 +msgid "New album" +msgstr "Új album" + +#: replaygainfilelist.cpp:218 +msgid "Open all albums" +msgstr "Összes album megnyitása" + +#: replaygainfilelist.cpp:219 +msgid "Cloase all albums" +msgstr "Összes album bezárása" + +#: replaygainfilelist.cpp:223 +msgid "" +"

Replay Gain Tool

With this tool you can add Replay " +"Gain tags to your audio files and remove them.
Replay Gain adds a volume " +"correction information to the files so that they can be played at an equal " +"volume level.
" +msgstr "" +"

Replay Gain Eszköz

Ezzel az eszközzel Replay Gain " +"adatokat tud az audió fájlokhoz hozzáadni és eltávolítani.
A Replay Gain " +"hangerő javító információkat fűz a fájlokhoz, hogy egyenlő hangerőszinttel " +"lehessen lejátszani azokat.
" + +#: replaygainfilelist.cpp:494 +msgid "You can't place files of different formats in the same 'album'." +msgstr "Nem lehet ugyanabba az albumba tenni a különböző formátumú fájlokat." + +#: replaygainfilelist.cpp:494 +msgid "Different file formats" +msgstr "Különböző fájlformátumok" + +#: replaygainfilelist.cpp:987 +msgid "Removing Replay Gain" +msgstr "Replay Gain eltávolítása" + +#: replaygainfilelist.cpp:1148 +msgid "built-in" +msgstr "beépített" + +#: replaygainscanner.cpp:33 replaygainscanner.cpp:216 +#: replaygainscanner.cpp:231 +msgid "Replay Gain Tool" +msgstr "Replay Gain Eszköz" + +#: replaygainscanner.cpp:43 +msgid "Add Folder ..." +msgstr "Könyvtár hozzáadása ..." + +#: replaygainscanner.cpp:44 +msgid "Add Files ..." +msgstr "Fájlok hozzáadása ..." + +#: replaygainscanner.cpp:52 +msgid "Force recalculation" +msgstr "Erős újraszámítás" + +#: replaygainscanner.cpp:53 +msgid "" +"Recalculate Replay Gain tag for files that already have a Replay Gain tag " +"set." +msgstr "" +"Replay Gain adatok újraszámítása azokhoz a fájlokhoz is amelyeknek már van." + +#: replaygainscanner.cpp:102 +msgid "Tag untagged" +msgstr "Replay Gain számítás" + +#: replaygainscanner.cpp:103 +msgid "" +"Calculate Replay Gain tag for all files in the file list without Replay Gain " +"tag." +msgstr "" +"Replay Gain adatok kiszámítása az összes Replay Gain adatok nélküli " +"fájlokhoz a fájllistában." + +#: replaygainscanner.cpp:109 +msgid "Untag tagged" +msgstr "Replay Gain eltávolítása" + +#: replaygainscanner.cpp:110 +msgid "Remove the Replay Gain tag from all files in the file list." +msgstr "Replay Gain adatok törlése az összes fájllistában található fájlból." + +#: replaygainscanner.cpp:151 +msgid "Choose files!" +msgstr "Válassza ki a fájlokat!" + +#: soundkonverter.cpp:107 +msgid "Choose your prefered output options and click on \"Add files ...\"!" +msgstr "" +"Válassza ki a kívánt kimeneti opciókat és kattintson a \"Fájlok hozzáadása " +"...\" gombra!" + +#: soundkonverter.cpp:110 soundkonverter.cpp:405 soundkonverter.cpp:448 +msgid "&Start conversion" +msgstr "Konvertálás &indítása" + +#: soundkonverter.cpp:112 +msgid "&Replay Gain Tool ..." +msgstr "&Replay Gain Eszköz ..." + +#: soundkonverter.cpp:114 +msgid "C&uesheet Editor ..." +msgstr "C&ue információ szerkesztő ..." + +#: soundkonverter.cpp:115 +msgid "Show &Log ..." +msgstr "&Napló mutatása ..." + +#: soundkonverter.cpp:118 +msgid "S&top after current file is complete" +msgstr "L&eállítás, miután az aktuális fájl elkészült" + +#: soundkonverter.cpp:119 +msgid "&Continue after current file is complete" +msgstr "&Folyatatás, miután az aktuális fájl elkészült" + +#: soundkonverter.cpp:120 +msgid "Stop &immediately" +msgstr "Leállítás &azonnal" + +#: soundkonverter.cpp:148 +msgid "A&dd Files ..." +msgstr "&Fájlok hozzáadása ..." + +#: soundkonverter.cpp:149 +msgid "Add &Folder ..." +msgstr "Könyvtár &hozzáadása ..." + +#: soundkonverter.cpp:150 +msgid "Add CD &tracks ..." +msgstr "CD s&zámok hozzáadása ..." + +#: soundkonverter.cpp:151 +msgid "Add &URL ..." +msgstr "&URL hozzáadása ..." + +#: soundkonverter.cpp:154 +msgid "L&oad file list" +msgstr "Fájllista be&töltése" + +#: soundkonverter.cpp:155 +msgid "Sa&ve file list" +msgstr "Fájllista m&entése" + +#: soundkonverter.cpp:229 +msgid "Add files ..." +msgstr "Fájlok hozzáadása ..." + +#: soundkonverter.cpp:230 +msgid "Add folder ..." +msgstr "Könyvtár hozzáadása ..." + +#: soundkonverter.cpp:231 +msgid "Add CD tracks ..." +msgstr "CD szám hozzáadása ..." + +#: soundkonverter.cpp:232 +msgid "Add URL ..." +msgstr "URL hozzáadása ..." + +#: soundkonverter.cpp:240 +msgid "Start" +msgstr "Indítás" + +#: soundkonverter.cpp:417 +msgid "&Start queue" +msgstr "&Indítás később" + +#: soundkonverter.cpp:489 +msgid "Choose files to convert" +msgstr "Válassza ki a fájlokat a konvertáláshoz" + +#: soundkonverter.cpp:617 +msgid "Open URL" +msgstr "URL megnyitása" + +#: soundkonverter.cpp:617 +msgid "Enter a URL:" +msgstr "Adjon meg egy URL-t:" diff --git a/po/it.po b/po/it.po new file mode 100644 index 0000000..5ff479e --- /dev/null +++ b/po/it.po @@ -0,0 +1,1632 @@ +# Italian translation for soundkonverter +# Copyright (c) 2008 Rosetta Contributors and Canonical Ltd 2008 +# This file is distributed under the same license as the soundkonverter package. +# FIRST AUTHOR , 2008. +# +msgid "" +msgstr "" +"Project-Id-Version: soundkonverter\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2008-02-25 17:22+0100\n" +"PO-Revision-Date: 2008-02-26 17:15+0000\n" +"Last-Translator: Edgardo Franzin \n" +"Language-Team: Italian \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2008-04-06 10:52+0000\n" +"X-Generator: Launchpad (build Unknown)\n" + +#: _translatorinfo.cpp:1 +msgid "Your names" +msgstr ",Launchpad Contributions:,Edgardo Franzin" + +#: _translatorinfo.cpp:3 +msgid "Your emails" +msgstr ",," + +#: cddb.cpp:368 +msgid "No Title" +msgstr "Nessun titolo" + +#: cddb.cpp:372 cdmanager.cpp:97 convert.cpp:513 convert.cpp:514 +#: convert.cpp:515 convert.cpp:517 convert.cpp:519 convert.cpp:520 +#: convert.cpp:1547 convert.cpp:1557 convert.cpp:1571 +#: replaygainfilelist.cpp:136 replaygainfilelist.cpp:137 +#: replaygainfilelist.cpp:144 replaygainfilelist.cpp:150 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:666 +#: replaygainfilelist.cpp:672 replaygainfilelist.cpp:701 +#: replaygainfilelist.cpp:707 replaygainfilelist.cpp:731 +#: replaygainfilelist.cpp:737 replaygainfilelist.cpp:945 +msgid "Unknown" +msgstr "Sconosciuto" + +#: cddb.cpp:380 +msgid "Track %1" +msgstr "Traccia %1" + +#: cddb.cpp:479 +msgid "Searching local cddb entry ..." +msgstr "Cerca voce nel database CDDB locale..." + +#: cddb.cpp:504 +msgid "Searching remote cddb entry ..." +msgstr "Ricerca voce CDDB remoto..." + +#: cddb.cpp:528 +msgid "Found exact match cddb entry ..." +msgstr "Esatta corrispondenza CDDB trovata..." + +#: cddb.cpp:585 +msgid "Found close cddb entry ..." +msgstr "Voce simile CDDB trovata..." + +#: cddb.cpp:608 +msgid "CDDB Matches" +msgstr "Corrispondenze CDDB" + +#: cddb.cpp:608 +msgid "Several close CDDB entries found. Choose one:" +msgstr "Molte voci CDDB simili trovate. Scegline una:" + +#: cdmanager.cpp:46 filelist.cpp:618 +msgid "Audio CD" +msgstr "CD audio" + +#: cdmanager.cpp:46 +msgid "Several audio CDs found. Choose one:" +msgstr "Trovati più CD audio. Scegline uno:" + +#: cdmanager.cpp:104 +msgid "No audio CD found." +msgstr "Nessun CD audio trovato." + +#: cdopener.cpp:41 +msgid "Add CD tracks" +msgstr "Aggiungi tracce dal CD" + +#: cdopener.cpp:52 cdopener.cpp:178 optionseditor.cpp:123 +msgid "Artist:" +msgstr "Artista:" + +#: cdopener.cpp:57 cdopener.cpp:480 cdopener.cpp:485 cdopener.cpp:538 +#: cdopener.cpp:567 cdopener.cpp:682 cdopener.cpp:697 +msgid "Various Artists" +msgstr "Artisti vari" + +#: cdopener.cpp:66 cdopener.cpp:193 optionseditor.cpp:138 +msgid "Composer:" +msgstr "Compositore:" + +#: cdopener.cpp:71 cdopener.cpp:496 cdopener.cpp:501 cdopener.cpp:548 +#: cdopener.cpp:579 cdopener.cpp:683 cdopener.cpp:698 +msgid "Various Composer" +msgstr "Compositori vari" + +#: cdopener.cpp:83 optionseditor.cpp:158 +msgid "Album:" +msgstr "Album:" + +#: cdopener.cpp:91 optionseditor.cpp:178 +msgid "Disc No.:" +msgstr "Disco:" + +#: cdopener.cpp:96 optionseditor.cpp:194 +msgid "Year:" +msgstr "Anno:" + +#: cdopener.cpp:100 optionseditor.cpp:210 +msgid "Genre:" +msgstr "Genere:" + +#: cdopener.cpp:114 cdopener.cpp:532 filelist.cpp:578 filelist.cpp:587 +#: replaygainfilelist.cpp:136 replaygainfilelist.cpp:141 +#: replaygainfilelist.cpp:144 replaygainfilelist.cpp:178 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:663 +#: replaygainfilelist.cpp:666 replaygainfilelist.cpp:698 +#: replaygainfilelist.cpp:701 replaygainfilelist.cpp:728 +#: replaygainfilelist.cpp:731 +msgid "Track" +msgstr "Traccia" + +#: cdopener.cpp:115 cdopener.cpp:568 cdopener.cpp:571 cdopener.cpp:607 +msgid "Artist" +msgstr "Artista" + +#: cdopener.cpp:116 cdopener.cpp:580 cdopener.cpp:583 cdopener.cpp:620 +msgid "Composer" +msgstr "Compositore" + +#: cdopener.cpp:117 cdopener.cpp:594 +msgid "Title" +msgstr "Titolo" + +#: cdopener.cpp:118 +msgid "Time" +msgstr "Durata" + +#: cdopener.cpp:131 +msgid "No track selected" +msgstr "Nessuna traccia selezionata" + +#: cdopener.cpp:159 optionseditor.cpp:88 +msgid "Title:" +msgstr "Titolo:" + +#: cdopener.cpp:212 optionseditor.cpp:235 +msgid "Comment:" +msgstr "Commento:" + +#: cdopener.cpp:242 +msgid "Save cuesheet ..." +msgstr "Salva lista CUE..." + +#: cdopener.cpp:250 +msgid "Add all tracks" +msgstr "Aggiungi tutte le tracce" + +#: cdopener.cpp:251 +msgid "Add selected tracks" +msgstr "Aggiungi le tracce selezionate" + +#: cdopener.cpp:253 +msgid "Add full CD as one file" +msgstr "Unisci tutto il CD in un unico file" + +#: cdopener.cpp:440 +msgid "All tracks" +msgstr "Tutti i brani" + +#: cdopener.cpp:443 +msgid "Tracks" +msgstr "Tracce" + +#: cdopener.cpp:742 +msgid "" +"A file with this name already exists.\n" +"\n" +"Do you want to overwrite the existing one?" +msgstr "" +"Esiste già un file con lo stesso nome.\n" +"Vuoi sovrascriverlo?" + +#: cdopener.cpp:743 +msgid "File already exists" +msgstr "File già esistente" + +#: config.cpp:103 config.cpp:104 config.cpp:1197 config.cpp:1206 +#: config.cpp:1237 configgeneralpage.cpp:37 configgeneralpage.cpp:60 +#: configgeneralpage.cpp:62 configgeneralpage.cpp:269 +#: configgeneralpage.cpp:273 configgeneralpage.cpp:297 +#: configgeneralpage.cpp:306 configgeneralpage.cpp:316 options.cpp:153 +#: optionsdetailed.cpp:363 optionssimple.cpp:49 optionssimple.cpp:221 +#: optionssimple.cpp:518 soundkonverter.cpp:308 soundkonverter.cpp:309 +msgid "Last used" +msgstr "Ultimo utilizzo" + +#: config.cpp:508 +msgid "Convert with soundKonverter ..." +msgstr "Converto con soundKonverter..." + +#: config.cpp:543 +msgid "Add Replay Gain with soundKonverter ..." +msgstr "Aggiungi normalizza con soundKonverter..." + +#: config.cpp:1228 config.cpp:1229 configgeneralpage.cpp:57 +#: configgeneralpage.cpp:302 convert.cpp:431 filelist.cpp:1379 +#: optionsdetailed.cpp:361 optionsdetailed.cpp:427 optionsdetailed.cpp:477 +#: optionsdetailed.cpp:527 optionsdetailed.cpp:604 optionssimple.cpp:46 +#: optionssimple.cpp:140 optionssimple.cpp:180 optionssimple.cpp:218 +#: optionssimple.cpp:407 optionssimple.cpp:515 optionssimple.cpp:535 +msgid "Lossless" +msgstr "Senza perdite" + +#: config.cpp:1232 config.cpp:1233 configgeneralpage.cpp:58 +#: configgeneralpage.cpp:312 convert.cpp:434 convert.cpp:1378 +#: filelist.cpp:1382 optionsdetailed.cpp:362 optionsdetailed.cpp:480 +#: optionsdetailed.cpp:618 optionssimple.cpp:47 optionssimple.cpp:141 +#: optionssimple.cpp:185 optionssimple.cpp:219 optionssimple.cpp:421 +#: optionssimple.cpp:430 optionssimple.cpp:516 optionssimple.cpp:544 +msgid "Hybrid" +msgstr "Ibrido" + +#: config.cpp:1245 config.cpp:1252 config.cpp:1259 config.cpp:1266 +#: config.cpp:1273 convert.cpp:403 convert.cpp:995 convert.cpp:1567 +#: filelist.cpp:139 filelist.cpp:752 filelist.cpp:1270 filelist.cpp:1351 +#: optionsdetailed.cpp:246 optionsdetailed.cpp:467 optionsdetailed.cpp:582 +#: optionsdetailed.cpp:641 optionssimple.cpp:38 optionssimple.cpp:283 +#: optionssimple.cpp:312 optionssimple.cpp:340 optionssimple.cpp:367 +#: optionssimple.cpp:394 +msgid "Quality" +msgstr "Qualità" + +#: config.cpp:1248 config.cpp:1285 convert.cpp:450 filelist.cpp:1398 +#: optionsdetailed.cpp:538 optionssimple.cpp:294 +msgid "Mono" +msgstr "Mono" + +#: config.cpp:1250 config.cpp:1287 configgeneralpage.cpp:52 +#: configgeneralpage.cpp:289 optionsdetailed.cpp:356 optionssimple.cpp:41 +#: optionssimple.cpp:135 optionssimple.cpp:155 optionssimple.cpp:213 +#: optionssimple.cpp:269 optionssimple.cpp:510 optionssimple.cpp:525 +msgid "Very low" +msgstr "Molto basso" + +#: config.cpp:1257 config.cpp:1294 configgeneralpage.cpp:53 +#: configgeneralpage.cpp:111 configgeneralpage.cpp:290 optionsdetailed.cpp:357 +#: optionssimple.cpp:42 optionssimple.cpp:136 optionssimple.cpp:160 +#: optionssimple.cpp:214 optionssimple.cpp:298 optionssimple.cpp:511 +#: optionssimple.cpp:525 +msgid "Low" +msgstr "Basso" + +#: config.cpp:1264 config.cpp:1301 configgeneralpage.cpp:54 +#: configgeneralpage.cpp:291 optionsdetailed.cpp:358 optionseditor.cpp:713 +#: optionssimple.cpp:43 optionssimple.cpp:137 optionssimple.cpp:165 +#: optionssimple.cpp:215 optionssimple.cpp:326 optionssimple.cpp:512 +#: optionssimple.cpp:526 +msgid "Medium" +msgstr "Medio" + +#: config.cpp:1271 config.cpp:1308 configgeneralpage.cpp:55 +#: configgeneralpage.cpp:292 optionsdetailed.cpp:359 optionssimple.cpp:44 +#: optionssimple.cpp:138 optionssimple.cpp:170 optionssimple.cpp:216 +#: optionssimple.cpp:353 optionssimple.cpp:513 optionssimple.cpp:526 +msgid "High" +msgstr "Alto" + +#: config.cpp:1278 config.cpp:1315 configgeneralpage.cpp:56 +#: configgeneralpage.cpp:293 optionsdetailed.cpp:360 optionssimple.cpp:45 +#: optionssimple.cpp:139 optionssimple.cpp:175 optionssimple.cpp:217 +#: optionssimple.cpp:380 optionssimple.cpp:514 optionssimple.cpp:527 +msgid "Very high" +msgstr "Molto alto" + +#: config.cpp:1282 config.cpp:1289 config.cpp:1296 config.cpp:1303 +#: config.cpp:1310 convert.cpp:387 convert.cpp:996 convert.cpp:997 +#: convert.cpp:1568 convert.cpp:1569 filelist.cpp:1234 filelist.cpp:1245 +#: filelist.cpp:1255 filelist.cpp:1335 optionsdetailed.cpp:246 +#: optionsdetailed.cpp:470 optionsdetailed.cpp:560 optionssimple.cpp:287 +#: optionssimple.cpp:316 optionssimple.cpp:344 optionssimple.cpp:371 +#: optionssimple.cpp:398 +msgid "Bitrate" +msgstr "Bitrate" + +#: config.cpp:1351 optionsdetailed.cpp:365 optionssimple.cpp:51 +#: optionssimple.cpp:142 optionssimple.cpp:190 optionssimple.cpp:223 +#: optionssimple.cpp:435 optionssimple.cpp:454 optionssimple.cpp:458 +#: optionssimple.cpp:468 optionssimple.cpp:472 optionssimple.cpp:520 +#: optionssimple.cpp:552 +msgid "User defined" +msgstr "Personalizzato" + +#: config.cpp:1394 config.cpp:1407 config.cpp:1411 config.cpp:1457 +#: config.cpp:1461 +msgid "files" +msgstr "file" + +#: config.cpp:1419 config.cpp:1469 +msgid "all supported formats" +msgstr "tutti i formati supportati" + +#: config.cpp:1419 config.cpp:1469 +msgid "all formats" +msgstr "tutti i formati" + +#: configbackendspage.cpp:42 +msgid "Legend" +msgstr "Didascalia" + +#: configbackendspage.cpp:45 +msgid "Full support" +msgstr "Supporto totale" + +#: configbackendspage.cpp:48 +msgid "Most supported" +msgstr "Maggiormente supportato" + +#: configbackendspage.cpp:51 +msgid "Basic support" +msgstr "Supporto di base" + +#: configbackendspage.cpp:57 +msgid "CD Ripper" +msgstr "Estrai CD" + +#: configbackendspage.cpp:243 +msgid "Encoder" +msgstr "Encoder" + +#: configbackendspage.cpp:256 +msgid "Strength" +msgstr "Robustezza" + +#: configbackendspage.cpp:263 +msgid "" +"Set the compression strength:\n" +"\n" +"Left = fast conversion\n" +"Right = good resultant file" +msgstr "" +"Scegli la qualità della compressione:\n" +"\n" +"Sinistra = conversione veloce\n" +"Destra = file di buona qualità" + +#: configbackendspage.cpp:272 +msgid "Decoder" +msgstr "Decoder" + +#: configbackendspage.cpp:286 convert.cpp:593 convert.cpp:1580 +#: optionsdetailed.cpp:168 +msgid "Replay Gain" +msgstr "Normalizza" + +#: configbackendspage.cpp:295 +msgid "Use internal Replay Gain" +msgstr "Utilizza normalizzazione interna" + +#: configbackendspage.cpp:296 +msgid "Use the internal Replay Gain calculator of the encoder" +msgstr "Utilizza l'analizzatore della normalizzazione interna dell'encoder" + +#: configbackendspage.cpp:320 +msgid "KDE audio CD protocol" +msgstr "Protocollo di KDE per i CD audio" + +#: configdialog.cpp:31 +msgid "Settings" +msgstr "Impostazioni" + +#: configdialog.cpp:56 +msgid "General" +msgstr "Impostazioni Generali" + +#: configdialog.cpp:68 +msgid "Plugins" +msgstr "Plugin" + +#: configdialog.cpp:80 +msgid "Environment" +msgstr "Ambiente" + +#: configdialog.cpp:92 +msgid "Backends" +msgstr "Backends" + +#: configenvironmentpage.cpp:32 +msgid "Directories to be scanned" +msgstr "Cartelle da analizzare" + +#: configenvironmentpage.cpp:50 +msgid "" +"Move selected directory one position up.\n" +"This effects which backend will be chosen, if there are several versions." +msgstr "" +"Sposta la cartella selezionata in un livello superiore.\n" +"Questo avrà effetto sul backend scelto, nel caso esistano più versioni." + +#: configenvironmentpage.cpp:60 +msgid "" +"Move selected directory one position down.\n" +"This effects which backend will be chosen, if there are several versions." +msgstr "" +"Sposta la cartella selezionata in un livello inferiore.\n" +"Questo avrà effetto sul backend scelto, se ne esistono più versioni." + +#: configenvironmentpage.cpp:67 configpluginspage.cpp:50 +msgid "Add ..." +msgstr "Aggiungi..." + +#: configenvironmentpage.cpp:87 +msgid "Programs found" +msgstr "Programmi trovati" + +#: configenvironmentpage.cpp:96 +msgid "Programs not found" +msgstr "Programmi non trovati" + +#: configgeneralpage.cpp:34 +msgid "Start in Mode" +msgstr "Modalità di avvio" + +#: configgeneralpage.cpp:38 options.cpp:36 +msgid "Simple" +msgstr "Semplice" + +#: configgeneralpage.cpp:39 options.cpp:41 +msgid "Detailed" +msgstr "Dettagliato" + +#: configgeneralpage.cpp:49 +msgid "Default profile" +msgstr "Profilo predefinito" + +#: configgeneralpage.cpp:72 +msgid "Default format" +msgstr "Formato predefinito" + +#: configgeneralpage.cpp:107 +msgid "Process priority of the backends" +msgstr "Priorità del processo dei backends" + +#: configgeneralpage.cpp:110 +msgid "Normal" +msgstr "Normale" + +#: configgeneralpage.cpp:122 +msgid "Use FAT compatible output file names" +msgstr "Utilizza nomi dei file compatibili col sistema FAT" + +#: configgeneralpage.cpp:123 +msgid "Replaces some special characters like '?' by '_'." +msgstr "Sostituisce i caratteri speciali come '?' con '_'." + +#: configgeneralpage.cpp:133 +msgid "Conflict handling" +msgstr "Gestione dei conflitti" + +#: configgeneralpage.cpp:136 +msgid "Do that if the output file already exists" +msgstr "Fai questo se il file di output esiste già" + +#: configgeneralpage.cpp:137 +msgid "Generate new file name" +msgstr "Genera un nuovo nome del file" + +#: configgeneralpage.cpp:138 +msgid "Skip file" +msgstr "Salta il file" + +#: configgeneralpage.cpp:149 +msgid "Number of files to convert at once" +msgstr "Numero di file da convertire contemporaneamente" + +#: configgeneralpage.cpp:160 +msgid "Status update delay (time in msec.)" +msgstr "Stato del ritardo dell'aggiornamento (tempo in ms)" + +#: configgeneralpage.cpp:163 +msgid "Update the progress bar in this interval (time in milliseconds)" +msgstr "Aggiorna la barra di progresso in questo intervallo (tempo in ms)" + +#: configgeneralpage.cpp:172 +msgid "Ask for new options, when adding files from external program" +msgstr "" +"Possibilità di scegliere nuove opzioni quando aggiungi file da un programma " +"esterno." + +#: configgeneralpage.cpp:173 +msgid "" +"If you open a file with soundKonverter and soundKonverter is already " +"running,\n" +"you can either be asked to define new converting options\n" +"or the current settings from the soundKonverter main window are used." +msgstr "Se apri un file con soundKonverter mentre è già avviato," + +#: configgeneralpage.cpp:183 +msgid "Execute user script (for advanced users)" +msgstr "Esegui script utente (per utenti avanzati)" + +#: configgeneralpage.cpp:184 +msgid "" +"Executes a script after every finished conversion. Have a look at " +"$KDEDIR/soundkonverter/userscript.sh" +msgstr "" +"Esegui uno script quando la conversione è completata.\n" +"controllare il file $KDEDIR/soundkonverter/userscript.sh" + +#: configpluginspage.cpp:39 +msgid "Installed plugins" +msgstr "Plugin installati" + +#: configpluginspage.cpp:228 +msgid "*.soundkonverter.xml|Plugins (*.soundkonverter.xml)" +msgstr "*.soundkonverter.xml|Plugins (*.soundkonverter.xml)" + +#: configpluginspage.cpp:228 +msgid "Choose a plugin to add!" +msgstr "Scegli un plugin da aggiungere!" + +#: configpluginspage.cpp:253 configpluginspage.cpp:546 +msgid "" +"The plugin could not be installed. Please ensure that you have selected a " +"valid soundKonverter plugin file." +msgstr "" +"Il plugin potrebbe non essere installato. Per piacere assicurati che il " +"plugin selezionato sia un file di plugin per soundKonverter valido." + +#: configpluginspage.cpp:254 configpluginspage.cpp:294 +#: configpluginspage.cpp:547 configpluginspage.cpp:587 +msgid "Error while installing plugin" +msgstr "Errore durante l'installazione del plugin" + +#: configpluginspage.cpp:279 configpluginspage.cpp:572 +msgid "" +"The plugin was installed successfully. Please restart soundKonverter in " +"order to activate it." +msgstr "" +"Il plugin è stato installato correttamente. Riavvia soundKonverter per " +"attivarlo." + +#: configpluginspage.cpp:280 configpluginspage.cpp:573 +msgid "Plugin successfully installed" +msgstr "Plugin installato correttamente" + +#: configpluginspage.cpp:293 configpluginspage.cpp:586 +msgid "" +"The plugin could not be installed. Please ensure that you have write " +"permission on your whole user directory." +msgstr "" +"Il plugin non può essere installato. Assicurati di avere i permessi di " +"scrittura nella tua cartella utente." + +#: configpluginspage.cpp:311 configpluginspage.cpp:330 +#: configpluginspage.cpp:349 +msgid "" +"The plugin was removed successfully. Please restart soundKonverter in order " +"to deactivate it." +msgstr "" +"Il plugin è stato rimosso completamente. Riavvia soundKonverter per " +"disattivarlo." + +#: configpluginspage.cpp:312 configpluginspage.cpp:331 +#: configpluginspage.cpp:350 +msgid "Plugin successfully removed" +msgstr "Plugin rimosso correttamente" + +#: configpluginspage.cpp:316 configpluginspage.cpp:335 +#: configpluginspage.cpp:354 +msgid "" +"The plugin could not be removed. Please ensure that you have write " +"permission on your whole user directory." +msgstr "" +"Il plugin non può essere rimosso. Assicurati di avere i permessi di " +"scrittura nella tua cartella utente." + +#: configpluginspage.cpp:317 configpluginspage.cpp:336 +#: configpluginspage.cpp:355 +msgid "Error while removing plugin" +msgstr "Errore durante la disinstallazione del plugin" + +#: configpluginspage.cpp:383 configpluginspage.cpp:395 +#: configpluginspage.cpp:407 +msgid "Version" +msgstr "Versione" + +#: configpluginspage.cpp:384 configpluginspage.cpp:396 +#: configpluginspage.cpp:408 +msgid "Author" +msgstr "Autore" + +#: configpluginspage.cpp:417 configpluginspage.cpp:472 +msgid "No new plugins available!" +msgstr "Nessun nuovo plugin disponibile!" + +#: configpluginspage.cpp:477 +msgid "" +"The plugin list could not be downloaded. Please ensure, that your internet " +"connection works correct.\n" +"Maybe our server is busy at the moment, please try it again later." +msgstr "" +"La lista dei plugin non può essere scaricata. Assicurati che la connessione " +"ad internet sia attiva.\n" +"Il server potrebbe essere occupato, prova più tardi." + +#: configpluginspage.cpp:478 +msgid "Error while loading plugin list" +msgstr "Errore durante il caricamento della lista dei plugin" + +#: configpluginspage.cpp:626 configpluginspage.cpp:632 +msgid "" +"The plugin info could not be downloaded. Please ensure, that your internet " +"connection works correctly." +msgstr "" +"Le informazioni sul plugin non disponibili. Assicurati che la tua " +"connessione ad internet sia attiva." + +#: configpluginspage.cpp:627 configpluginspage.cpp:633 +msgid "Error while loading plugin info" +msgstr "Errore durante il caricamente delle informazioni sul plugin" + +#: convert.cpp:83 convert.cpp:86 convert.cpp:1538 +msgid "Getting file" +msgstr "Ricevo il file..." + +#: convert.cpp:86 convert.cpp:130 convert.cpp:190 convert.cpp:260 +#: convert.cpp:314 convert.cpp:555 convert.cpp:593 convert.cpp:603 +#: convert.cpp:617 convert.cpp:661 convert.cpp:694 convert.cpp:1538 +#: convert.cpp:1542 convert.cpp:1547 convert.cpp:1551 convert.cpp:1557 +#: convert.cpp:1561 convert.cpp:1571 convert.cpp:1575 convert.cpp:1580 +#: convert.cpp:1583 convert.cpp:1587 filelist.cpp:136 filelist.cpp:638 +#: filelist.cpp:641 filelist.cpp:650 filelist.cpp:651 filelist.cpp:696 +#: filelist.cpp:726 filelist.cpp:729 filelist.cpp:733 filelist.cpp:860 +#: filelist.cpp:861 filelist.cpp:918 filelist.cpp:955 filelist.cpp:956 +msgid "State" +msgstr "Stato" + +#: convert.cpp:116 convert.cpp:130 convert.cpp:1542 +msgid "Getting correction file" +msgstr "Ricevo il file di correzione.." + +#: convert.cpp:122 +msgid "Aborting, file does not exist" +msgstr "Azione annullata. Il file non esiste" + +#: convert.cpp:157 convert.cpp:190 convert.cpp:260 convert.cpp:1547 +#: convert.cpp:1551 +msgid "Ripping" +msgstr "Estrazione in corso..." + +#: convert.cpp:270 convert.cpp:314 convert.cpp:1557 convert.cpp:1561 +msgid "Decoding" +msgstr "Decoding" + +#: convert.cpp:334 convert.cpp:555 convert.cpp:1571 convert.cpp:1575 +msgid "Encoding" +msgstr "Encoding" + +#: convert.cpp:453 filelist.cpp:1401 optionsdetailed.cpp:541 +msgid "Stereo" +msgstr "Stereo" + +#: convert.cpp:456 filelist.cpp:1404 optionsdetailed.cpp:544 +msgid "Joint-Stereo" +msgstr "Joint-Stereo" + +#: convert.cpp:459 filelist.cpp:1407 optionsdetailed.cpp:547 +msgid "Forced Joint-Stereo" +msgstr "Joint-Stereo forzato" + +#: convert.cpp:462 filelist.cpp:1410 optionsdetailed.cpp:550 +msgid "Dual Channels" +msgstr "Doppi canali" + +#: convert.cpp:563 replaygainfilelist.cpp:914 +msgid "Applying Replay Gain" +msgstr "Normalizzazione in corso..." + +#: convert.cpp:598 convert.cpp:603 +msgid "Writing tags" +msgstr "Aggiornamento tags..." + +#: convert.cpp:611 convert.cpp:617 convert.cpp:1583 +msgid "Moving file" +msgstr "Spostamento file in corso" + +#: convert.cpp:649 convert.cpp:661 convert.cpp:1587 +msgid "Moving correction file" +msgstr "Spostamento file di correzione in corso" + +#: convert.cpp:688 convert.cpp:694 +msgid "Running user script" +msgstr "Script utente avviato e in corso..." + +#: convert.cpp:713 +msgid "Executing next step" +msgstr "Passaggio successivo..." + +#: convert.cpp:857 convert.cpp:874 convert.cpp:1123 convert.cpp:1147 +msgid "Got file" +msgstr "File ricevuto" + +#: convert.cpp:891 convert.cpp:1204 convert.cpp:1216 +msgid "Could not write to file: `%1'" +msgstr "Non si può scrivere sul file %1" + +#: convert.cpp:903 convert.cpp:918 convert.cpp:1228 convert.cpp:1255 +msgid "File moved" +msgstr "File spostato" + +#: convert.cpp:941 filelist.cpp:70 filelist.cpp:138 filelist.cpp:750 +#: outputdirectory.cpp:39 replaygainfilelist.cpp:1141 +msgid "Output" +msgstr "Output" + +#: convert.cpp:1292 +msgid "Adding new item to conversion list: `%1'" +msgstr "Aggiungo nuovi elementi alla lista di conversione: %1" + +#: convert.cpp:1299 +msgid "Got log ID: %1" +msgstr "Log ID %1 ricevuto" + +#: convert.cpp:1302 +msgid "Tags successfully read" +msgstr "Lettura tags completata" + +#: convert.cpp:1303 +msgid "Reading tags failed" +msgstr "Lettura tags fallita" + +#: convert.cpp:1443 convert.cpp:1453 replaygainfilelist.cpp:1025 +msgid "Killing process ..." +msgstr "Chiusura processo..." + +#: convert.cpp:1446 replaygainfilelist.cpp:1028 +msgid "Killing process failed. Stopping after files are completed ..." +msgstr "" +"Chiusura processo fallita. Il processo verrà interrotto dopo che tutti i " +"file saranno stati completati." + +#: convert.cpp:1468 +msgid "Removing file from conversion list. Exit code %1" +msgstr "Rimuovo i file dalla lista di conversione... Codice di uscita %1" + +#: convert.cpp:1475 +msgid "Executing command: \"%1\"" +msgstr "Comando '%1'" + +#: cuesheeteditor.cpp:29 +msgid "Cuesheet Editor" +msgstr "Editor della lista CUE" + +#: cuesheeteditor.cpp:76 +msgid "Generate" +msgstr "Genera" + +#: cuesheeteditor.cpp:82 +msgid "Format" +msgstr "Formato" + +#: cuesheeteditor.cpp:88 +msgid "Shift Title/Performer" +msgstr "Cambia Titolo/Artista" + +#: cuesheeteditor.cpp:113 +msgid "" +"

With this small tool you can process cue files as they are used for " +"burning music mixes and for organizing them in media players like " +"amaroK.

You can generate a new file by pasting text into the input " +"area. It must be formated the following way:

Title - Artist " +"[time]
Title - Artist [3:25]
Title - Artist [2:37]
...
A tip: " +"Use kwrite and regular expressions to format it this way.

" +msgstr "" +"

Grazie a questo piccolo strumento si può trattare file .cue, che sono " +"utilizzati per masterizzare compilation musicali e per organizzare queste " +"ultime in lettori multimediali come amaroK.

Puoi creare un nuovo file " +"incollando il testo nella casella di input. Deve essere formattato nel modo " +"seguente

Titolo - Artista [durata]
Titolo - Artista " +"[3:25]
Titolo - Artista [2:37]
...
Consiglio: Usa kwrite e " +"espressioni regolari per formattarlo in questo modo.

" + +#: cuesheeteditor.cpp:114 +msgid "Cuesheet Editor - Help" +msgstr "Editore della lista CUE - Aiuto" + +#: dirdialog.cpp:24 +msgid "Add folder" +msgstr "Aggiungi cartella" + +#: dirdialog.cpp:33 +msgid "Directory:" +msgstr "Cartella:" + +#: dirdialog.cpp:63 +msgid "Select all" +msgstr "Seleziona tutto" + +#: dirdialog.cpp:69 +msgid "Select none" +msgstr "Deseleziona tutto" + +#: dirdialog.cpp:75 +msgid "Recursive" +msgstr "Ricorsivo" + +#: dirdialog.cpp:106 dirdialog.cpp:133 +msgid "Choose a directory" +msgstr "Scegli una cartella" + +#: filelist.cpp:70 filelist.cpp:137 filelist.cpp:736 filelist.cpp:737 +msgid "Input" +msgstr "Input" + +#: filelist.cpp:170 +msgid "Edit options ..." +msgstr "Modifica le opzioni..." + +#: filelist.cpp:171 +msgid "Start conversion" +msgstr "Inizia la conversione" + +#: filelist.cpp:172 +msgid "Stop conversion" +msgstr "Interrompi la conversione" + +#: filelist.cpp:184 +msgid "" +"

File List

Select your desired output options in " +"the form above and add some files.
You can add files by clicking on " +"\"Add files ...\" or dropping them here.
" +msgstr "" +"

Lista file

Seleziona le opzioni di output nella " +"casella sottostante e aggiungi i file.
Puoi aggiungere i file cliccando " +"su \"Aggiungi file...\" o spostandoli qui.
" + +#: filelist.cpp:578 filelist.cpp:593 +msgid "Audio CD (%1)" +msgstr "Audio CD (%1)" + +#: filelist.cpp:609 filelist.cpp:624 +msgid "Full audio CD (%1)" +msgstr "Audio CD (%1) completo" + +#: filelist.cpp:638 filelist.cpp:650 filelist.cpp:955 +msgid "Stopped" +msgstr "Interrotto" + +#: filelist.cpp:641 filelist.cpp:650 filelist.cpp:955 +msgid "Failed" +msgstr "Fallito" + +#: filelist.cpp:650 filelist.cpp:726 filelist.cpp:860 filelist.cpp:955 +msgid "Will be skipped" +msgstr "Sarà saltato" + +#: filelist.cpp:651 filelist.cpp:696 filelist.cpp:729 filelist.cpp:861 +#: filelist.cpp:918 filelist.cpp:956 progressindicator.cpp:49 +msgid "Waiting" +msgstr "Attendere..." + +#: filelist.cpp:733 +msgid "Converting" +msgstr "Conversione in corso" + +#: logger.cpp:136 +msgid "Finished logging" +msgstr "Registro salvato" + +#: logviewer.cpp:83 +msgid "Log Viewer" +msgstr "Visualizzatore del registro" + +#: logviewer.cpp:90 +msgid "Job/File" +msgstr "Lavoro/File" + +#: main.cpp:12 +msgid "" +"soundKonverter is a frontend to various sound en- and decoding programs." +msgstr "" +"soundKonverter è un frontend per vari programmi di encoding e decoding." + +#: main.cpp:18 +msgid "Open the Replay Gain tool an add all given files" +msgstr "Apri lo strumento normalizza e aggiungi tutti i file" + +#: main.cpp:20 +msgid "List all tracks on the cd drive , 'auto' will search for a cd" +msgstr "Mostra tutte le tracce nell'unità , 'auto' cercherà il cd" + +#: main.cpp:21 +msgid "Add all files using the given profile" +msgstr "Aggiungi tutti i file utilizzando il profilo selezionato" + +#: main.cpp:22 +msgid "Add all files using the given format" +msgstr "Aggiungi tutti i file utilizzando il formato selezionato" + +#: main.cpp:23 +msgid "Output all files to " +msgstr "Salva tutti i file in " + +#: main.cpp:24 +msgid "Start soundKonverter invisible" +msgstr "Avvia soundKonverter invisibile" + +#: main.cpp:25 +msgid "" +"Close soundKonverter after all files are converted (enabled when using '--" +"invisible')" +msgstr "Chiudi soundKonverter dopo che tutti i file sono stati convertiti." + +#: main.cpp:26 +msgid "Execute after each file has been converted" +msgstr "Esegui dopo che ciascun file è stato convertito" + +#: main.cpp:27 +msgid "Audio file(s) to append to the file list" +msgstr "File audio da aggiungere alla lista" + +#: main.cpp:33 +msgid "soundKonverter" +msgstr "soundKonverter" + +#: options.cpp:127 +msgid "" +"soundKonverter either found new backends or misses some.\n" +"Click on this button in order to open the configuration dialog." +msgstr "" +"soundKonverter ha trovato sia nuovi backend ma ne ha anche perso alcuni.\n" +"Clicca questo pulsante per aprire la finestra di configurazione." + +#: options.cpp:136 +msgid "Advanced Options" +msgstr "Opzioni avanzate" + +#: optionsdetailed.cpp:45 +msgid "Convert" +msgstr "Converti" + +#: optionsdetailed.cpp:73 +msgid "" +"vbr - variable bitrate\n" +"abr - average bitrate\n" +"cbr - constant bitrate" +msgstr "" +"vbr - bitrate variabile\n" +"abr - bitrate medio\n" +"cbr - bitrate costante" + +#: optionsdetailed.cpp:83 +msgid "Bitrate range" +msgstr "Intervallo di bitrate" + +#: optionsdetailed.cpp:84 +msgid "" +"Use it only if, you know what you are doing, you could reduce the quality." +msgstr "Usa soltanto se sai cosa stai facendo, potresti ridurre la qualità." + +#: optionsdetailed.cpp:119 +msgid "Resample" +msgstr "Ricampiona" + +#: optionsdetailed.cpp:147 +msgid "Channels" +msgstr "Canali" + +#: optionsdetailed.cpp:170 +msgid "Add a Replay Gain tag to the converted file." +msgstr "Aggiungi un etichetta \"normalizza\" al file processato." + +#: optionsdetailed.cpp:171 +msgid "" +"Replay Gain is a volume correction technique. A volume difference is " +"calculated and stored in a tag. This way audio players can automatically " +"adjust the volume and the original music data is not modified (like at " +"normalization)." +msgstr "" +"La normalizzazione è una tecnica di correzione del volume. Viene calcolata " +"una differenza nel volume e salvata in un'etichetta. In questo modo i player " +"audio sono in grado di aggiustare automaticamente il volume mentre i dati " +"musicali originali non vengono modificati." + +#: optionsdetailed.cpp:192 +msgid "Save current options as a profile" +msgstr "Salva le impostazioni correnti come un profilo" + +#: optionsdetailed.cpp:208 +msgid "Command" +msgstr "Comando" + +#: optionsdetailed.cpp:219 +#, c-format +msgid "%p: The parameters generated by soundKonverter" +msgstr "%p: I parametri generati da soundKonverter" + +#: optionsdetailed.cpp:225 +#, c-format +msgid "%i: The input file ; %o: The output file" +msgstr "%i: file di input ; %o: file di output" + +#: optionsdetailed.cpp:353 +msgid "New profile" +msgstr "Nuovo profilo" + +#: optionsdetailed.cpp:353 +msgid "Enter a name for the new profile:" +msgstr "Inserisci il nome del nuovo profilo:" + +#: optionsdetailed.cpp:368 +msgid "You cannot overwrite the built-in profiles." +msgstr "Non puoi sovrascrivere i profili integrati." + +#: optionsdetailed.cpp:369 optionsdetailed.cpp:379 +msgid "Profile already exists" +msgstr "Profilo già esistente" + +#: optionsdetailed.cpp:378 +msgid "" +"A profile with this name already exists.\n" +"\n" +"Do you want to overwrite the existing one?" +msgstr "" +"Esiste già un profilo con lo stesso nome.\n" +"Vuoi sovrascriverlo?" + +#: optionsdetailed.cpp:473 optionsdetailed.cpp:628 +msgid "Unchanged" +msgstr "Invariato" + +#: optionsdetailed.cpp:483 optionsdetailed.cpp:604 +msgid "Undefined" +msgstr "Non definito" + +#: optionsdetailed.cpp:561 optionsdetailed.cpp:619 +msgid "Kilobit per second" +msgstr "kilobit/secondo" + +#: optionsdetailed.cpp:689 +msgid "" +"This is a relative quality between 0 and 100.\n" +"The higher this number the higher is the quality.\n" +"soundKonverter will convert it into the file format's quality format.\n" +"See the \"What's this?\" for more informations.\n" +"\n" +"Current parameter: \"%1\"" +msgstr "" +"Questa è la qualità relativa compresa tra 0 e 100.\n" +"Maggiore è il numero e maggiore è la qualità.\n" +"soundKonverter convertirà nel formato di qualità del formato del file.\n" +"Consulta il \"Cosa è questo?\" per maggiori informazioni.\n" +"\n" +"Parametro corrente: %1" + +#: optionseditor.cpp:28 +msgid "Options Editor" +msgstr "Editor delle opzioni" + +#: optionseditor.cpp:55 +msgid "Conversion" +msgstr "Conversione" + +#: optionseditor.cpp:55 +msgid "Conversion options" +msgstr "Opzioni di conversione" + +#: optionseditor.cpp:59 +msgid "Choose your prefered output options and click on \"Close\"!" +msgstr "Seleziona le opzioni di output preferite e clicca su \"Chiudi\"!" + +#: optionseditor.cpp:70 +msgid "Edit conversion options" +msgstr "Modifica le opzioni di conversione" + +#: optionseditor.cpp:79 +msgid "Tags" +msgstr "Tag" + +#: optionseditor.cpp:103 +msgid "Track No.:" +msgstr "Traccia numero:" + +#: optionseditor.cpp:256 +msgid "Edit tags" +msgstr "Modifica tag" + +#: optionseditor.cpp:330 +msgid "No file selected" +msgstr "Nessun file selezionato" + +#: optionseditor.cpp:358 +msgid "" +"The tags could not be read, because this file isn't a local one.\n" +"soundKonverter will try to read the tags, when it is about to convert the " +"file.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags." +msgstr "" +"Le etichette potrebbero non essere lette perché non si tratta di un file " +"locale.\n" +"soundKonverter proverà a leggerle nel momento di convertire il file.\n" +"Se vuoi modificare le etichette, premi il pulsante sottostante e " +"soundKonverter\n" +"non proverà a leggerle." + +#: optionseditor.cpp:367 +msgid "" +"Reading the tags of this file failed.\n" +"soundKonverter will try to read the tags a second time, when it is about to " +"convert the file.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags a second time." +msgstr "" +"Lettura delle etichette di questo file fallita.\n" +"soundKonverter proverà nuovamente a leggere le etichette nel momento di " +"convertire il file.\n" +"Se vuoi modificare le etichette, premi il pulsante sottostante e " +"soundKonverter\n" +"non proverà a leggerle una seconda volta." + +#: optionseditor.cpp:387 +msgid "%1 Files" +msgstr "%1 file" + +#: optionseditor.cpp:402 +msgid "" +"You have selected multiple files with different conversion options.\n" +"You can change the options of all files by hitting the button below." +msgstr "" +"Hai selezionato più file con differenti opzioni di conversione.\n" +"Puoi cambiare le opzioni per tutti i file cliccando il pulsante sotto." + +#: optionseditor.cpp:408 +msgid "" +"Reading the tags of one or more files failed.\n" +"soundKonverter will try to read the tags a second time, when it is about to " +"convert the files.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags a second time." +msgstr "" +"Lettura delle tag di uno o più file fallita.\n" +"soundKonverter proverà a reggere nuovamente le etichette nel momento di " +"convertire i file.\n" +"Se vuoi modificare le etichette premi il pulsante sotto, ma in questo caso " +"soundKonverter\n" +"non proverà a leggerle una seconda volta." + +#: optionsrequester.cpp:18 +msgid "Choose output options" +msgstr "Seleziona le opzioni di output" + +#: optionsrequester.cpp:28 +msgid "Click on \"Ok\" to add the files to the list in the main window!" +msgstr "" +"Clicca su \"Ok\" per aggiungere i file alla lista nella finestra principale!" + +#: optionsrequester.cpp:43 +msgid "" +"Warning: If you select \"wav\" as output format, your wav files will not be " +"added to the list." +msgstr "" +"Attenzione: se selezioni \"wav\" come formato di output, i tuoi file wav non " +"saranno aggiunti alla lista." + +#: optionsrequester.cpp:59 +msgid "Ok" +msgstr "Ok" + +#: optionssimple.cpp:64 +msgid "Remove the selected profile" +msgstr "Rimuovi il profilo selezionato" + +#: optionssimple.cpp:70 optionssimple.cpp:90 +msgid "Info" +msgstr "Info" + +#: optionssimple.cpp:71 +msgid "Information about the selected profile" +msgstr "Informazioni sul profilo selezionato" + +#: optionssimple.cpp:78 +msgid "Output format" +msgstr "Formato di output" + +#: optionssimple.cpp:91 +msgid "Information about the selected file format" +msgstr "Informazioni sul formato di file selezionato" + +#: optionssimple.cpp:157 +msgid "" +"This produces sound files of a very low quality.\n" +"That can be useful, if you have a mobile device, where your memory cell is " +"limited. It is not recommended to save your music in this quality without a " +"copy with higher quality.\n" +"It can also be used to save audio files with voices." +msgstr "" +"Questo produce file audio di qualità molto bassa.\n" +"Può essere utile nel caso di dispositivi mobili (cellulari...) con poca " +"memoria. Non è consigliato salvare la propria musica in questa qualità senza " +"avere anche una copia ad alta qualità.\n" +"Può essere inoltre utile per salvare file audio con voci." + +#: optionssimple.cpp:158 optionssimple.cpp:163 optionssimple.cpp:168 +#: optionssimple.cpp:173 optionssimple.cpp:178 optionssimple.cpp:183 +#: optionssimple.cpp:188 optionssimple.cpp:193 +msgid "Profile" +msgstr "Profilo" + +#: optionssimple.cpp:162 +msgid "" +"This produces sound files of a low quality.\n" +"That can be useful if you habe a mobile device where your memory cell is " +"limited. It is not recommended to save your music in this quality without a " +"copy with higher quality." +msgstr "" +"Questo produce file audio di bassa qualità.\n" +"Può essere utile nel caso di dispositivi con bassa memoria (come " +"cellulari...). Non è consigliato salvare la tua musica in questa qualità " +"senza avere anche una copia ad alta qualità." + +#: optionssimple.cpp:167 +msgid "" +"This produces sound files of a medium quality.\n" +"If your disc space is limited, you can use this to save your music." +msgstr "" +"Questo produce file audio di media qualità.\n" +"Usa questa opzione per salvare la tua musica se hai spazio limitato sul tuo " +"disco." + +#: optionssimple.cpp:172 +msgid "" +"This produces sound files of a high quality.\n" +"If you have enough disc space available, you can use this to save your music." +msgstr "" +"Questo produce file audio di alta qualità.\n" +"Usa questa opzione per salvare la tua musica se hai abbastanza spazio " +"disponibile sul tuo disco." + +#: optionssimple.cpp:177 +msgid "" +"This produces sound files of a very high quality.\n" +"You should only use this, if you are a quality freak and have enough disc " +"space available." +msgstr "" +"Questo produce file audio di qualità molto alta.\n" +"Dovresti usare questa opzione se sufficiente spazio sul disco e se hai il " +"pallino della qualità :)" + +#: optionssimple.cpp:182 +msgid "" +"This produces files, that have exact the same quality as the input files.\n" +"This files are very big and definitely only for quality freaks." +msgstr "" +"Questo produce file audio della stessa qualità dei file sorgenti.\n" +"Questi file sono molto grandi e soltanto per i maniaci della qualità." + +#: optionssimple.cpp:187 +msgid "" +"This produces two files. One lossy compressed playable file and one " +"correction file.\n" +"Both files together result in a file that is equivalent to the input file." +msgstr "" +"Questo produce due file: un file compresso e un file di correzione.\n" +"I due file insieme sono equivalenti al file sorgente." + +#: optionssimple.cpp:192 +msgid "You can define your own profile in the \"detailed\" tab." +msgstr "Puoi definire il tuo profilo nella scheda \"Dettagliato\"" + +#: optionssimple.cpp:205 +msgid "Do you really want to remove the profile: %1" +msgstr "Vuoi veramente rimuovere il profilo %1 ?" + +#: optionssimple.cpp:206 +msgid "Remove profile?" +msgstr "Vuoi rimuovere il profilo?" + +#: optionssimple.cpp:234 +msgid "" +"

Wave is a file format, that doesn't compress it's audio data.

\n" +"

So the quality is very high, but the file size is enormous. It is widely " +"spread and should work with every audio player.

\n" +"
http://en.wikipedia.org/wiki/Wav" +msgstr "" +"

Il formato Wave è un formato di file audio che non comprime i dati.

\n" +"

Perciò la qualità è molto alta, ma la dimensione del file è enorme. Si " +"tratta di un formato ampiamente diffuso e funziona con la maggior parte di " +"player.

\n" +"
http://it.wikipedia.org/wiki/WAV" + +#: optionssimple.cpp:235 optionssimple.cpp:242 +msgid "File format" +msgstr "Formato file" + +#: outputdirectory.cpp:44 +msgid "By meta data" +msgstr "Dai metadati" + +#: outputdirectory.cpp:45 +msgid "Source directory" +msgstr "Cartella sorgente" + +#: outputdirectory.cpp:46 +msgid "Specify output directory" +msgstr "Specifica la cartella di destinazione" + +#: outputdirectory.cpp:47 +msgid "Copy directory structure" +msgstr "Copia la struttura della cartella" + +#: outputdirectory.cpp:61 +msgid "Clear the directory input field" +msgstr "Pulisci il campo della cartella sorgente" + +#: outputdirectory.cpp:81 outputdirectory.cpp:345 +msgid "Choose an output directory" +msgstr "Scegli la cartella di destinazione" + +#: outputdirectory.cpp:87 +msgid "Open Konqueror with the output directory" +msgstr "Apri Konqueror con la cartella di destinazione" + +#: outputdirectory.cpp:184 +msgid "Unknown Artist" +msgstr "Artista sconosciuto" + +#: outputdirectory.cpp:188 +msgid "Unknown Album" +msgstr "Album sconosciuto" + +#: outputdirectory.cpp:192 +msgid "No Comment" +msgstr "Nessun commento" + +#: outputdirectory.cpp:199 +msgid "Unknown Genre" +msgstr "Genere sconosciuto" + +#: outputdirectory.cpp:206 +msgid "Unknown Composer" +msgstr "Compositore sconosciuto" + +#: outputdirectory.cpp:210 +msgid "Unknown Title" +msgstr "Titolo sconosciuto" + +#: outputdirectory.cpp:264 +msgid "new" +msgstr "nuovo" + +#: outputdirectory.cpp:406 +msgid "Name all converted files according to the specified pattern" +msgstr "Nomina tutti i file convertiti secondo lo schema specificato" + +#: outputdirectory.cpp:408 +msgid "" +"

The following strings are wildcards, that will be replaced by the " +"information in the meta data:

%a - Artist
%b - Album
%c - " +"Comment
%d - Disc number
%g - Genre
%n - Track number
%p - " +"Composer
%t - Title
%y - Year
%f - Original file name

" +msgstr "" +"

Le stringhe seguenti sono caratteri jolly, saranno sostituite dalle " +"informazioni presenti nei meta dati:

" +"

%a - Artista
%b - Album
%c - Commenti
%d - numero del " +"disco
%g - Genere
%n - Traccia
%p - Compositore
%t - " +"Titolo
%y - Anno
%f - nome del file originale

" + +#: outputdirectory.cpp:420 +msgid "" +"Output all converted files into the same directory as the original files" +msgstr "" +"Salva tutti i file convertiti nella stessa cartella dei file originali" + +#: outputdirectory.cpp:434 +msgid "Output all converted files into the specified output directory" +msgstr "" +"Salva tutti i file convertiti nella cartella di destinazione specificata" + +#: outputdirectory.cpp:448 +msgid "Copy the whole directory structure for all converted files" +msgstr "Copia l'intera struttura della cartella per tutti i file convertiti" + +#: paranoia.cpp:214 +msgid "MB" +msgstr "MB" + +#: paranoia.cpp:215 +msgid "KB" +msgstr "KB" + +#: paranoia.cpp:216 +msgid "Bytes" +msgstr "Byte" + +#: progressindicator.cpp:33 +msgid "Speed" +msgstr "Velocità" + +#: progressindicator.cpp:41 +msgid "Time remaining" +msgstr "Tempo rimanente" + +#: progressindicator.cpp:95 progressindicator.cpp:96 replaygainscanner.cpp:216 +msgid "Finished" +msgstr "Completato" + +#. i18n: file ./soundkonverterui.rc line 13 +#: rc.cpp:3 +#, no-c-format +msgid "&Conversion" +msgstr "&Conversione" + +#: replaygain.cpp:88 +msgid "Executing" +msgstr "In esecuzione..." + +#: replaygainfilelist.cpp:137 replaygainfilelist.cpp:147 +#: replaygainfilelist.cpp:150 replaygainfilelist.cpp:180 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:669 +#: replaygainfilelist.cpp:672 replaygainfilelist.cpp:704 +#: replaygainfilelist.cpp:707 replaygainfilelist.cpp:734 +#: replaygainfilelist.cpp:737 replaygainfilelist.cpp:940 +msgid "Album" +msgstr "Album" + +#: replaygainfilelist.cpp:213 +msgid "Calculate Replay Gain tags" +msgstr "Calcola le etichette di normalizzazione" + +#: replaygainfilelist.cpp:214 +msgid "Remove Replay Gain tags" +msgstr "Rimuovi le etichette di normalizzazione" + +#: replaygainfilelist.cpp:217 replaygainfilelist.cpp:825 +msgid "New album" +msgstr "Nuovo album" + +#: replaygainfilelist.cpp:218 +msgid "Open all albums" +msgstr "Apri tutti gli album" + +#: replaygainfilelist.cpp:219 +msgid "Cloase all albums" +msgstr "Chiudi tutti gli album" + +#: replaygainfilelist.cpp:223 +msgid "" +"

Replay Gain Tool

With this tool you can add Replay " +"Gain tags to your audio files and remove them.
Replay Gain adds a volume " +"correction information to the files so that they can be played at an equal " +"volume level.
" +msgstr "" +"

Strumento Normalizza

Con questo strumento si " +"possono aggiungere e rimuovere etichette di normalizzazione ai file " +"audio.
Normalizza aggiunge un'informazione sulla correzione del volume al " +"file in modo che tutti i file possano venire eseguiti allo stesso " +"volume.
" + +#: replaygainfilelist.cpp:494 +msgid "You can't place files of different formats in the same 'album'." +msgstr "" +"Non puoi raccogliere file di differente formato nello stesso 'album'." + +#: replaygainfilelist.cpp:494 +msgid "Different file formats" +msgstr "Formati di file diversi" + +#: replaygainfilelist.cpp:987 +msgid "Removing Replay Gain" +msgstr "Rimuovo normalizza..." + +#: replaygainfilelist.cpp:1148 +msgid "built-in" +msgstr "integrato" + +#: replaygainscanner.cpp:33 replaygainscanner.cpp:216 +#: replaygainscanner.cpp:231 +msgid "Replay Gain Tool" +msgstr "Strumento normalizza" + +#: replaygainscanner.cpp:43 +msgid "Add Folder ..." +msgstr "Aggiungi cartella..." + +#: replaygainscanner.cpp:44 +msgid "Add Files ..." +msgstr "Aggiungi file..." + +#: replaygainscanner.cpp:52 +msgid "Force recalculation" +msgstr "Forza il ricalcolo" + +#: replaygainscanner.cpp:53 +msgid "" +"Recalculate Replay Gain tag for files that already have a Replay Gain tag " +"set." +msgstr "" +"Ricalcola le etichette di normalizzazione per i file che ne hanno già una." + +#: replaygainscanner.cpp:102 +msgid "Tag untagged" +msgstr "Etichetta non assegnata" + +#: replaygainscanner.cpp:103 +msgid "" +"Calculate Replay Gain tag for all files in the file list without Replay Gain " +"tag." +msgstr "" +"Calcola l'etichetta di normalizzazione per tutti i file che non ce l'hanno " +"nella lista." + +#: replaygainscanner.cpp:109 +msgid "Untag tagged" +msgstr "Non etichetta assegnata" + +#: replaygainscanner.cpp:110 +msgid "Remove the Replay Gain tag from all files in the file list." +msgstr "Rimuovi l'etichetta di normalizzazione da tutti i file nella lista." + +#: replaygainscanner.cpp:151 +msgid "Choose files!" +msgstr "Seleziona i file!" + +#: soundkonverter.cpp:107 +msgid "Choose your prefered output options and click on \"Add files ...\"!" +msgstr "Selezione le opzioni di output e clicca su \"Aggiungi file...\"!" + +#: soundkonverter.cpp:110 soundkonverter.cpp:405 soundkonverter.cpp:448 +msgid "&Start conversion" +msgstr "&Avvia conversione" + +#: soundkonverter.cpp:112 +msgid "&Replay Gain Tool ..." +msgstr "Strumento no&rmalizza..." + +#: soundkonverter.cpp:114 +msgid "C&uesheet Editor ..." +msgstr "Editor Lista C&UE" + +#: soundkonverter.cpp:115 +msgid "Show &Log ..." +msgstr "Mostra &Registro" + +#: soundkonverter.cpp:118 +msgid "S&top after current file is complete" +msgstr "In&terrompi dopo il completamente del file corrente" + +#: soundkonverter.cpp:119 +msgid "&Continue after current file is complete" +msgstr "&Continua dopo il completamento del file corrente" + +#: soundkonverter.cpp:120 +msgid "Stop &immediately" +msgstr "&Interrompi" + +#: soundkonverter.cpp:148 +msgid "A&dd Files ..." +msgstr "A&ggiungi file..." + +#: soundkonverter.cpp:149 +msgid "Add &Folder ..." +msgstr "Aggiungi &cartella..." + +#: soundkonverter.cpp:150 +msgid "Add CD &tracks ..." +msgstr "Aggiungi &tracce dal CD..." + +#: soundkonverter.cpp:151 +msgid "Add &URL ..." +msgstr "Aggiungi &URL..." + +#: soundkonverter.cpp:154 +msgid "L&oad file list" +msgstr "Carica la &lista dei file" + +#: soundkonverter.cpp:155 +msgid "Sa&ve file list" +msgstr "Sal&va la lista dei file" + +#: soundkonverter.cpp:229 +msgid "Add files ..." +msgstr "Aggiungi file..." + +#: soundkonverter.cpp:230 +msgid "Add folder ..." +msgstr "Aggiungi cartella..." + +#: soundkonverter.cpp:231 +msgid "Add CD tracks ..." +msgstr "Aggiungi tracce dal CD..." + +#: soundkonverter.cpp:232 +msgid "Add URL ..." +msgstr "Aggiungi URL..." + +#: soundkonverter.cpp:240 +msgid "Start" +msgstr "Avvia" + +#: soundkonverter.cpp:417 +msgid "&Start queue" +msgstr "&Avvia la coda" + +#: soundkonverter.cpp:489 +msgid "Choose files to convert" +msgstr "Seleziona i file da convertire" + +#: soundkonverter.cpp:617 +msgid "Open URL" +msgstr "Apri URL" + +#: soundkonverter.cpp:617 +msgid "Enter a URL:" +msgstr "Inserisci URL:" diff --git a/po/nl.po b/po/nl.po new file mode 100644 index 0000000..ffa58e4 --- /dev/null +++ b/po/nl.po @@ -0,0 +1,1687 @@ +# Dutch translation soundKonverter +# This file is put in the public domain. +# Sander Thijsen , 2007. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-02-25 17:22+0100\n" +"PO-Revision-Date: 2008-04-19 21:10+0000\n" +"Last-Translator: Sander Thijsen \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2008-06-09 14:16+0000\n" +"X-Generator: Launchpad (build Unknown)\n" + +#~ msgid "Available plugins" +#~ msgstr "Beschikbare plugins" + +#~ msgid "Refresh" +#~ msgstr "Vernieuw" + +#~ msgid "Download the latest list of available plugins." +#~ msgstr "Download de nieuwste lijst met beschikbare plugins." + +#~ msgid "Install" +#~ msgstr "Installeer" + +#~ msgid "" +#~ "Download the selected plugin and install it into the soundKonverter " +#~ "directory." +#~ msgstr "" +#~ "Download de geselecteerde plugin en installeer het in de soundKonverter-map." + +#~ msgid "Check for new plugins on every startup" +#~ msgstr "Controleer op nieuwe plugins elke keer dat het programma start" + +#~ msgid "Adding new item to conversion list: `%1')" +#~ msgstr "Nieuw item aan lijst toevoegen: `%1')" + +#~ msgid "Choose a directory!" +#~ msgstr "Kies een map!" + +#~ msgid "" +#~ "There are new plugin updates available.\n" +#~ "Click on this button in order to open the configuration dialog." +#~ msgstr "" +#~ "Er zijn nieuwe pluginupdates beschikbaar.\n" +#~ "Klik op deze knop om het configuratiescherm te openen." + +#: _translatorinfo.cpp:1 +msgid "" +"_: NAME OF TRANSLATORS\n" +"Your names" +msgstr "_: NAMEN VAN VERTALERS,,Launchpad Contributions:,Sander Thijsen" + +#: _translatorinfo.cpp:3 +msgid "" +"_: EMAIL OF TRANSLATORS\n" +"Your emails" +msgstr "_: EMAIL VAN VERTALERS,,,sander@ubuntu-nl.org" + +#: cddb.cpp:368 +msgid "No Title" +msgstr "Geen titel" + +#: cddb.cpp:372 cdmanager.cpp:97 convert.cpp:513 convert.cpp:514 +#: convert.cpp:515 convert.cpp:517 convert.cpp:519 convert.cpp:520 +#: convert.cpp:1547 convert.cpp:1557 convert.cpp:1571 +#: replaygainfilelist.cpp:136 replaygainfilelist.cpp:137 +#: replaygainfilelist.cpp:144 replaygainfilelist.cpp:150 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:666 +#: replaygainfilelist.cpp:672 replaygainfilelist.cpp:701 +#: replaygainfilelist.cpp:707 replaygainfilelist.cpp:731 +#: replaygainfilelist.cpp:737 replaygainfilelist.cpp:945 +msgid "Unknown" +msgstr "Onbekend" + +#: cddb.cpp:380 +msgid "Track %1" +msgstr "Track %1" + +#: cddb.cpp:479 +msgid "Searching local cddb entry ..." +msgstr "Zoeken naar lokaal CDDB-resultaat..." + +#: cddb.cpp:504 +msgid "Searching remote cddb entry ..." +msgstr "Zoeken in CDDB..." + +#: cddb.cpp:528 +msgid "Found exact match cddb entry ..." +msgstr "Een exacte overeenkomst in CDDB gevonden..." + +#: cddb.cpp:585 +msgid "Found close cddb entry ..." +msgstr "Een bijna-overeenkomst in CDDB gevonden..." + +#: cddb.cpp:608 +msgid "CDDB Matches" +msgstr "CDDB-overeenkomsten" + +#: cddb.cpp:608 +msgid "Several close CDDB entries found. Choose one:" +msgstr "Meerdere geschikte CDDB-items gevonden. Selecteer er een:" + +#: cdmanager.cpp:46 filelist.cpp:618 +msgid "Audio CD" +msgstr "Audio-CD" + +#: cdmanager.cpp:46 +msgid "Several audio CDs found. Choose one:" +msgstr "Verschillende audio-CD's gevonden. Kies er één:" + +#: cdmanager.cpp:104 +msgid "No audio CD found." +msgstr "Geen audio-CD gevonden." + +#: cdopener.cpp:41 +msgid "Add CD tracks" +msgstr "CD-nummers toevoegen" + +#: cdopener.cpp:52 cdopener.cpp:178 optionseditor.cpp:123 +msgid "Artist:" +msgstr "Artiest:" + +#: cdopener.cpp:57 cdopener.cpp:480 cdopener.cpp:485 cdopener.cpp:538 +#: cdopener.cpp:567 cdopener.cpp:682 cdopener.cpp:697 +msgid "Various Artists" +msgstr "Diverse artiesten" + +#: cdopener.cpp:66 cdopener.cpp:193 optionseditor.cpp:138 +msgid "Composer:" +msgstr "Componist:" + +#: cdopener.cpp:71 cdopener.cpp:496 cdopener.cpp:501 cdopener.cpp:548 +#: cdopener.cpp:579 cdopener.cpp:683 cdopener.cpp:698 +msgid "Various Composer" +msgstr "Diverse componisten" + +#: cdopener.cpp:83 optionseditor.cpp:158 +msgid "Album:" +msgstr "Album:" + +#: cdopener.cpp:91 optionseditor.cpp:178 +msgid "Disc No.:" +msgstr "CD-nummer:" + +#: cdopener.cpp:96 optionseditor.cpp:194 +msgid "Year:" +msgstr "Jaar:" + +#: cdopener.cpp:100 optionseditor.cpp:210 +msgid "Genre:" +msgstr "Genre:" + +#: cdopener.cpp:114 cdopener.cpp:532 filelist.cpp:578 filelist.cpp:587 +#: replaygainfilelist.cpp:136 replaygainfilelist.cpp:141 +#: replaygainfilelist.cpp:144 replaygainfilelist.cpp:178 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:663 +#: replaygainfilelist.cpp:666 replaygainfilelist.cpp:698 +#: replaygainfilelist.cpp:701 replaygainfilelist.cpp:728 +#: replaygainfilelist.cpp:731 +msgid "Track" +msgstr "Spoornummer" + +#: cdopener.cpp:115 cdopener.cpp:568 cdopener.cpp:571 cdopener.cpp:607 +msgid "Artist" +msgstr "Artiest" + +#: cdopener.cpp:116 cdopener.cpp:580 cdopener.cpp:583 cdopener.cpp:620 +msgid "Composer" +msgstr "Componist" + +#: cdopener.cpp:117 cdopener.cpp:594 +msgid "Title" +msgstr "Titel" + +#: cdopener.cpp:118 +msgid "Time" +msgstr "Tijd" + +#: cdopener.cpp:131 +msgid "No track selected" +msgstr "Geen spoornummer geselecteerd" + +#: cdopener.cpp:159 optionseditor.cpp:88 +msgid "Title:" +msgstr "Titel:" + +#: cdopener.cpp:212 optionseditor.cpp:235 +msgid "Comment:" +msgstr "Commentaar:" + +#: cdopener.cpp:242 +msgid "Save cuesheet ..." +msgstr "Cuesheet opslaan..." + +#: cdopener.cpp:250 +msgid "Add all tracks" +msgstr "Alle nummers toevoegen" + +#: cdopener.cpp:251 +msgid "Add selected tracks" +msgstr "Geselecteerde nummers toevoegen" + +#: cdopener.cpp:253 +msgid "Add full CD as one file" +msgstr "Hele CD als één bestand toevoegen" + +#: cdopener.cpp:440 +msgid "All tracks" +msgstr "Alle nummers" + +#: cdopener.cpp:443 +msgid "Tracks" +msgstr "Spoornummers" + +#: cdopener.cpp:742 +msgid "" +"A file with this name already exists.\n" +"\n" +"Do you want to overwrite the existing one?" +msgstr "" +"Er bestaat al een bestand met deze naam.\n" +"\n" +"Wilt u het bestand overschrijven?" + +#: cdopener.cpp:743 +msgid "File already exists" +msgstr "Bestand bestaat al" + +#: config.cpp:103 config.cpp:104 config.cpp:1197 config.cpp:1206 +#: config.cpp:1237 configgeneralpage.cpp:37 configgeneralpage.cpp:60 +#: configgeneralpage.cpp:62 configgeneralpage.cpp:269 +#: configgeneralpage.cpp:273 configgeneralpage.cpp:297 +#: configgeneralpage.cpp:306 configgeneralpage.cpp:316 options.cpp:153 +#: optionsdetailed.cpp:363 optionssimple.cpp:49 optionssimple.cpp:221 +#: optionssimple.cpp:518 soundkonverter.cpp:308 soundkonverter.cpp:309 +msgid "Last used" +msgstr "Laatst gebruikt" + +#: config.cpp:508 +msgid "Convert with soundKonverter ..." +msgstr "Converteren met soundKonverter..." + +#: config.cpp:543 +msgid "Add Replay Gain with soundKonverter ..." +msgstr "Replay Gain toevoegen met soundKonverter..." + +#: config.cpp:1228 config.cpp:1229 configgeneralpage.cpp:57 +#: configgeneralpage.cpp:302 convert.cpp:431 filelist.cpp:1379 +#: optionsdetailed.cpp:361 optionsdetailed.cpp:427 optionsdetailed.cpp:477 +#: optionsdetailed.cpp:527 optionsdetailed.cpp:604 optionssimple.cpp:46 +#: optionssimple.cpp:140 optionssimple.cpp:180 optionssimple.cpp:218 +#: optionssimple.cpp:407 optionssimple.cpp:515 optionssimple.cpp:535 +msgid "Lossless" +msgstr "Lossless" + +#: config.cpp:1232 config.cpp:1233 configgeneralpage.cpp:58 +#: configgeneralpage.cpp:312 convert.cpp:434 convert.cpp:1378 +#: filelist.cpp:1382 optionsdetailed.cpp:362 optionsdetailed.cpp:480 +#: optionsdetailed.cpp:618 optionssimple.cpp:47 optionssimple.cpp:141 +#: optionssimple.cpp:185 optionssimple.cpp:219 optionssimple.cpp:421 +#: optionssimple.cpp:430 optionssimple.cpp:516 optionssimple.cpp:544 +msgid "Hybrid" +msgstr "Hybride" + +#: config.cpp:1245 config.cpp:1252 config.cpp:1259 config.cpp:1266 +#: config.cpp:1273 convert.cpp:403 convert.cpp:995 convert.cpp:1567 +#: filelist.cpp:139 filelist.cpp:752 filelist.cpp:1270 filelist.cpp:1351 +#: optionsdetailed.cpp:246 optionsdetailed.cpp:467 optionsdetailed.cpp:582 +#: optionsdetailed.cpp:641 optionssimple.cpp:38 optionssimple.cpp:283 +#: optionssimple.cpp:312 optionssimple.cpp:340 optionssimple.cpp:367 +#: optionssimple.cpp:394 +msgid "Quality" +msgstr "Kwaliteit" + +#: config.cpp:1248 config.cpp:1285 convert.cpp:450 filelist.cpp:1398 +#: optionsdetailed.cpp:538 optionssimple.cpp:294 +msgid "Mono" +msgstr "Mono" + +#: config.cpp:1250 config.cpp:1287 configgeneralpage.cpp:52 +#: configgeneralpage.cpp:289 optionsdetailed.cpp:356 optionssimple.cpp:41 +#: optionssimple.cpp:135 optionssimple.cpp:155 optionssimple.cpp:213 +#: optionssimple.cpp:269 optionssimple.cpp:510 optionssimple.cpp:525 +msgid "Very low" +msgstr "Erg laag" + +#: config.cpp:1257 config.cpp:1294 configgeneralpage.cpp:53 +#: configgeneralpage.cpp:111 configgeneralpage.cpp:290 optionsdetailed.cpp:357 +#: optionssimple.cpp:42 optionssimple.cpp:136 optionssimple.cpp:160 +#: optionssimple.cpp:214 optionssimple.cpp:298 optionssimple.cpp:511 +#: optionssimple.cpp:525 +msgid "Low" +msgstr "Laag" + +#: config.cpp:1264 config.cpp:1301 configgeneralpage.cpp:54 +#: configgeneralpage.cpp:291 optionsdetailed.cpp:358 optionseditor.cpp:713 +#: optionssimple.cpp:43 optionssimple.cpp:137 optionssimple.cpp:165 +#: optionssimple.cpp:215 optionssimple.cpp:326 optionssimple.cpp:512 +#: optionssimple.cpp:526 +msgid "Medium" +msgstr "Gemiddeld" + +#: config.cpp:1271 config.cpp:1308 configgeneralpage.cpp:55 +#: configgeneralpage.cpp:292 optionsdetailed.cpp:359 optionssimple.cpp:44 +#: optionssimple.cpp:138 optionssimple.cpp:170 optionssimple.cpp:216 +#: optionssimple.cpp:353 optionssimple.cpp:513 optionssimple.cpp:526 +msgid "High" +msgstr "Hoog" + +#: config.cpp:1278 config.cpp:1315 configgeneralpage.cpp:56 +#: configgeneralpage.cpp:293 optionsdetailed.cpp:360 optionssimple.cpp:45 +#: optionssimple.cpp:139 optionssimple.cpp:175 optionssimple.cpp:217 +#: optionssimple.cpp:380 optionssimple.cpp:514 optionssimple.cpp:527 +msgid "Very high" +msgstr "Erg hoog" + +#: config.cpp:1282 config.cpp:1289 config.cpp:1296 config.cpp:1303 +#: config.cpp:1310 convert.cpp:387 convert.cpp:996 convert.cpp:997 +#: convert.cpp:1568 convert.cpp:1569 filelist.cpp:1234 filelist.cpp:1245 +#: filelist.cpp:1255 filelist.cpp:1335 optionsdetailed.cpp:246 +#: optionsdetailed.cpp:470 optionsdetailed.cpp:560 optionssimple.cpp:287 +#: optionssimple.cpp:316 optionssimple.cpp:344 optionssimple.cpp:371 +#: optionssimple.cpp:398 +msgid "Bitrate" +msgstr "Bitsnelheid" + +#: config.cpp:1351 optionsdetailed.cpp:365 optionssimple.cpp:51 +#: optionssimple.cpp:142 optionssimple.cpp:190 optionssimple.cpp:223 +#: optionssimple.cpp:435 optionssimple.cpp:454 optionssimple.cpp:458 +#: optionssimple.cpp:468 optionssimple.cpp:472 optionssimple.cpp:520 +#: optionssimple.cpp:552 +msgid "User defined" +msgstr "Door gebruiker bepaald" + +#: config.cpp:1394 config.cpp:1407 config.cpp:1411 config.cpp:1457 +#: config.cpp:1461 +msgid "files" +msgstr "bestanden" + +#: config.cpp:1419 config.cpp:1469 +msgid "all supported formats" +msgstr "alle ondersteunde formaten" + +#: config.cpp:1419 config.cpp:1469 +msgid "all formats" +msgstr "alle formaten" + +#: configbackendspage.cpp:42 +msgid "Legend" +msgstr "Legenda" + +#: configbackendspage.cpp:45 +msgid "Full support" +msgstr "Volledige ondersteuning" + +#: configbackendspage.cpp:48 +msgid "Most supported" +msgstr "Gedeeltelijk ondersteund" + +#: configbackendspage.cpp:51 +msgid "Basic support" +msgstr "Basis ondersteund" + +#: configbackendspage.cpp:57 +msgid "CD Ripper" +msgstr "CD-ripper" + +#: configbackendspage.cpp:243 +msgid "Encoder" +msgstr "Encoder" + +#: configbackendspage.cpp:256 +msgid "Strength" +msgstr "Sterkte" + +#: configbackendspage.cpp:263 +msgid "" +"Set the compression strength:\n" +"\n" +"Left = fast conversion\n" +"Right = good resultant file" +msgstr "" +"Kies de compressiesterkte:\n" +"\n" +"Links = snelle conversie\n" +"Rechts = hoge kwaliteit uitvoer" + +#: configbackendspage.cpp:272 +msgid "Decoder" +msgstr "Decoder" + +#: configbackendspage.cpp:286 convert.cpp:593 convert.cpp:1580 +#: optionsdetailed.cpp:168 +msgid "Replay Gain" +msgstr "Replay Gain" + +#: configbackendspage.cpp:295 +msgid "Use internal Replay Gain" +msgstr "Gebruik intern Replay Gain" + +#: configbackendspage.cpp:296 +msgid "Use the internal Replay Gain calculator of the encoder" +msgstr "Gebruik het interne Replay Gain van de encoder" + +#: configbackendspage.cpp:320 +msgid "KDE audio CD protocol" +msgstr "KDE audio-CD protocol" + +#: configdialog.cpp:31 +msgid "Settings" +msgstr "Instellingen" + +#: configdialog.cpp:56 +msgid "General" +msgstr "Algemeen" + +#: configdialog.cpp:68 +msgid "Plugins" +msgstr "Plugins" + +#: configdialog.cpp:80 +msgid "Environment" +msgstr "Omgeving" + +#: configdialog.cpp:92 +msgid "Backends" +msgstr "Backends" + +#: configenvironmentpage.cpp:32 +msgid "Directories to be scanned" +msgstr "Mappen die gescand moeten worden" + +#: configenvironmentpage.cpp:50 +msgid "" +"Move selected directory one position up.\n" +"This effects which backend will be chosen, if there are several versions." +msgstr "" +"Verplaats de geselecteerde map één positie omhoog.\n" +"Dit heeft effect op welke backend gekozen wordt, als er verschillende " +"versie's zijn." + +#: configenvironmentpage.cpp:60 +msgid "" +"Move selected directory one position down.\n" +"This effects which backend will be chosen, if there are several versions." +msgstr "" +"Verplaats de geselecteerde map één positie naar beneden.\n" +"Dit heeft effect op welke backend gekozen wordt, als er verschillende " +"versie's zijn." + +#: configenvironmentpage.cpp:67 configpluginspage.cpp:50 +msgid "Add ..." +msgstr "Toevoegen..." + +#: configenvironmentpage.cpp:87 +msgid "Programs found" +msgstr "Programma's gevonden" + +#: configenvironmentpage.cpp:96 +msgid "Programs not found" +msgstr "Programma's niet gevonden" + +#: configgeneralpage.cpp:34 +msgid "Start in Mode" +msgstr "Start in mode" + +#: configgeneralpage.cpp:38 options.cpp:36 +msgid "Simple" +msgstr "Simpel" + +#: configgeneralpage.cpp:39 options.cpp:41 +msgid "Detailed" +msgstr "Gedetailleerd" + +#: configgeneralpage.cpp:49 +msgid "Default profile" +msgstr "Standaardprofiel" + +#: configgeneralpage.cpp:72 +msgid "Default format" +msgstr "Standaardformaat" + +#: configgeneralpage.cpp:107 +msgid "Process priority of the backends" +msgstr "Prioriteit van backend-processen" + +#: configgeneralpage.cpp:110 +msgid "Normal" +msgstr "Normaal" + +#: configgeneralpage.cpp:122 +msgid "Use FAT compatible output file names" +msgstr "Gebruikt FAT-compatibele uitvoer bestandsnamen" + +#: configgeneralpage.cpp:123 +msgid "Replaces some special characters like '?' by '_'." +msgstr "Vervangt een aantal speciale tekens zoals '?' door '_'." + +#: configgeneralpage.cpp:133 +msgid "Conflict handling" +msgstr "Conflictafhandeling" + +#: configgeneralpage.cpp:136 +msgid "Do that if the output file already exists" +msgstr "Deze actie uitvoeren als het uitvoerbestand al bestaat" + +#: configgeneralpage.cpp:137 +msgid "Generate new file name" +msgstr "Nieuwe bestandsnaam genereren" + +#: configgeneralpage.cpp:138 +msgid "Skip file" +msgstr "Bestand overslaan" + +#: configgeneralpage.cpp:149 +msgid "Number of files to convert at once" +msgstr "Aantal bestanden om in één keer te converteren" + +#: configgeneralpage.cpp:160 +msgid "Status update delay (time in msec.)" +msgstr "Status update vertraging (tijd in msec.)" + +#: configgeneralpage.cpp:163 +msgid "Update the progress bar in this interval (time in milliseconds)" +msgstr "De voortgangsbalk elke ... milliseconden vernieuwen" + +#: configgeneralpage.cpp:172 +msgid "Ask for new options, when adding files from external program" +msgstr "" +"Vraag voor nieuwe optie's bij het toevoegen van bestanden uit een extern " +"programma" + +#: configgeneralpage.cpp:173 +msgid "" +"If you open a file with soundKonverter and soundKonverter is already " +"running,\n" +"you can either be asked to define new converting options\n" +"or the current settings from the soundKonverter main window are used." +msgstr "" +"Als u een bestand opent met soundKonverter terwijl soundKonverter al " +"draait,\n" +"kunt u gevraagd worden nieuwe converteeroptie's op te geven,\n" +"of de huide instellingen van soundKonverter worden gebruikt." + +#: configgeneralpage.cpp:183 +msgid "Execute user script (for advanced users)" +msgstr "Script van gebruiker uitvoeren (voor gevorderden)" + +#: configgeneralpage.cpp:184 +msgid "" +"Executes a script after every finished conversion. Have a look at " +"$KDEDIR/soundkonverter/userscript.sh" +msgstr "" +"Voert een script uit na elke afgeronde conversie. Kijk eens naar " +"$KDEDIR/soundkonverter/userscript.sh" + +#: configpluginspage.cpp:39 +msgid "Installed plugins" +msgstr "Geïnstalleerde plugins" + +#: configpluginspage.cpp:228 +msgid "*.soundkonverter.xml|Plugins (*.soundkonverter.xml)" +msgstr "*.soundkonverter.xml|Plugins (*.soundkonverter.xml)" + +#: configpluginspage.cpp:228 +msgid "Choose a plugin to add!" +msgstr "Kies een plugin om toe te voegen!" + +#: configpluginspage.cpp:253 configpluginspage.cpp:546 +msgid "" +"The plugin could not be installed. Please ensure that you have selected a " +"valid soundKonverter plugin file." +msgstr "" +"De plugin kon niet geïnstalleerd worden. Controleer alstublieft of u een " +"geldig soundKonverter pluginbestand gebruikt." + +#: configpluginspage.cpp:254 configpluginspage.cpp:294 +#: configpluginspage.cpp:547 configpluginspage.cpp:587 +msgid "Error while installing plugin" +msgstr "Fout tijdens het installeren van de plugin" + +#: configpluginspage.cpp:279 configpluginspage.cpp:572 +msgid "" +"The plugin was installed successfully. Please restart soundKonverter in " +"order to activate it." +msgstr "" +"De plugin is met succes geïnstalleerd. Herstart soundKonverter om de plugin " +"te activeren." + +#: configpluginspage.cpp:280 configpluginspage.cpp:573 +msgid "Plugin successfully installed" +msgstr "Plugin met succes geïnstalleerd" + +#: configpluginspage.cpp:293 configpluginspage.cpp:586 +msgid "" +"The plugin could not be installed. Please ensure that you have write " +"permission on your whole user directory." +msgstr "" +"De plugin kon niet geïnstalleerd worden. Controleer of u schrijftoegang " +"heeft tot de hele gebruikersmap." + +#: configpluginspage.cpp:311 configpluginspage.cpp:330 +#: configpluginspage.cpp:349 +msgid "" +"The plugin was removed successfully. Please restart soundKonverter in order " +"to deactivate it." +msgstr "" +"De plugin is met succes verwijderd. Herstart soundKonverter om de plugin te " +"deactiveren." + +#: configpluginspage.cpp:312 configpluginspage.cpp:331 +#: configpluginspage.cpp:350 +msgid "Plugin successfully removed" +msgstr "Plugin met succes verwijderd" + +#: configpluginspage.cpp:316 configpluginspage.cpp:335 +#: configpluginspage.cpp:354 +msgid "" +"The plugin could not be removed. Please ensure that you have write " +"permission on your whole user directory." +msgstr "" +"De plugin kon niet verwijderd worden. Controleer of u schrijftoegang heeft " +"tot de hele gebruikersmap." + +#: configpluginspage.cpp:317 configpluginspage.cpp:336 +#: configpluginspage.cpp:355 +msgid "Error while removing plugin" +msgstr "Fout tijdens het verwijderen van de plugin" + +#: configpluginspage.cpp:383 configpluginspage.cpp:395 +#: configpluginspage.cpp:407 +msgid "Version" +msgstr "Versie" + +#: configpluginspage.cpp:384 configpluginspage.cpp:396 +#: configpluginspage.cpp:408 +msgid "Author" +msgstr "Auteur" + +#: configpluginspage.cpp:417 configpluginspage.cpp:472 +msgid "No new plugins available!" +msgstr "Geen nieuwe plugins beschikbaar!" + +#: configpluginspage.cpp:477 +msgid "" +"The plugin list could not be downloaded. Please ensure, that your internet " +"connection works correct.\n" +"Maybe our server is busy at the moment, please try it again later." +msgstr "" +"De plugin-lijst kon niet gedownload worden. Controleer of uw " +"internetverbinding correct werkt.\n" +"Het is ook mogelijk dat onze server op het moment te druk is. Probeer het in " +"dat geval later nog eens." + +#: configpluginspage.cpp:478 +msgid "Error while loading plugin list" +msgstr "Fout tijden het laden van de plugin-lijst" + +#: configpluginspage.cpp:626 configpluginspage.cpp:632 +msgid "" +"The plugin info could not be downloaded. Please ensure, that your internet " +"connection works correctly." +msgstr "" +"De plugin-informatie kon niet gedownload worden. Controleer of uw " +"internetverbinding correct werkt." + +#: configpluginspage.cpp:627 configpluginspage.cpp:633 +msgid "Error while loading plugin info" +msgstr "Fout tijden het laden van de plugin-informatie" + +#: convert.cpp:83 convert.cpp:86 convert.cpp:1538 +msgid "Getting file" +msgstr "Bestand ophalen" + +#: convert.cpp:86 convert.cpp:130 convert.cpp:190 convert.cpp:260 +#: convert.cpp:314 convert.cpp:555 convert.cpp:593 convert.cpp:603 +#: convert.cpp:617 convert.cpp:661 convert.cpp:694 convert.cpp:1538 +#: convert.cpp:1542 convert.cpp:1547 convert.cpp:1551 convert.cpp:1557 +#: convert.cpp:1561 convert.cpp:1571 convert.cpp:1575 convert.cpp:1580 +#: convert.cpp:1583 convert.cpp:1587 filelist.cpp:136 filelist.cpp:638 +#: filelist.cpp:641 filelist.cpp:650 filelist.cpp:651 filelist.cpp:696 +#: filelist.cpp:726 filelist.cpp:729 filelist.cpp:733 filelist.cpp:860 +#: filelist.cpp:861 filelist.cpp:918 filelist.cpp:955 filelist.cpp:956 +msgid "State" +msgstr "Status" + +#: convert.cpp:116 convert.cpp:130 convert.cpp:1542 +msgid "Getting correction file" +msgstr "Correctiebestand ophalen" + +#: convert.cpp:122 +msgid "Aborting, file does not exist" +msgstr "Stoppen, bestand bestaat niet" + +#: convert.cpp:157 convert.cpp:190 convert.cpp:260 convert.cpp:1547 +#: convert.cpp:1551 +msgid "Ripping" +msgstr "Rippen" + +#: convert.cpp:270 convert.cpp:314 convert.cpp:1557 convert.cpp:1561 +msgid "Decoding" +msgstr "Decoderen" + +#: convert.cpp:334 convert.cpp:555 convert.cpp:1571 convert.cpp:1575 +msgid "Encoding" +msgstr "Encoderen" + +#: convert.cpp:453 filelist.cpp:1401 optionsdetailed.cpp:541 +msgid "Stereo" +msgstr "Stereo" + +#: convert.cpp:456 filelist.cpp:1404 optionsdetailed.cpp:544 +msgid "Joint-Stereo" +msgstr "Joint-Stereo" + +#: convert.cpp:459 filelist.cpp:1407 optionsdetailed.cpp:547 +msgid "Forced Joint-Stereo" +msgstr "Geforceerde Joint-Stereo" + +#: convert.cpp:462 filelist.cpp:1410 optionsdetailed.cpp:550 +msgid "Dual Channels" +msgstr "Dubbele kanalen" + +#: convert.cpp:563 replaygainfilelist.cpp:914 +msgid "Applying Replay Gain" +msgstr "Replay Gain toevoegen" + +#: convert.cpp:598 convert.cpp:603 +msgid "Writing tags" +msgstr "Tags schrijven" + +#: convert.cpp:611 convert.cpp:617 convert.cpp:1583 +msgid "Moving file" +msgstr "Bestand verplaatsen" + +#: convert.cpp:649 convert.cpp:661 convert.cpp:1587 +msgid "Moving correction file" +msgstr "Correctiebestand verplaatsen" + +#: convert.cpp:688 convert.cpp:694 +msgid "Running user script" +msgstr "Script van gebruiker uitvoeren" + +#: convert.cpp:713 +msgid "Executing next step" +msgstr "Volgende stap uitvoeren" + +#: convert.cpp:857 convert.cpp:874 convert.cpp:1123 convert.cpp:1147 +msgid "Got file" +msgstr "Heeft bestand" + +#: convert.cpp:891 convert.cpp:1204 convert.cpp:1216 +msgid "Could not write to file: `%1'" +msgstr "Kon niet naar het bestand schrijven: `%1'" + +#: convert.cpp:903 convert.cpp:918 convert.cpp:1228 convert.cpp:1255 +msgid "File moved" +msgstr "Bestand verplaatst" + +#: convert.cpp:941 filelist.cpp:70 filelist.cpp:138 filelist.cpp:750 +#: outputdirectory.cpp:39 replaygainfilelist.cpp:1141 +msgid "Output" +msgstr "Uitvoer" + +#: convert.cpp:1292 +msgid "Adding new item to conversion list: `%1'" +msgstr "Nieuw item aan conversielijst toevoegen: `%1'" + +#: convert.cpp:1299 +msgid "Got log ID: %1" +msgstr "Heeft log ID: %1" + +#: convert.cpp:1302 +msgid "Tags successfully read" +msgstr "Tags succesvol gelezen" + +#: convert.cpp:1303 +msgid "Reading tags failed" +msgstr "Tags lezen mislukt" + +#: convert.cpp:1443 convert.cpp:1453 replaygainfilelist.cpp:1025 +msgid "Killing process ..." +msgstr "Proces afbreken..." + +#: convert.cpp:1446 replaygainfilelist.cpp:1028 +msgid "Killing process failed. Stopping after files are completed ..." +msgstr "" +"Afbreken van proces mislukt. Stoppen nadat de bestanden klaar zijn..." + +#: convert.cpp:1468 +msgid "Removing file from conversion list. Exit code %1" +msgstr "Bestand verwijderen van de lijst. Exit code %1" + +#: convert.cpp:1475 +msgid "Executing command: \"%1\"" +msgstr "Commando uitvoeren: \"%1\"" + +#: cuesheeteditor.cpp:29 +msgid "Cuesheet Editor" +msgstr "Cuesheet bewerker" + +#: cuesheeteditor.cpp:76 +msgid "Generate" +msgstr "Aanmaken" + +#: cuesheeteditor.cpp:82 +msgid "Format" +msgstr "Formaat" + +#: cuesheeteditor.cpp:88 +msgid "Shift Title/Performer" +msgstr "Titel/Artiest omkeren" + +#: cuesheeteditor.cpp:113 +msgid "" +"

With this small tool you can process cue files as they are used for " +"burning music mixes and for organizing them in media players like " +"amaroK.

You can generate a new file by pasting text into the input " +"area. It must be formated the following way:

Title - Artist " +"[time]
Title - Artist [3:25]
Title - Artist [2:37]
...
A tip: " +"Use kwrite and regular expressions to format it this way.

" +msgstr "" +"

Met dit kleine gereedschap kunt u cue-files verwerken, zoals ze gebruikt " +"worden voor het branden van muziek en het organiseren van muziek in " +"mediaspelers zoals Amarok.

U kunt een nieuw bestand aanmaken door " +"tekst in het invoerveld te plakken. Het moet op deze manier ingedeeld " +"zijn:

Titel - Artiest [tijd]
Titel - Artiest [3:25]
Titel - " +"Artiest [2:37]
...
Een tip: gebruik kwrite en reguliere expressie's om " +"het op deze manier in te delen.

" + +#: cuesheeteditor.cpp:114 +msgid "Cuesheet Editor - Help" +msgstr "Cuesheet bewerker - Help" + +#: dirdialog.cpp:24 +msgid "Add folder" +msgstr "Map toevoegen" + +#: dirdialog.cpp:33 +msgid "Directory:" +msgstr "Map:" + +#: dirdialog.cpp:63 +msgid "Select all" +msgstr "Alle selecteren" + +#: dirdialog.cpp:69 +msgid "Select none" +msgstr "Niets selecteren" + +#: dirdialog.cpp:75 +msgid "Recursive" +msgstr "Recursief" + +#: dirdialog.cpp:106 dirdialog.cpp:133 +msgid "Choose a directory" +msgstr "Kies een map" + +#: filelist.cpp:70 filelist.cpp:137 filelist.cpp:736 filelist.cpp:737 +msgid "Input" +msgstr "Invoer" + +#: filelist.cpp:170 +msgid "Edit options ..." +msgstr "Optie's aanpassen..." + +#: filelist.cpp:171 +msgid "Start conversion" +msgstr "Start conversie" + +#: filelist.cpp:172 +msgid "Stop conversion" +msgstr "Stop conversie" + +#: filelist.cpp:184 +msgid "" +"

File List

Select your desired output options in " +"the form above and add some files.
You can add files by clicking on " +"\"Add files ...\" or dropping them here.
" +msgstr "" +"

Bestandslijst

Selecteer uw gewenste uitvoeroptie's " +"in het menu hierboven, en voeg een aantal bestanden toe.
U kunt " +"bestanden toevoegen door op \"Bestanden toevoegen...\" te klikken, of door " +"ze hierheen te slepen.
" + +#: filelist.cpp:578 filelist.cpp:593 +msgid "Audio CD (%1)" +msgstr "Audio-CD (%1)" + +#: filelist.cpp:609 filelist.cpp:624 +msgid "Full audio CD (%1)" +msgstr "Hele audio-CD (%1)" + +#: filelist.cpp:638 filelist.cpp:650 filelist.cpp:955 +msgid "Stopped" +msgstr "Gestopt" + +#: filelist.cpp:641 filelist.cpp:650 filelist.cpp:955 +msgid "Failed" +msgstr "Mislukt" + +#: filelist.cpp:650 filelist.cpp:726 filelist.cpp:860 filelist.cpp:955 +msgid "Will be skipped" +msgstr "Zal overgeslagen worden" + +#: filelist.cpp:651 filelist.cpp:696 filelist.cpp:729 filelist.cpp:861 +#: filelist.cpp:918 filelist.cpp:956 progressindicator.cpp:49 +msgid "Waiting" +msgstr "Wachten" + +#: filelist.cpp:733 +msgid "Converting" +msgstr "Converteren" + +#: logger.cpp:136 +msgid "Finished logging" +msgstr "Klaar met loggen" + +#: logviewer.cpp:83 +msgid "Log Viewer" +msgstr "Logboek" + +#: logviewer.cpp:90 +msgid "Job/File" +msgstr "Taak/Bestand" + +#: main.cpp:12 +msgid "" +"soundKonverter is a frontend to various sound en- and decoding programs." +msgstr "" +"soundKonverter is een frontend voor verschillende geluids encodeer- en " +"decodeerprogramma's." + +#: main.cpp:18 +msgid "Open the Replay Gain tool an add all given files" +msgstr "Open de Replay Gain-tagger en voeg alle opgegeven bestanden toe" + +#: main.cpp:20 +msgid "List all tracks on the cd drive , 'auto' will search for a cd" +msgstr "" +"Scan voor nummers op de CD-speler , 'auto' zal zoeken naar een CD" + +#: main.cpp:21 +msgid "Add all files using the given profile" +msgstr "Alle bestanden toevoegen met gebruik van het opgegeven profiel" + +#: main.cpp:22 +msgid "Add all files using the given format" +msgstr "Alle bestanden toevoegen met gebruik van het opgegeven formaat" + +#: main.cpp:23 +msgid "Output all files to " +msgstr "Sla alle bestanden op in " + +#: main.cpp:24 +msgid "Start soundKonverter invisible" +msgstr "Start soundKonverter onzichtbaar" + +#: main.cpp:25 +msgid "" +"Close soundKonverter after all files are converted (enabled when using '--" +"invisible')" +msgstr "" +"Sluit soundKonverter als alle bestanden geconverteerd zijn (ingeschakeld als " +"'--invisible' gebruikt wordt)" + +#: main.cpp:26 +msgid "Execute after each file has been converted" +msgstr "Voer uit nadat elk bestand geconverteerd is" + +#: main.cpp:27 +msgid "Audio file(s) to append to the file list" +msgstr "Audiobestanden om aan de lijst toe te voegen" + +#: main.cpp:33 +msgid "soundKonverter" +msgstr "soundKonverter" + +#: options.cpp:127 +msgid "" +"soundKonverter either found new backends or misses some.\n" +"Click on this button in order to open the configuration dialog." +msgstr "" +"soundKonverter vond nieuwe backends, of mist er een aantal.\n" +"Klik op deze knop om het configuratiescherm te openen." + +#: options.cpp:136 +msgid "Advanced Options" +msgstr "Geavanceerde opties" + +#: optionsdetailed.cpp:45 +msgid "Convert" +msgstr "Converteren" + +#: optionsdetailed.cpp:73 +msgid "" +"vbr - variable bitrate\n" +"abr - average bitrate\n" +"cbr - constant bitrate" +msgstr "" +"vbr - variabele bitrate\n" +"abr - gemiddelde bitrate\n" +"cbr - constante bitrate" + +#: optionsdetailed.cpp:83 +msgid "Bitrate range" +msgstr "Bitsnelheid bereik" + +#: optionsdetailed.cpp:84 +msgid "" +"Use it only if, you know what you are doing, you could reduce the quality." +msgstr "" +"Alleen gebruiken als u weet wat u doet, u zou de kwaliteit kunnen " +"verminderen." + +#: optionsdetailed.cpp:119 +msgid "Resample" +msgstr "Hersamplen" + +#: optionsdetailed.cpp:147 +msgid "Channels" +msgstr "Kanalen" + +#: optionsdetailed.cpp:170 +msgid "Add a Replay Gain tag to the converted file." +msgstr "Voeg een Replay Gain-tag toe aan het geconverteerde bestand." + +#: optionsdetailed.cpp:171 +msgid "" +"Replay Gain is a volume correction technique. A volume difference is " +"calculated and stored in a tag. This way audio players can automatically " +"adjust the volume and the original music data is not modified (like at " +"normalization)." +msgstr "" +"Replay Gain is een volumecorrectie techniek. Een volumeverschil wordt " +"berekend en opgeslagen in een tag. Op deze manier kunnen audiospelers " +"automatisch het volumeniveau aanpassen, en de originele data wordt niet " +"aangepast (zoals bij normalisatie)." + +#: optionsdetailed.cpp:192 +msgid "Save current options as a profile" +msgstr "Sla de huidige optie's op als een profiel" + +#: optionsdetailed.cpp:208 +msgid "Command" +msgstr "Opdracht" + +#: optionsdetailed.cpp:219 +#, c-format +msgid "%p: The parameters generated by soundKonverter" +msgstr "%p: De door soundKonverter aangemaakte parameters" + +#: optionsdetailed.cpp:225 +#, c-format +msgid "%i: The input file ; %o: The output file" +msgstr "%i: Het invoerbestand ; %o: Het uitvoerbestand" + +#: optionsdetailed.cpp:353 +msgid "New profile" +msgstr "Nieuw profiel" + +#: optionsdetailed.cpp:353 +msgid "Enter a name for the new profile:" +msgstr "Kies een naam voor het nieuwe profiel:" + +#: optionsdetailed.cpp:368 +msgid "You cannot overwrite the built-in profiles." +msgstr "U kunt de ingebouwde profielen niet overschrijven." + +#: optionsdetailed.cpp:369 optionsdetailed.cpp:379 +msgid "Profile already exists" +msgstr "Profiel bestaat al" + +#: optionsdetailed.cpp:378 +msgid "" +"A profile with this name already exists.\n" +"\n" +"Do you want to overwrite the existing one?" +msgstr "" +"Er bestaat al een profiel met deze naam.\n" +"\n" +"Wilt u het bestaande profiel overschrijven?" + +#: optionsdetailed.cpp:473 optionsdetailed.cpp:628 +msgid "Unchanged" +msgstr "Ongewijzigd" + +#: optionsdetailed.cpp:483 optionsdetailed.cpp:604 +msgid "Undefined" +msgstr "Ongedefinieerd" + +#: optionsdetailed.cpp:561 optionsdetailed.cpp:619 +msgid "Kilobit per second" +msgstr "Kilobit per seconde" + +#: optionsdetailed.cpp:689 +msgid "" +"This is a relative quality between 0 and 100.\n" +"The higher this number the higher is the quality.\n" +"soundKonverter will convert it into the file format's quality format.\n" +"See the \"What's this?\" for more informations.\n" +"\n" +"Current parameter: \"%1\"" +msgstr "" +"Dit is een relatieve kwaliteit tussen 0 en 100.\n" +"Hoe hoger het nummer, hoe hoger de kwaliteit.\n" +"soundKonverter zal het converteren naar het kwaliteitsformaat van het " +"bestandsformaat.\n" +"Zie \"Wat is dit?\" voor meer informatie.\n" +"\n" +"Huidige parameter: \"%1\"" + +#: optionseditor.cpp:28 +msgid "Options Editor" +msgstr "Optie's bewerken" + +#: optionseditor.cpp:55 +msgid "Conversion" +msgstr "Conversie" + +#: optionseditor.cpp:55 +msgid "Conversion options" +msgstr "Conversie-optie's" + +#: optionseditor.cpp:59 +msgid "Choose your prefered output options and click on \"Close\"!" +msgstr "Kies uitvoeroptie's en klik op \"Sluiten\"!" + +#: optionseditor.cpp:70 +msgid "Edit conversion options" +msgstr "Conversie-optie's aanpassen" + +#: optionseditor.cpp:79 +msgid "Tags" +msgstr "Tags" + +#: optionseditor.cpp:103 +msgid "Track No.:" +msgstr "Spoornummer:" + +#: optionseditor.cpp:256 +msgid "Edit tags" +msgstr "Tags aanpassen" + +#: optionseditor.cpp:330 +msgid "No file selected" +msgstr "Geen bestand geselecteerd" + +#: optionseditor.cpp:358 +msgid "" +"The tags could not be read, because this file isn't a local one.\n" +"soundKonverter will try to read the tags, when it is about to convert the " +"file.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags." +msgstr "" +"De tags konden niet gelezen worden, omdat het geen lokaal bestand is.\n" +"soundKonverter zal de tags nog een keer proberen te lezen, wanneer het de " +"bestanden gaat converteren.\n" +"Als u de tags aan wilt passen, kunt u op de knop hieronder drukken, maar dan " +"zal soundKonverter niet proberen de tags nog een keer te lezen." + +#: optionseditor.cpp:367 +msgid "" +"Reading the tags of this file failed.\n" +"soundKonverter will try to read the tags a second time, when it is about to " +"convert the file.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags a second time." +msgstr "" +"Kon geen tags lezen voor dit bestand.\n" +"soundKonverter zal de tags nog een keer proberen te lezen, wanneer het de " +"bestanden gaat converteren.\n" +"Als u de tags aan wilt passen, kunt u op de knop hieronder drukken, maar dan " +"zal soundKonverter niet proberen de tags nog een keer te lezen." + +#: optionseditor.cpp:387 +msgid "%1 Files" +msgstr "%1 bestanden" + +#: optionseditor.cpp:402 +msgid "" +"You have selected multiple files with different conversion options.\n" +"You can change the options of all files by hitting the button below." +msgstr "" +"U heeft meerdere bestanden met verschillende conversie-optie's " +"geselecteerd.\n" +"U kunt de optie's van alle bestanden aanpassen door op de knop hieronder te " +"drukken." + +#: optionseditor.cpp:408 +msgid "" +"Reading the tags of one or more files failed.\n" +"soundKonverter will try to read the tags a second time, when it is about to " +"convert the files.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags a second time." +msgstr "" +"Het lezen van de tags van één of meer bestanden is niet gelukt.\n" +"soundKonverter zal de tags nog een keer proberen te lezen, wanneer het de " +"bestanden gaat converteren.\n" +"Als u de tags aan wilt passen, kunt u op de knop hieronder drukken, maar dan " +"zal soundKonverter niet proberen de tags nog een keer te lezen." + +#: optionsrequester.cpp:18 +msgid "Choose output options" +msgstr "Kies uitvoeroptie's" + +#: optionsrequester.cpp:28 +msgid "Click on \"Ok\" to add the files to the list in the main window!" +msgstr "" +"Klik op \"Ok\" om de bestanden aan de lijst in het hoofdscherm toe te voegen!" + +#: optionsrequester.cpp:43 +msgid "" +"Warning: If you select \"wav\" as output format, your wav files will not be " +"added to the list." +msgstr "" +"Waarschuwing: als u \"wav\" selecteert als uitvoerformaat, zullen uw wav-" +"bestanden niet toegevoegd worden aan de lijst." + +#: optionsrequester.cpp:59 +msgid "Ok" +msgstr "Ok" + +#: optionssimple.cpp:64 +msgid "Remove the selected profile" +msgstr "Geselecteerd profiel verwijderen" + +#: optionssimple.cpp:70 optionssimple.cpp:90 +msgid "Info" +msgstr "Informatie" + +#: optionssimple.cpp:71 +msgid "Information about the selected profile" +msgstr "Informatie over het geselecteerde profiel" + +#: optionssimple.cpp:78 +msgid "Output format" +msgstr "Uitvoerformaat" + +#: optionssimple.cpp:91 +msgid "Information about the selected file format" +msgstr "Informatie over het geselecteerde bestandsformaat" + +#: optionssimple.cpp:157 +msgid "" +"This produces sound files of a very low quality.\n" +"That can be useful, if you have a mobile device, where your memory cell is " +"limited. It is not recommended to save your music in this quality without a " +"copy with higher quality.\n" +"It can also be used to save audio files with voices." +msgstr "" +"Dit produceert bestanden van een erg lage kwaliteit.\n" +"Dit kan handig zijn als u een mobiel apparaat heeft met weinig schijfruimte. " +"Het is niet aangeraden deze kwaliteit te kiezen voor gebruik op uw " +"computer.\n" +"Het kan ook gebruikt worden om audiobestanden met stemmen op te slaan." + +#: optionssimple.cpp:158 optionssimple.cpp:163 optionssimple.cpp:168 +#: optionssimple.cpp:173 optionssimple.cpp:178 optionssimple.cpp:183 +#: optionssimple.cpp:188 optionssimple.cpp:193 +msgid "Profile" +msgstr "Profiel" + +#: optionssimple.cpp:162 +msgid "" +"This produces sound files of a low quality.\n" +"That can be useful if you habe a mobile device where your memory cell is " +"limited. It is not recommended to save your music in this quality without a " +"copy with higher quality." +msgstr "" +"Dit produceert bestanden van een lage kwaliteit.\n" +"Dit kan handig zijn als u een mobiel apparaat heeft met weinig schijfruimte. " +"Het is niet aangeraden deze kwaliteit te kiezen voor gebruik op uw computer." + +#: optionssimple.cpp:167 +msgid "" +"This produces sound files of a medium quality.\n" +"If your disc space is limited, you can use this to save your music." +msgstr "" +"Dit produceert bestanden met een gemiddelde kwaliteit.\n" +"Als u gelimiteerde schijfruimte tot uw beschikking heeft, kunt u deze optie " +"gebruiken." + +#: optionssimple.cpp:172 +msgid "" +"This produces sound files of a high quality.\n" +"If you have enough disc space available, you can use this to save your music." +msgstr "" +"Dit produceert bestanden van een hoge kwaliteit.\n" +"Als u genoeg schijfruimte tot uw beschikking hebt, kunt u deze optie " +"gebruiken." + +#: optionssimple.cpp:177 +msgid "" +"This produces sound files of a very high quality.\n" +"You should only use this, if you are a quality freak and have enough disc " +"space available." +msgstr "" +"Dit produceert bestanden van een erg hoge kwaliteit.\n" +"U zou deze optie alleen moeten gebruiken als u een kwaliteitfreak bent en " +"genoeg schijfruimte tot uw beschikking heeft." + +#: optionssimple.cpp:182 +msgid "" +"This produces files, that have exact the same quality as the input files.\n" +"This files are very big and definitely only for quality freaks." +msgstr "" +"Dit produceert bestanden die exact dezelfde kwaliteit hebben als de " +"invoerbestanden.\n" +"Deze bestanden worden erg groot, deze optie is dus ook alleen bedoeld voor " +"kwaliteit-freaks." + +#: optionssimple.cpp:187 +msgid "" +"This produces two files. One lossy compressed playable file and one " +"correction file.\n" +"Both files together result in a file that is equivalent to the input file." +msgstr "" +"Dit produceert twee bestanden: een bestand met kwaliteitsverlies (lossy) en " +"een correctiebestand.\n" +"Deze twee bestanden samen resulteren in een bestand dat gelijk is aan het " +"invoerbestand." + +#: optionssimple.cpp:192 +msgid "You can define your own profile in the \"detailed\" tab." +msgstr "U kunt uw eigen profiel maken onder het tabblad \"gedetailleerd\"." + +#: optionssimple.cpp:205 +msgid "Do you really want to remove the profile: %1" +msgstr "Wilt u het profiel %1 echt verwijderen?" + +#: optionssimple.cpp:206 +msgid "Remove profile?" +msgstr "Profiel verwijderen?" + +#: optionssimple.cpp:234 +msgid "" +"

Wave is a file format, that doesn't compress it's audio data.

\n" +"

So the quality is very high, but the file size is enormous. It is widely " +"spread and should work with every audio player.

\n" +"
http://en.wikipedia.org/wiki/Wav" +msgstr "" +"

Wave is een bestandsformaat dat de audiodata niet compresseert.

\n" +"

De kwaliteit is zeer hoog, maar de bestanden worden erg groot. Dit " +"formaat is erg bekend en zou met elke mediaspeler moeten werken.

\n" +"
http://nl.wikipedia.org/wiki/WAV" + +#: optionssimple.cpp:235 optionssimple.cpp:242 +msgid "File format" +msgstr "Bestandsformaat" + +#: outputdirectory.cpp:44 +msgid "By meta data" +msgstr "Op meta-data" + +#: outputdirectory.cpp:45 +msgid "Source directory" +msgstr "Bronmap" + +#: outputdirectory.cpp:46 +msgid "Specify output directory" +msgstr "Geef uitvoermap op" + +#: outputdirectory.cpp:47 +msgid "Copy directory structure" +msgstr "Kopieer de mappenstructuur" + +#: outputdirectory.cpp:61 +msgid "Clear the directory input field" +msgstr "Leeg het uitvoermap-veld" + +#: outputdirectory.cpp:81 outputdirectory.cpp:345 +msgid "Choose an output directory" +msgstr "Kies een uitvoermap" + +#: outputdirectory.cpp:87 +msgid "Open Konqueror with the output directory" +msgstr "Open de uitvoermap met Konqueror" + +#: outputdirectory.cpp:184 +msgid "Unknown Artist" +msgstr "Onbekende artiest" + +#: outputdirectory.cpp:188 +msgid "Unknown Album" +msgstr "Onbekend album" + +#: outputdirectory.cpp:192 +msgid "No Comment" +msgstr "Geen commentaar" + +#: outputdirectory.cpp:199 +msgid "Unknown Genre" +msgstr "Onbekend genre" + +#: outputdirectory.cpp:206 +msgid "Unknown Composer" +msgstr "Onbekende componist" + +#: outputdirectory.cpp:210 +msgid "Unknown Title" +msgstr "Onbekende titel" + +#: outputdirectory.cpp:264 +msgid "new" +msgstr "nieuw" + +#: outputdirectory.cpp:406 +msgid "Name all converted files according to the specified pattern" +msgstr "Benoem alle geconverteerde bestanden volgens het opgegeven patroon" + +#: outputdirectory.cpp:408 +msgid "" +"

The following strings are wildcards, that will be replaced by the " +"information in the meta data:

%a - Artist
%b - Album
%c - " +"Comment
%d - Disc number
%g - Genre
%n - Track number
%p - " +"Composer
%t - Title
%y - Year
%f - Original file name

" +msgstr "" +"

De volgende reeksen zijn zogenaamde \"wildcards\", die vervangen zullen " +"worden door de informatie in de metadata:

%a - Artiest
%b - " +"Album
%c - Commentaar
%d - CD nummer
%g - Genre
%n - " +"Spoornummer
%p - Componist
%t - Titel
%y - Jaar
%f - Originele " +"bestandsnaam

" + +#: outputdirectory.cpp:420 +msgid "" +"Output all converted files into the same directory as the original files" +msgstr "" +"Sla alle geconverteerde bestanden op in dezelfde map als de originele " +"bestanden" + +#: outputdirectory.cpp:434 +msgid "Output all converted files into the specified output directory" +msgstr "Sla alle geconverteerde bestanden op in de opgegeven uitvoermap" + +#: outputdirectory.cpp:448 +msgid "Copy the whole directory structure for all converted files" +msgstr "Kopieer de mappenstructuur voor alle geconverteerde bestanden" + +#: paranoia.cpp:214 +msgid "MB" +msgstr "MB" + +#: paranoia.cpp:215 +msgid "KB" +msgstr "KB" + +#: paranoia.cpp:216 +msgid "Bytes" +msgstr "Bytes" + +#: progressindicator.cpp:33 +msgid "Speed" +msgstr "Snelheid" + +#: progressindicator.cpp:41 +msgid "Time remaining" +msgstr "Resterende tijd" + +#: progressindicator.cpp:95 progressindicator.cpp:96 replaygainscanner.cpp:216 +msgid "Finished" +msgstr "Gereed" + +#. i18n: file ./soundkonverterui.rc line 13 +#: rc.cpp:3 +#, no-c-format +msgid "&Conversion" +msgstr "&Conversie" + +#: replaygain.cpp:88 +msgid "Executing" +msgstr "Uitvoeren" + +#: replaygainfilelist.cpp:137 replaygainfilelist.cpp:147 +#: replaygainfilelist.cpp:150 replaygainfilelist.cpp:180 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:669 +#: replaygainfilelist.cpp:672 replaygainfilelist.cpp:704 +#: replaygainfilelist.cpp:707 replaygainfilelist.cpp:734 +#: replaygainfilelist.cpp:737 replaygainfilelist.cpp:940 +msgid "Album" +msgstr "Album" + +#: replaygainfilelist.cpp:213 +msgid "Calculate Replay Gain tags" +msgstr "Bereken Replay Gain-tags" + +#: replaygainfilelist.cpp:214 +msgid "Remove Replay Gain tags" +msgstr "Verwijder Replay Gain-tags" + +#: replaygainfilelist.cpp:217 replaygainfilelist.cpp:825 +msgid "New album" +msgstr "Nieuw album" + +#: replaygainfilelist.cpp:218 +msgid "Open all albums" +msgstr "Open alle albums" + +#: replaygainfilelist.cpp:219 +msgid "Cloase all albums" +msgstr "Sluit alle albums" + +#: replaygainfilelist.cpp:223 +msgid "" +"

Replay Gain Tool

With this tool you can add Replay " +"Gain tags to your audio files and remove them.
Replay Gain adds a volume " +"correction information to the files so that they can be played at an equal " +"volume level.
" +msgstr "" +"

Replay Gain-tagger

Met dit gereedschap kunt u " +"Replay Gain-tags aan al uw audio-bestanden toevoegen, en ze ook weer " +"verwijderen.
Replay Gain voegt volumecorrectie-informatie toe aan de " +"bestanden zodat ze op een gelijk volumeniveau afgespeeld kunnen worden.
" + +#: replaygainfilelist.cpp:494 +msgid "You can't place files of different formats in the same 'album'." +msgstr "" +"U kunt geen bestanden van verschillende formaten in hetzelfde 'album' " +"plaatsen." + +#: replaygainfilelist.cpp:494 +msgid "Different file formats" +msgstr "Verschillende bestandsformaten" + +#: replaygainfilelist.cpp:987 +msgid "Removing Replay Gain" +msgstr "Replay Gain verwijderen" + +#: replaygainfilelist.cpp:1148 +msgid "built-in" +msgstr "ingebouwd" + +#: replaygainscanner.cpp:33 replaygainscanner.cpp:216 +#: replaygainscanner.cpp:231 +msgid "Replay Gain Tool" +msgstr "Replay Gain-tagger" + +#: replaygainscanner.cpp:43 +msgid "Add Folder ..." +msgstr "Map toevoegen..." + +#: replaygainscanner.cpp:44 +msgid "Add Files ..." +msgstr "Bestanden toevoegen..." + +#: replaygainscanner.cpp:52 +msgid "Force recalculation" +msgstr "Forceer herberekening" + +#: replaygainscanner.cpp:53 +msgid "" +"Recalculate Replay Gain tag for files that already have a Replay Gain tag " +"set." +msgstr "" +"Herbereken de Replay Gain tags voor alle bestanden die al over een Replay " +"Gain tag beschikken." + +#: replaygainscanner.cpp:102 +msgid "Tag untagged" +msgstr "Tag alles" + +#: replaygainscanner.cpp:103 +msgid "" +"Calculate Replay Gain tag for all files in the file list without Replay Gain " +"tag." +msgstr "" +"Bereken een Replay Gain tag voor alle bestanden zonder Replay Gain tag." + +#: replaygainscanner.cpp:109 +msgid "Untag tagged" +msgstr "Verwijder alle tags" + +#: replaygainscanner.cpp:110 +msgid "Remove the Replay Gain tag from all files in the file list." +msgstr "Verwijder de Replay Gain-tag van alle bestanden in de lijst." + +#: replaygainscanner.cpp:151 +msgid "Choose files!" +msgstr "Kies bestanden!" + +#: soundkonverter.cpp:107 +msgid "Choose your prefered output options and click on \"Add files ...\"!" +msgstr "" +"Kies uw uitvoeropties hierboven en klik dan op \"Bestanden toevoegen...\"!" + +#: soundkonverter.cpp:110 soundkonverter.cpp:405 soundkonverter.cpp:448 +msgid "&Start conversion" +msgstr "&Start conversie" + +#: soundkonverter.cpp:112 +msgid "&Replay Gain Tool ..." +msgstr "&Replay Gain-tagger..." + +#: soundkonverter.cpp:114 +msgid "C&uesheet Editor ..." +msgstr "C&uesheet bewerker..." + +#: soundkonverter.cpp:115 +msgid "Show &Log ..." +msgstr "&Log tonen..." + +#: soundkonverter.cpp:118 +msgid "S&top after current file is complete" +msgstr "S&top nadat huidig bestand compleet is" + +#: soundkonverter.cpp:119 +msgid "&Continue after current file is complete" +msgstr "Doorgaan nadat huidig bestand compleet is" + +#: soundkonverter.cpp:120 +msgid "Stop &immediately" +msgstr "Meteen stoppen" + +#: soundkonverter.cpp:148 +msgid "A&dd Files ..." +msgstr "Bestanden toevoegen..." + +#: soundkonverter.cpp:149 +msgid "Add &Folder ..." +msgstr "Map toevoegen..." + +#: soundkonverter.cpp:150 +msgid "Add CD &tracks ..." +msgstr "CD-nummers toevoegen..." + +#: soundkonverter.cpp:151 +msgid "Add &URL ..." +msgstr "&URL toevoegen..." + +#: soundkonverter.cpp:154 +msgid "L&oad file list" +msgstr "Bestandenlijst laden" + +#: soundkonverter.cpp:155 +msgid "Sa&ve file list" +msgstr "Bestandenlijst opslaan" + +#: soundkonverter.cpp:229 +msgid "Add files ..." +msgstr "Bestanden toevoegen..." + +#: soundkonverter.cpp:230 +msgid "Add folder ..." +msgstr "Map toevoegen..." + +#: soundkonverter.cpp:231 +msgid "Add CD tracks ..." +msgstr "CD-nummers toevoegen..." + +#: soundkonverter.cpp:232 +msgid "Add URL ..." +msgstr "URL toevoegen..." + +#: soundkonverter.cpp:240 +msgid "Start" +msgstr "Start" + +#: soundkonverter.cpp:417 +msgid "&Start queue" +msgstr "&Start wachtrij" + +#: soundkonverter.cpp:489 +msgid "Choose files to convert" +msgstr "Kies bestanden om te converteren" + +#: soundkonverter.cpp:617 +msgid "Open URL" +msgstr "Open URL" + +#: soundkonverter.cpp:617 +msgid "Enter a URL:" +msgstr "Voer een URL in:" diff --git a/po/pl.po b/po/pl.po new file mode 100644 index 0000000..6ecf140 --- /dev/null +++ b/po/pl.po @@ -0,0 +1,1636 @@ +# translation of pl.po to +# translation of pl.po_[5qyoSa].po to +# This file is put in the public domain. +# +# qla , 2007. +# Tomasz Argasiński , 2007. +msgid "" +msgstr "" +"Project-Id-Version: pl\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-02-25 17:22+0100\n" +"PO-Revision-Date: 2007-09-07 22:05+0000\n" +"Last-Translator: qla \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2008-04-06 10:52+0000\n" +"X-Generator: Launchpad (build Unknown)\n" + +#: _translatorinfo.cpp:1 +msgid "Your names" +msgstr "qla,,Launchpad Contributions:,Piotr Strębski,johny,qla" + +#: _translatorinfo.cpp:3 +msgid "Your emails" +msgstr "qla0@vp.pl,,,strebski@o2.pl,," + +#: cddb.cpp:368 +msgid "No Title" +msgstr "Bez tytułu" + +#: cddb.cpp:372 cdmanager.cpp:97 convert.cpp:513 convert.cpp:514 +#: convert.cpp:515 convert.cpp:517 convert.cpp:519 convert.cpp:520 +#: convert.cpp:1547 convert.cpp:1557 convert.cpp:1571 +#: replaygainfilelist.cpp:136 replaygainfilelist.cpp:137 +#: replaygainfilelist.cpp:144 replaygainfilelist.cpp:150 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:666 +#: replaygainfilelist.cpp:672 replaygainfilelist.cpp:701 +#: replaygainfilelist.cpp:707 replaygainfilelist.cpp:731 +#: replaygainfilelist.cpp:737 replaygainfilelist.cpp:945 +msgid "Unknown" +msgstr "Nieznany" + +#: cddb.cpp:380 +msgid "Track %1" +msgstr "Ścieżka %1" + +#: cddb.cpp:479 +msgid "Searching local cddb entry ..." +msgstr "Wyszukiwanie lokalnego wpisu CDDB..." + +#: cddb.cpp:504 +msgid "Searching remote cddb entry ..." +msgstr "Wyszukiwanie zdalnego wpisu CDDB..." + +#: cddb.cpp:528 +msgid "Found exact match cddb entry ..." +msgstr "Znaleziono pasujący wpis CDDB..." + +#: cddb.cpp:585 +msgid "Found close cddb entry ..." +msgstr "Znaleziono podobny wpis CDDB..." + +#: cddb.cpp:608 +msgid "CDDB Matches" +msgstr "Pasujący wpis CDDB" + +#: cddb.cpp:608 +msgid "Several close CDDB entries found. Choose one:" +msgstr "Znaleziono kilka wpisów CDDB. Wybierz jeden:" + +#: cdmanager.cpp:46 filelist.cpp:618 +msgid "Audio CD" +msgstr "Płyta Audio CD" + +#: cdmanager.cpp:46 +msgid "Several audio CDs found. Choose one:" +msgstr "Znaleziono kilka plyt. Wybierz jedną:" + +#: cdmanager.cpp:104 +msgid "No audio CD found." +msgstr "Nie znaleziono płyty." + +#: cdopener.cpp:41 +msgid "Add CD tracks" +msgstr "Dodaj ścieżki" + +#: cdopener.cpp:52 cdopener.cpp:178 optionseditor.cpp:123 +msgid "Artist:" +msgstr "Wykonawca:" + +#: cdopener.cpp:57 cdopener.cpp:480 cdopener.cpp:485 cdopener.cpp:538 +#: cdopener.cpp:567 cdopener.cpp:682 cdopener.cpp:697 +msgid "Various Artists" +msgstr "Różni wykonawcy" + +#: cdopener.cpp:66 cdopener.cpp:193 optionseditor.cpp:138 +msgid "Composer:" +msgstr "Kompozytor:" + +#: cdopener.cpp:71 cdopener.cpp:496 cdopener.cpp:501 cdopener.cpp:548 +#: cdopener.cpp:579 cdopener.cpp:683 cdopener.cpp:698 +msgid "Various Composer" +msgstr "Różni kompozytorzy" + +#: cdopener.cpp:83 optionseditor.cpp:158 +msgid "Album:" +msgstr "Album:" + +#: cdopener.cpp:91 optionseditor.cpp:178 +msgid "Disc No.:" +msgstr "Numer płyty:" + +#: cdopener.cpp:96 optionseditor.cpp:194 +msgid "Year:" +msgstr "Rok:" + +#: cdopener.cpp:100 optionseditor.cpp:210 +msgid "Genre:" +msgstr "Gatunek:" + +#: cdopener.cpp:114 cdopener.cpp:532 filelist.cpp:578 filelist.cpp:587 +#: replaygainfilelist.cpp:136 replaygainfilelist.cpp:141 +#: replaygainfilelist.cpp:144 replaygainfilelist.cpp:178 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:663 +#: replaygainfilelist.cpp:666 replaygainfilelist.cpp:698 +#: replaygainfilelist.cpp:701 replaygainfilelist.cpp:728 +#: replaygainfilelist.cpp:731 +msgid "Track" +msgstr "Utwór" + +#: cdopener.cpp:115 cdopener.cpp:568 cdopener.cpp:571 cdopener.cpp:607 +msgid "Artist" +msgstr "Wykonawca" + +#: cdopener.cpp:116 cdopener.cpp:580 cdopener.cpp:583 cdopener.cpp:620 +msgid "Composer" +msgstr "Kompozytor" + +#: cdopener.cpp:117 cdopener.cpp:594 +msgid "Title" +msgstr "Tytuł" + +#: cdopener.cpp:118 +msgid "Time" +msgstr "Czas" + +#: cdopener.cpp:131 +msgid "No track selected" +msgstr "Brak wybranej scieżki" + +#: cdopener.cpp:159 optionseditor.cpp:88 +msgid "Title:" +msgstr "Tutuł:" + +#: cdopener.cpp:212 optionseditor.cpp:235 +msgid "Comment:" +msgstr "Komentarz:" + +#: cdopener.cpp:242 +msgid "Save cuesheet ..." +msgstr "Zachowaj plik cue" + +#: cdopener.cpp:250 +msgid "Add all tracks" +msgstr "Dodaj wszystkie scieżki" + +#: cdopener.cpp:251 +msgid "Add selected tracks" +msgstr "Dodaj wybrane scieżki" + +#: cdopener.cpp:253 +msgid "Add full CD as one file" +msgstr "Dodaj całą płyte jako plik" + +#: cdopener.cpp:440 +msgid "All tracks" +msgstr "Wszystkie Scieżki" + +#: cdopener.cpp:443 +msgid "Tracks" +msgstr "Ścieżki" + +#: cdopener.cpp:742 +msgid "" +"A file with this name already exists.\n" +"\n" +"Do you want to overwrite the existing one?" +msgstr "" +"Istnieje już plik o wybranej nazwie.\n" +"Czy chcesz go nadpisac?" + +#: cdopener.cpp:743 +msgid "File already exists" +msgstr "Plik już istnieje" + +#: config.cpp:103 config.cpp:104 config.cpp:1197 config.cpp:1206 +#: config.cpp:1237 configgeneralpage.cpp:37 configgeneralpage.cpp:60 +#: configgeneralpage.cpp:62 configgeneralpage.cpp:269 +#: configgeneralpage.cpp:273 configgeneralpage.cpp:297 +#: configgeneralpage.cpp:306 configgeneralpage.cpp:316 options.cpp:153 +#: optionsdetailed.cpp:363 optionssimple.cpp:49 optionssimple.cpp:221 +#: optionssimple.cpp:518 soundkonverter.cpp:308 soundkonverter.cpp:309 +msgid "Last used" +msgstr "Ostatnio używane" + +#: config.cpp:508 +msgid "Convert with soundKonverter ..." +msgstr "Konwertuj SoundKonverterem" + +#: config.cpp:543 +msgid "Add Replay Gain with soundKonverter ..." +msgstr "Dodaj Replay Gain" + +#: config.cpp:1228 config.cpp:1229 configgeneralpage.cpp:57 +#: configgeneralpage.cpp:302 convert.cpp:431 filelist.cpp:1379 +#: optionsdetailed.cpp:361 optionsdetailed.cpp:427 optionsdetailed.cpp:477 +#: optionsdetailed.cpp:527 optionsdetailed.cpp:604 optionssimple.cpp:46 +#: optionssimple.cpp:140 optionssimple.cpp:180 optionssimple.cpp:218 +#: optionssimple.cpp:407 optionssimple.cpp:515 optionssimple.cpp:535 +msgid "Lossless" +msgstr "Bezstratny" + +#: config.cpp:1232 config.cpp:1233 configgeneralpage.cpp:58 +#: configgeneralpage.cpp:312 convert.cpp:434 convert.cpp:1378 +#: filelist.cpp:1382 optionsdetailed.cpp:362 optionsdetailed.cpp:480 +#: optionsdetailed.cpp:618 optionssimple.cpp:47 optionssimple.cpp:141 +#: optionssimple.cpp:185 optionssimple.cpp:219 optionssimple.cpp:421 +#: optionssimple.cpp:430 optionssimple.cpp:516 optionssimple.cpp:544 +msgid "Hybrid" +msgstr "Mieszany" + +#: config.cpp:1245 config.cpp:1252 config.cpp:1259 config.cpp:1266 +#: config.cpp:1273 convert.cpp:403 convert.cpp:995 convert.cpp:1567 +#: filelist.cpp:139 filelist.cpp:752 filelist.cpp:1270 filelist.cpp:1351 +#: optionsdetailed.cpp:246 optionsdetailed.cpp:467 optionsdetailed.cpp:582 +#: optionsdetailed.cpp:641 optionssimple.cpp:38 optionssimple.cpp:283 +#: optionssimple.cpp:312 optionssimple.cpp:340 optionssimple.cpp:367 +#: optionssimple.cpp:394 +msgid "Quality" +msgstr "Jakość" + +#: config.cpp:1248 config.cpp:1285 convert.cpp:450 filelist.cpp:1398 +#: optionsdetailed.cpp:538 optionssimple.cpp:294 +msgid "Mono" +msgstr "Mono" + +#: config.cpp:1250 config.cpp:1287 configgeneralpage.cpp:52 +#: configgeneralpage.cpp:289 optionsdetailed.cpp:356 optionssimple.cpp:41 +#: optionssimple.cpp:135 optionssimple.cpp:155 optionssimple.cpp:213 +#: optionssimple.cpp:269 optionssimple.cpp:510 optionssimple.cpp:525 +msgid "Very low" +msgstr "Bardzo niski" + +#: config.cpp:1257 config.cpp:1294 configgeneralpage.cpp:53 +#: configgeneralpage.cpp:111 configgeneralpage.cpp:290 optionsdetailed.cpp:357 +#: optionssimple.cpp:42 optionssimple.cpp:136 optionssimple.cpp:160 +#: optionssimple.cpp:214 optionssimple.cpp:298 optionssimple.cpp:511 +#: optionssimple.cpp:525 +msgid "Low" +msgstr "Mało" + +#: config.cpp:1264 config.cpp:1301 configgeneralpage.cpp:54 +#: configgeneralpage.cpp:291 optionsdetailed.cpp:358 optionseditor.cpp:713 +#: optionssimple.cpp:43 optionssimple.cpp:137 optionssimple.cpp:165 +#: optionssimple.cpp:215 optionssimple.cpp:326 optionssimple.cpp:512 +#: optionssimple.cpp:526 +msgid "Medium" +msgstr "Średnia" + +#: config.cpp:1271 config.cpp:1308 configgeneralpage.cpp:55 +#: configgeneralpage.cpp:292 optionsdetailed.cpp:359 optionssimple.cpp:44 +#: optionssimple.cpp:138 optionssimple.cpp:170 optionssimple.cpp:216 +#: optionssimple.cpp:353 optionssimple.cpp:513 optionssimple.cpp:526 +msgid "High" +msgstr "Wysoka" + +#: config.cpp:1278 config.cpp:1315 configgeneralpage.cpp:56 +#: configgeneralpage.cpp:293 optionsdetailed.cpp:360 optionssimple.cpp:45 +#: optionssimple.cpp:139 optionssimple.cpp:175 optionssimple.cpp:217 +#: optionssimple.cpp:380 optionssimple.cpp:514 optionssimple.cpp:527 +msgid "Very high" +msgstr "Bardzo wysok" + +#: config.cpp:1282 config.cpp:1289 config.cpp:1296 config.cpp:1303 +#: config.cpp:1310 convert.cpp:387 convert.cpp:996 convert.cpp:997 +#: convert.cpp:1568 convert.cpp:1569 filelist.cpp:1234 filelist.cpp:1245 +#: filelist.cpp:1255 filelist.cpp:1335 optionsdetailed.cpp:246 +#: optionsdetailed.cpp:470 optionsdetailed.cpp:560 optionssimple.cpp:287 +#: optionssimple.cpp:316 optionssimple.cpp:344 optionssimple.cpp:371 +#: optionssimple.cpp:398 +msgid "Bitrate" +msgstr "Bitrate" + +#: config.cpp:1351 optionsdetailed.cpp:365 optionssimple.cpp:51 +#: optionssimple.cpp:142 optionssimple.cpp:190 optionssimple.cpp:223 +#: optionssimple.cpp:435 optionssimple.cpp:454 optionssimple.cpp:458 +#: optionssimple.cpp:468 optionssimple.cpp:472 optionssimple.cpp:520 +#: optionssimple.cpp:552 +msgid "User defined" +msgstr "Zdefiniowane przez użytkownika" + +#: config.cpp:1394 config.cpp:1407 config.cpp:1411 config.cpp:1457 +#: config.cpp:1461 +msgid "files" +msgstr "pliki:" + +#: config.cpp:1419 config.cpp:1469 +msgid "all supported formats" +msgstr "Wszystkie wspierane formaty" + +#: config.cpp:1419 config.cpp:1469 +msgid "all formats" +msgstr "Wszystkie formaty" + +#: configbackendspage.cpp:42 +msgid "Legend" +msgstr "Legenda" + +#: configbackendspage.cpp:45 +msgid "Full support" +msgstr "Pełne wsparcie" + +#: configbackendspage.cpp:48 +msgid "Most supported" +msgstr "Dobre wsparcie" + +#: configbackendspage.cpp:51 +msgid "Basic support" +msgstr "Podstawowe wsparcie" + +#: configbackendspage.cpp:57 +msgid "CD Ripper" +msgstr "Ripper CD" + +#: configbackendspage.cpp:243 +msgid "Encoder" +msgstr "koder" + +#: configbackendspage.cpp:256 +msgid "Strength" +msgstr "Siła" + +#: configbackendspage.cpp:263 +msgid "" +"Set the compression strength:\n" +"\n" +"Left = fast conversion\n" +"Right = good resultant file" +msgstr "" +"Ustaw siłę kompresji\n" +"\n" +"Lewo = szybka konwersja /Gorsza jakość\n" +"Prawo = wolna konwersja/Dobra jakość" + +#: configbackendspage.cpp:272 +msgid "Decoder" +msgstr "Dekoder" + +#: configbackendspage.cpp:286 convert.cpp:593 convert.cpp:1580 +#: optionsdetailed.cpp:168 +msgid "Replay Gain" +msgstr "Replay Gain" + +#: configbackendspage.cpp:295 +msgid "Use internal Replay Gain" +msgstr "Uzyj wbudowanego Replay Gain" + +#: configbackendspage.cpp:296 +msgid "Use the internal Replay Gain calculator of the encoder" +msgstr "Użyj wbudowanego przelicznika Replay Gain w enkoderze" + +#: configbackendspage.cpp:320 +msgid "KDE audio CD protocol" +msgstr "Protokół AudioCD KDE" + +#: configdialog.cpp:31 +msgid "Settings" +msgstr "Ustawienia" + +#: configdialog.cpp:56 +msgid "General" +msgstr "Ogólne" + +#: configdialog.cpp:68 +msgid "Plugins" +msgstr "Wtyczki" + +#: configdialog.cpp:80 +msgid "Environment" +msgstr "Środowisko" + +#: configdialog.cpp:92 +msgid "Backends" +msgstr "Backends" + +#: configenvironmentpage.cpp:32 +msgid "Directories to be scanned" +msgstr "Katalogi do skanowania" + +#: configenvironmentpage.cpp:50 +msgid "" +"Move selected directory one position up.\n" +"This effects which backend will be chosen, if there are several versions." +msgstr "" +"Przenieś wybrany katalog o jedną pozycję w góre\n" +"To spowoduje wybranie odpowiedniej wersji backendu." + +#: configenvironmentpage.cpp:60 +msgid "" +"Move selected directory one position down.\n" +"This effects which backend will be chosen, if there are several versions." +msgstr "" +"Przenieś wybrany katalog o jedną pozycję w dół.\n" +"To spowoduje wybranie odpowiedniej wersji backendu." + +#: configenvironmentpage.cpp:67 configpluginspage.cpp:50 +msgid "Add ..." +msgstr "Dodaj" + +#: configenvironmentpage.cpp:87 +msgid "Programs found" +msgstr "Znaleziono program" + +#: configenvironmentpage.cpp:96 +msgid "Programs not found" +msgstr "Nie znaleziono programu" + +#: configgeneralpage.cpp:34 +msgid "Start in Mode" +msgstr "Startuj jako" + +#: configgeneralpage.cpp:38 options.cpp:36 +msgid "Simple" +msgstr "Prosty" + +#: configgeneralpage.cpp:39 options.cpp:41 +msgid "Detailed" +msgstr "Szczegółowy" + +#: configgeneralpage.cpp:49 +msgid "Default profile" +msgstr "Domyślny profil" + +#: configgeneralpage.cpp:72 +msgid "Default format" +msgstr "Domyślny format" + +#: configgeneralpage.cpp:107 +msgid "Process priority of the backends" +msgstr "Priorytet procesów backendów" + +#: configgeneralpage.cpp:110 +msgid "Normal" +msgstr "Zwykly" + +#: configgeneralpage.cpp:122 +msgid "Use FAT compatible output file names" +msgstr "Używaj nazw plików zgodnych z FAT" + +#: configgeneralpage.cpp:123 +msgid "Replaces some special characters like '?' by '_'." +msgstr "Zmienia niektóre znaki specjalne jak '?' na '-'." + +#: configgeneralpage.cpp:133 +msgid "Conflict handling" +msgstr "" + +#: configgeneralpage.cpp:136 +msgid "Do that if the output file already exists" +msgstr "" + +#: configgeneralpage.cpp:137 +msgid "Generate new file name" +msgstr "" + +#: configgeneralpage.cpp:138 +msgid "Skip file" +msgstr "" + +#: configgeneralpage.cpp:149 +msgid "Number of files to convert at once" +msgstr "Numer plików do jednoczesnej konwersji" + +#: configgeneralpage.cpp:160 +msgid "Status update delay (time in msec.)" +msgstr "Opóźnienie stanu aktualizacji (czas w msek.)" + +#: configgeneralpage.cpp:163 +msgid "Update the progress bar in this interval (time in milliseconds)" +msgstr "Aktualizuj pasek postępu co ... ( czas w msek)" + +#: configgeneralpage.cpp:172 +msgid "Ask for new options, when adding files from external program" +msgstr "" +"Zapytaj o nowe opcje podczas dodawania plików z zewnętrznego programu" + +#: configgeneralpage.cpp:173 +msgid "" +"If you open a file with soundKonverter and soundKonverter is already " +"running,\n" +"you can either be asked to define new converting options\n" +"or the current settings from the soundKonverter main window are used." +msgstr "" +"Jeśli otwierasz plik przy pomocy soundKonvertera i soundKonverter jest już " +"uruchomiony,\n" +"możesz otrzymać pytanie czy zdefiniować nowe opcje konwersji,\n" +"czy też użyć aktualnych ustawień z okna głównego." + +#: configgeneralpage.cpp:183 +msgid "Execute user script (for advanced users)" +msgstr "" + +#: configgeneralpage.cpp:184 +msgid "" +"Executes a script after every finished conversion. Have a look at " +"$KDEDIR/soundkonverter/userscript.sh" +msgstr "" + +#: configpluginspage.cpp:39 +msgid "Installed plugins" +msgstr "Zainstalowane wtyczki" + +#: configpluginspage.cpp:228 +msgid "*.soundkonverter.xml|Plugins (*.soundkonverter.xml)" +msgstr "*.soundkonverter.xml|Plugins (*.soundkonverter.xml)" + +#: configpluginspage.cpp:228 +msgid "Choose a plugin to add!" +msgstr "Wybierz wtyczke do dodania" + +#: configpluginspage.cpp:253 configpluginspage.cpp:546 +msgid "" +"The plugin could not be installed. Please ensure that you have selected a " +"valid soundKonverter plugin file." +msgstr "" +"Ups Chyba tego nie zainstaluje ): .Upewnij się że wybrałeś odpowiedni plik " +"wtyczki" + +#: configpluginspage.cpp:254 configpluginspage.cpp:294 +#: configpluginspage.cpp:547 configpluginspage.cpp:587 +msgid "Error while installing plugin" +msgstr "Błąd podczas instalacji wtyczki" + +#: configpluginspage.cpp:279 configpluginspage.cpp:572 +msgid "" +"The plugin was installed successfully. Please restart soundKonverter in " +"order to activate it." +msgstr "Wtyczka jest już zainstalowana. Uruchom ponownie SoundKonvertera" + +#: configpluginspage.cpp:280 configpluginspage.cpp:573 +msgid "Plugin successfully installed" +msgstr "Pomyślnie zainstalowano wtyczke" + +#: configpluginspage.cpp:293 configpluginspage.cpp:586 +msgid "" +"The plugin could not be installed. Please ensure that you have write " +"permission on your whole user directory." +msgstr "" +"Wtyczka nie może być zainstalowana. Upewnij się ze masz pozwolenie na zapis " +"w katalogu." + +#: configpluginspage.cpp:311 configpluginspage.cpp:330 +#: configpluginspage.cpp:349 +msgid "" +"The plugin was removed successfully. Please restart soundKonverter in order " +"to deactivate it." +msgstr "" +"Wtyczka usunięta pomyślnie. Uruchom soundKonverter ponownie aby uczynić ją " +"nieaktywną" + +#: configpluginspage.cpp:312 configpluginspage.cpp:331 +#: configpluginspage.cpp:350 +msgid "Plugin successfully removed" +msgstr "Wtyczka usunięta pomyślnie" + +#: configpluginspage.cpp:316 configpluginspage.cpp:335 +#: configpluginspage.cpp:354 +msgid "" +"The plugin could not be removed. Please ensure that you have write " +"permission on your whole user directory." +msgstr "" +"Wtyczka nie może być usunięta. Upewnij się ze masz pozwolenie na zapis w " +"katalogu." + +#: configpluginspage.cpp:317 configpluginspage.cpp:336 +#: configpluginspage.cpp:355 +msgid "Error while removing plugin" +msgstr "Błąd podczas usuwania wtyczki" + +#: configpluginspage.cpp:383 configpluginspage.cpp:395 +#: configpluginspage.cpp:407 +msgid "Version" +msgstr "Wersja" + +#: configpluginspage.cpp:384 configpluginspage.cpp:396 +#: configpluginspage.cpp:408 +msgid "Author" +msgstr "Autor" + +#: configpluginspage.cpp:417 configpluginspage.cpp:472 +msgid "No new plugins available!" +msgstr "Brak nowych wtyczek" + +#: configpluginspage.cpp:477 +msgid "" +"The plugin list could not be downloaded. Please ensure, that your internet " +"connection works correct.\n" +"Maybe our server is busy at the moment, please try it again later." +msgstr "" +"Wtyczka nie może zostać pobrana. Sprawdz swoje połączenie z Internetem\n" +"\n" +"Serwer moze byc aktualnie zajęty. Spróbuj póżniej" + +#: configpluginspage.cpp:478 +msgid "Error while loading plugin list" +msgstr "Błąd podczas ładowania listy wtyczek" + +#: configpluginspage.cpp:626 configpluginspage.cpp:632 +msgid "" +"The plugin info could not be downloaded. Please ensure, that your internet " +"connection works correctly." +msgstr "" +"Nie można pobrać informacji o wtyczce. Sprawdz swoje połączenie z siecią" + +#: configpluginspage.cpp:627 configpluginspage.cpp:633 +msgid "Error while loading plugin info" +msgstr "Błąd podczas ładowania informacji o wtyczce" + +#: convert.cpp:83 convert.cpp:86 convert.cpp:1538 +msgid "Getting file" +msgstr "Pobieranie pliku" + +#: convert.cpp:86 convert.cpp:130 convert.cpp:190 convert.cpp:260 +#: convert.cpp:314 convert.cpp:555 convert.cpp:593 convert.cpp:603 +#: convert.cpp:617 convert.cpp:661 convert.cpp:694 convert.cpp:1538 +#: convert.cpp:1542 convert.cpp:1547 convert.cpp:1551 convert.cpp:1557 +#: convert.cpp:1561 convert.cpp:1571 convert.cpp:1575 convert.cpp:1580 +#: convert.cpp:1583 convert.cpp:1587 filelist.cpp:136 filelist.cpp:638 +#: filelist.cpp:641 filelist.cpp:650 filelist.cpp:651 filelist.cpp:696 +#: filelist.cpp:726 filelist.cpp:729 filelist.cpp:733 filelist.cpp:860 +#: filelist.cpp:861 filelist.cpp:918 filelist.cpp:955 filelist.cpp:956 +msgid "State" +msgstr "Status" + +#: convert.cpp:116 convert.cpp:130 convert.cpp:1542 +msgid "Getting correction file" +msgstr "Pobieranie pliku naprawczego" + +#: convert.cpp:122 +msgid "Aborting, file does not exist" +msgstr "Anulowanie, plik nie istnieje" + +#: convert.cpp:157 convert.cpp:190 convert.cpp:260 convert.cpp:1547 +#: convert.cpp:1551 +msgid "Ripping" +msgstr "Ripowanie" + +#: convert.cpp:270 convert.cpp:314 convert.cpp:1557 convert.cpp:1561 +msgid "Decoding" +msgstr "Dekodowanie" + +#: convert.cpp:334 convert.cpp:555 convert.cpp:1571 convert.cpp:1575 +msgid "Encoding" +msgstr "Kodowanie" + +#: convert.cpp:453 filelist.cpp:1401 optionsdetailed.cpp:541 +msgid "Stereo" +msgstr "Stereofoniczny" + +#: convert.cpp:456 filelist.cpp:1404 optionsdetailed.cpp:544 +msgid "Joint-Stereo" +msgstr "Joint-Stereo" + +#: convert.cpp:459 filelist.cpp:1407 optionsdetailed.cpp:547 +msgid "Forced Joint-Stereo" +msgstr "Wymuszone Joint-Stereo" + +#: convert.cpp:462 filelist.cpp:1410 optionsdetailed.cpp:550 +msgid "Dual Channels" +msgstr "Podwójne Kanaly" + +#: convert.cpp:563 replaygainfilelist.cpp:914 +msgid "Applying Replay Gain" +msgstr "Akceptacja Replay Gain" + +#: convert.cpp:598 convert.cpp:603 +msgid "Writing tags" +msgstr "Zapisywanie Tagow" + +#: convert.cpp:611 convert.cpp:617 convert.cpp:1583 +msgid "Moving file" +msgstr "Przenoszenie pliku" + +#: convert.cpp:649 convert.cpp:661 convert.cpp:1587 +msgid "Moving correction file" +msgstr "Przenoszenie pliku korygującego" + +#: convert.cpp:688 convert.cpp:694 +msgid "Running user script" +msgstr "" + +#: convert.cpp:713 +msgid "Executing next step" +msgstr "przygotowanie do następnego kroku" + +#: convert.cpp:857 convert.cpp:874 convert.cpp:1123 convert.cpp:1147 +msgid "Got file" +msgstr "zakonczono" + +#: convert.cpp:891 convert.cpp:1204 convert.cpp:1216 +msgid "Could not write to file: `%1'" +msgstr "Brak praw zapisu w pliku '%1'" + +#: convert.cpp:903 convert.cpp:918 convert.cpp:1228 convert.cpp:1255 +msgid "File moved" +msgstr "Plik przeniesiony" + +#: convert.cpp:941 filelist.cpp:70 filelist.cpp:138 filelist.cpp:750 +#: outputdirectory.cpp:39 replaygainfilelist.cpp:1141 +msgid "Output" +msgstr "Wyjscie" + +#: convert.cpp:1292 +msgid "Adding new item to conversion list: `%1'" +msgstr "" + +#: convert.cpp:1299 +msgid "Got log ID: %1" +msgstr "Zidentifikowano log ID '%1'" + +#: convert.cpp:1302 +msgid "Tags successfully read" +msgstr "Tagi przeczytane" + +#: convert.cpp:1303 +msgid "Reading tags failed" +msgstr "Błąd w czytaniu tagów" + +#: convert.cpp:1443 convert.cpp:1453 replaygainfilelist.cpp:1025 +msgid "Killing process ..." +msgstr "Zamykanie procesu..." + +#: convert.cpp:1446 replaygainfilelist.cpp:1028 +msgid "Killing process failed. Stopping after files are completed ..." +msgstr "" +"Nieudane zamknięcie procesu. Zamknięcie nastąpi po ukończeniu pracy na " +"plikach..." + +#: convert.cpp:1468 +msgid "Removing file from conversion list. Exit code %1" +msgstr "Usuwanie pliku z listy konwersji . Kod wyjścia %1" + +#: convert.cpp:1475 +msgid "Executing command: \"%1\"" +msgstr "Wykonuję polecenie: \"%1\"" + +#: cuesheeteditor.cpp:29 +msgid "Cuesheet Editor" +msgstr "Edytor Cuesheet" + +#: cuesheeteditor.cpp:76 +msgid "Generate" +msgstr "Generuj" + +#: cuesheeteditor.cpp:82 +msgid "Format" +msgstr "Format" + +#: cuesheeteditor.cpp:88 +msgid "Shift Title/Performer" +msgstr "Zamień Tytuł/Wykonawca" + +#: cuesheeteditor.cpp:113 +msgid "" +"

With this small tool you can process cue files as they are used for " +"burning music mixes and for organizing them in media players like " +"amaroK.

You can generate a new file by pasting text into the input " +"area. It must be formated the following way:

Title - Artist " +"[time]
Title - Artist [3:25]
Title - Artist [2:37]
...
A tip: " +"Use kwrite and regular expressions to format it this way.

" +msgstr "" +"

Przy pomocy tego narzędzia możesz przetwarzać pliki \"cue\", które potem " +"używane są do nagrywania muzyki oraz wykorzystywane są do zarządzania " +"listami w odtwarzaczach takich jak amaroK..

Możesz utworzyć nowy plik " +"wklejając tekst w tym oknie. Składnia musi wyglądać " +"następująco:

Tytuł - Wykonawca [czas]
Tytuł - Wykonawca " +"[3:25]
Tytuł - Wykonawca [2:37]
...
Wskazówka: Użyj kwrite i " +"wyrażeń regularnych aby sformatować tekst w ten sposób.

" + +#: cuesheeteditor.cpp:114 +msgid "Cuesheet Editor - Help" +msgstr "Edytor Cuesheet - Pomoc" + +#: dirdialog.cpp:24 +msgid "Add folder" +msgstr "Dodaj katalog ..." + +#: dirdialog.cpp:33 +msgid "Directory:" +msgstr "Katalog:" + +#: dirdialog.cpp:63 +msgid "Select all" +msgstr "Wybierz wszystko" + +#: dirdialog.cpp:69 +msgid "Select none" +msgstr "Nic nie wybieraj" + +#: dirdialog.cpp:75 +msgid "Recursive" +msgstr "" + +#: dirdialog.cpp:106 dirdialog.cpp:133 +msgid "Choose a directory" +msgstr "Wybierz katalog" + +#: filelist.cpp:70 filelist.cpp:137 filelist.cpp:736 filelist.cpp:737 +msgid "Input" +msgstr "Źródło" + +#: filelist.cpp:170 +msgid "Edit options ..." +msgstr "Edytyj pcje" + +#: filelist.cpp:171 +msgid "Start conversion" +msgstr "Rozpocznij onwersje" + +#: filelist.cpp:172 +msgid "Stop conversion" +msgstr "Zatrzymaj konwersje" + +#: filelist.cpp:184 +msgid "" +"

File List

Select your desired output options in " +"the form above and add some files.
You can add files by clicking on " +"\"Add files ...\" or dropping them here.
" +msgstr "" +"

File List

Wybierz jedną z powyższych opcji i dodaj " +"pliki.
. Możesz to zrobic klikając na \"Dodaj pliki\" albo po prostu " +"przeciagnąć je tutaj.
" + +#: filelist.cpp:578 filelist.cpp:593 +msgid "Audio CD (%1)" +msgstr "Audio CD (%1)" + +#: filelist.cpp:609 filelist.cpp:624 +msgid "Full audio CD (%1)" +msgstr "Pełne audio CD (%1)" + +#: filelist.cpp:638 filelist.cpp:650 filelist.cpp:955 +msgid "Stopped" +msgstr "Zatrzymany" + +#: filelist.cpp:641 filelist.cpp:650 filelist.cpp:955 +msgid "Failed" +msgstr "Nieudane" + +#: filelist.cpp:650 filelist.cpp:726 filelist.cpp:860 filelist.cpp:955 +msgid "Will be skipped" +msgstr "" + +#: filelist.cpp:651 filelist.cpp:696 filelist.cpp:729 filelist.cpp:861 +#: filelist.cpp:918 filelist.cpp:956 progressindicator.cpp:49 +msgid "Waiting" +msgstr "Oczekiwanie" + +#: filelist.cpp:733 +msgid "Converting" +msgstr "Konwertowanie" + +#: logger.cpp:136 +msgid "Finished logging" +msgstr "Kończenie logowania" + +#: logviewer.cpp:83 +msgid "Log Viewer" +msgstr "Przegląd logów" + +#: logviewer.cpp:90 +msgid "Job/File" +msgstr "Zadanie/Plik" + +#: main.cpp:12 +msgid "" +"soundKonverter is a frontend to various sound en- and decoding programs." +msgstr "" +"SoundKonverter jest \"nakladką\" na rózne dzwiękowe aplikacje kodujące i " +"rozkodowywujące" + +#: main.cpp:18 +msgid "Open the Replay Gain tool an add all given files" +msgstr "Otwórz narzędzia Replay Gain i dodaj wszystkie pliki" + +#: main.cpp:20 +msgid "List all tracks on the cd drive , 'auto' will search for a cd" +msgstr "" +"Pokaż wszystkie ścieżki na dysku cd 'auto' wyszuka " +"automatycznie płyte" + +#: main.cpp:21 +msgid "Add all files using the given profile" +msgstr "Dodaj wszystkie pliki uzywając wybranego profilu" + +#: main.cpp:22 +msgid "Add all files using the given format" +msgstr "Dodaj wszystkie pliki uzywając wybranego formatu" + +#: main.cpp:23 +msgid "Output all files to " +msgstr "Zapisz wszystkie pliki do " + +#: main.cpp:24 +msgid "Start soundKonverter invisible" +msgstr "Uruchom soundKonverter w trybie \"niewidoczny\"" + +#: main.cpp:25 +msgid "" +"Close soundKonverter after all files are converted (enabled when using '--" +"invisible')" +msgstr "Zamknij soundKonverter po udanej konwersji wszystkich plików" + +#: main.cpp:26 +msgid "Execute after each file has been converted" +msgstr "Wykonaj po konwersji kazdego z plików" + +#: main.cpp:27 +msgid "Audio file(s) to append to the file list" +msgstr "Plik/i audio do dołączenia do listy" + +#: main.cpp:33 +msgid "soundKonverter" +msgstr "soundKonverter" + +#: options.cpp:127 +msgid "" +"soundKonverter either found new backends or misses some.\n" +"Click on this button in order to open the configuration dialog." +msgstr "" +"soundKonverter znalazł nowe programy zewnętrzne lub stwierdził brak któregoś " +"z nich.\n" +"Kliknij na ten przycisk aby otworzyć okno konfiguracji." + +#: options.cpp:136 +msgid "Advanced Options" +msgstr "Zaawansowane ustawienia" + +#: optionsdetailed.cpp:45 +msgid "Convert" +msgstr "Konwertuj" + +#: optionsdetailed.cpp:73 +msgid "" +"vbr - variable bitrate\n" +"abr - average bitrate\n" +"cbr - constant bitrate" +msgstr "" +"vbr - zmienna szybkość transmisji\n" +"abr - uśredniona szybkość transmisji\n" +"cbr - stała szybkość transmisji" + +#: optionsdetailed.cpp:83 +msgid "Bitrate range" +msgstr "Zasięg bitrate" + +#: optionsdetailed.cpp:84 +msgid "" +"Use it only if, you know what you are doing, you could reduce the quality." +msgstr "Używaj tylko wtedy jeśli wiesz co robisz, możesz zmniejszyć jakośc" + +#: optionsdetailed.cpp:119 +msgid "Resample" +msgstr "" +"Resampling. Szczegóły tu " + +#: optionsdetailed.cpp:147 +msgid "Channels" +msgstr "Kanały" + +#: optionsdetailed.cpp:170 +msgid "Add a Replay Gain tag to the converted file." +msgstr "Dodaj reply gain do skonvertowanych plików" + +#: optionsdetailed.cpp:171 +msgid "" +"Replay Gain is a volume correction technique. A volume difference is " +"calculated and stored in a tag. This way audio players can automatically " +"adjust the volume and the original music data is not modified (like at " +"normalization)." +msgstr "" +"Replay Gain jest to technika korekcji głośności. Różnice głośności są " +"obliczane i zapisywane w znaczniku. Dzięki temu odtwarzacze audio mogą " +"automatycznie korygować głośność, bez konieczności modyfikowania " +"oryginalnych plików (tak jak przy normalizacji)" + +#: optionsdetailed.cpp:192 +msgid "Save current options as a profile" +msgstr "Zapisz wybrane opcje jako profil" + +#: optionsdetailed.cpp:208 +msgid "Command" +msgstr "Polecenie" + +#: optionsdetailed.cpp:219 +#, c-format +msgid "%p: The parameters generated by soundKonverter" +msgstr "%p Parametry stworzone przez soundKonverter" + +#: optionsdetailed.cpp:225 +#, c-format +msgid "%i: The input file ; %o: The output file" +msgstr "%i: Plik wejściowy ; %o: Plik wyjściowy" + +#: optionsdetailed.cpp:353 +msgid "New profile" +msgstr "Nowy profil" + +#: optionsdetailed.cpp:353 +msgid "Enter a name for the new profile:" +msgstr "Wprowadź nazwę nowego profilu:" + +#: optionsdetailed.cpp:368 +msgid "You cannot overwrite the built-in profiles." +msgstr "Nie można nadpisać wbudowanych już profili" + +#: optionsdetailed.cpp:369 optionsdetailed.cpp:379 +msgid "Profile already exists" +msgstr "Wybrałeś już istniejący profil" + +#: optionsdetailed.cpp:378 +msgid "" +"A profile with this name already exists.\n" +"\n" +"Do you want to overwrite the existing one?" +msgstr "" +"Wybrany profil już istnieje.\n" +"\n" +"Nadpisać?" + +#: optionsdetailed.cpp:473 optionsdetailed.cpp:628 +msgid "Unchanged" +msgstr "Niezmienione" + +#: optionsdetailed.cpp:483 optionsdetailed.cpp:604 +msgid "Undefined" +msgstr "Nieokreślone" + +#: optionsdetailed.cpp:561 optionsdetailed.cpp:619 +msgid "Kilobit per second" +msgstr "Kilobit na sekunde" + +#: optionsdetailed.cpp:689 +msgid "" +"This is a relative quality between 0 and 100.\n" +"The higher this number the higher is the quality.\n" +"soundKonverter will convert it into the file format's quality format.\n" +"See the \"What's this?\" for more informations.\n" +"\n" +"Current parameter: \"%1\"" +msgstr "" +"To jest skala jakości od 0 do 100.\n" +"Im wyższy numer, tym wyższa jakośc.\n" +"soundKonverter przekonwertuje ją na bardziej \"plikowy\" format.\n" +"Jeśli chcesz wiedzieć więcej, zobacz \"Co to jest\".\n" +"\n" +"Obecne ustawienie: \"%1\"" + +#: optionseditor.cpp:28 +msgid "Options Editor" +msgstr "Edytor Opcji" + +#: optionseditor.cpp:55 +msgid "Conversion" +msgstr "Konwersja" + +#: optionseditor.cpp:55 +msgid "Conversion options" +msgstr "Opcje konwersji" + +#: optionseditor.cpp:59 +msgid "Choose your prefered output options and click on \"Close\"!" +msgstr "" +"Wybierz preferowane opcje wyjściowe a następnie kliknij \"Zamknij\"!" + +#: optionseditor.cpp:70 +msgid "Edit conversion options" +msgstr "Edytuj ustawienia konwersji" + +#: optionseditor.cpp:79 +msgid "Tags" +msgstr "Tagi" + +#: optionseditor.cpp:103 +msgid "Track No.:" +msgstr "Numer scieżki.:" + +#: optionseditor.cpp:256 +msgid "Edit tags" +msgstr "Edytuj tagi" + +#: optionseditor.cpp:330 +msgid "No file selected" +msgstr "Nie wybrano plików" + +#: optionseditor.cpp:358 +msgid "" +"The tags could not be read, because this file isn't a local one.\n" +"soundKonverter will try to read the tags, when it is about to convert the " +"file.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags." +msgstr "" +"Znaczniki nie zostały odczytane, ponieważ ten plik nie jest plikiem " +"lokalnym.\n" +"soundKonverter spróbuje odczytać znaczniki, gdy zacznie konwertować ten " +"plik.\n" +"Jeśli chcesz zmienić znaczniki, możesz nacisnąć przycisk poniżej, ale wtedy\n" +"soundKonverter nie będzie odczytywał tagów." + +#: optionseditor.cpp:367 +msgid "" +"Reading the tags of this file failed.\n" +"soundKonverter will try to read the tags a second time, when it is about to " +"convert the file.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags a second time." +msgstr "" +"Nie udało się odczytać tagów w tym pliku.\n" +"soundKonverter spróbuje odczytać je jeszcze raz, przed konwersją pliku.\n" +"Jeśli chcesz samemu wyedytować tagi, naciśnij przycisk poniżej, ale pamiętaj " +"że w takim wypadku soundKonverter nie będzie już starał sie ich odczytać po " +"raz drugi." + +#: optionseditor.cpp:387 +msgid "%1 Files" +msgstr "%1 Pliki" + +#: optionseditor.cpp:402 +msgid "" +"You have selected multiple files with different conversion options.\n" +"You can change the options of all files by hitting the button below." +msgstr "" +"Wybrałeś kilka plików z różnymi opcjami konwersji.\n" +"Możesz zmienić te ustawienia naciskając przycisk poniżej." + +#: optionseditor.cpp:408 +msgid "" +"Reading the tags of one or more files failed.\n" +"soundKonverter will try to read the tags a second time, when it is about to " +"convert the files.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags a second time." +msgstr "" +"Nie udało się odczytać tagów w jednym , lub więcej pliku.\n" +"soundKonverter spróbuje odczytać je jeszcze raz, przed konwersją pliku.\n" +"Jeśli chcesz samemu wyedytować tagi, naciśnij przycisk poniżej, ale pamiętaj " +"że w takim wypadku soundKonverter nie będzie już starał sie ich odczytać po " +"raz drugi." + +#: optionsrequester.cpp:18 +msgid "Choose output options" +msgstr "Wybierz opcje wyjściowe" + +#: optionsrequester.cpp:28 +msgid "Click on \"Ok\" to add the files to the list in the main window!" +msgstr "Wybierz \"Ok\" aby dodać pliki do listy w głównym oknie!" + +#: optionsrequester.cpp:43 +msgid "" +"Warning: If you select \"wav\" as output format, your wav files will not be " +"added to the list." +msgstr "" +"Ostrzeżenie: Jesli wybierzesz \"wav\" jako format wyjściowy, pliki nie będą " +"dodane do listy." + +#: optionsrequester.cpp:59 +msgid "Ok" +msgstr "Ok" + +#: optionssimple.cpp:64 +msgid "Remove the selected profile" +msgstr "Usuń wybrany profil" + +#: optionssimple.cpp:70 optionssimple.cpp:90 +msgid "Info" +msgstr "Informacja" + +#: optionssimple.cpp:71 +msgid "Information about the selected profile" +msgstr "Informacje o wybranym profilu" + +#: optionssimple.cpp:78 +msgid "Output format" +msgstr "Format wyjściowy" + +#: optionssimple.cpp:91 +msgid "Information about the selected file format" +msgstr "Informacje o wybranym formacie plikow" + +#: optionssimple.cpp:157 +msgid "" +"This produces sound files of a very low quality.\n" +"That can be useful, if you have a mobile device, where your memory cell is " +"limited. It is not recommended to save your music in this quality without a " +"copy with higher quality.\n" +"It can also be used to save audio files with voices." +msgstr "" +"Otrzymasz pliki dźwiękowe o bardzo niskiej jakości.\n" +"Ten profil może być użyteczny jeśli posiadasz urządzenie przenośne " +"wyposażone w niewielką ilośćpamięci. Nie jest zalecane aby zapisywać muzykę " +"w takiej jakości, jeśli nie posiadasz kopii o wyższej jakości.\n" +"Można użyć tego profilu aby zapisywać pliki dźwiękowe z rozmową." + +#: optionssimple.cpp:158 optionssimple.cpp:163 optionssimple.cpp:168 +#: optionssimple.cpp:173 optionssimple.cpp:178 optionssimple.cpp:183 +#: optionssimple.cpp:188 optionssimple.cpp:193 +msgid "Profile" +msgstr "Profil" + +#: optionssimple.cpp:162 +msgid "" +"This produces sound files of a low quality.\n" +"That can be useful if you habe a mobile device where your memory cell is " +"limited. It is not recommended to save your music in this quality without a " +"copy with higher quality." +msgstr "" +"Ta opcja stworzy pliki dźwiękowe o bardzo słabej jakości.\n" +"Jeśli masz telefon komórkowy obsługujący formaty multimedialne i " +"ograniczoną pamięć, powyższa opcja może być dla ciebie użyteczna.\n" +"Nie jest jednak zalecane zapisywanie muzyki o takiej jakości bez posiadania " +"uprzedniej kopi o wyzszej jakości." + +#: optionssimple.cpp:167 +msgid "" +"This produces sound files of a medium quality.\n" +"If your disc space is limited, you can use this to save your music." +msgstr "" +"Ta opcja stworzy pliki dźwiękowe o średniej jakości.\n" +"Jeśli brak ci miejsca na dysku, użyj jej opcji w celu zapisu." + +#: optionssimple.cpp:172 +msgid "" +"This produces sound files of a high quality.\n" +"If you have enough disc space available, you can use this to save your music." +msgstr "" +"Ta opcja stworzy pliki dźwiękowe o wysokiej jakości.\n" +"Jeśli masz wystarczająco miejsca na dysku, użyj jej opcji w celu zapisu." + +#: optionssimple.cpp:177 +msgid "" +"This produces sound files of a very high quality.\n" +"You should only use this, if you are a quality freak and have enough disc " +"space available." +msgstr "" +"Ta opcja stworzy pliki dźwiękowe o bardzo wysokiej jakości.\n" +"Jeśli masz wyczulone ucho i wystarczająco miejsca na dysku, możesz jej użyć." + +#: optionssimple.cpp:182 +msgid "" +"This produces files, that have exact the same quality as the input files.\n" +"This files are very big and definitely only for quality freaks." +msgstr "" +"Otrzymasz pliki dźwiękowe o takiej samej jakości jak pliki wejściowe.\n" +"Pliki będą bardzo duże i zdecydowanie przeznaczone są dla maniaków jakości." + +#: optionssimple.cpp:187 +msgid "" +"This produces two files. One lossy compressed playable file and one " +"correction file.\n" +"Both files together result in a file that is equivalent to the input file." +msgstr "" +"Otrzymasz dwa pliki.\n" +"Jeden stratnie skompresowany i przeznaczony do odtwarzania, oraz jeden plik " +"korekcyjny.\n" +"Te dwa pliki łącznie są równoważne plikowi wejściowemu." + +#: optionssimple.cpp:192 +msgid "You can define your own profile in the \"detailed\" tab." +msgstr "Możesz zdefiniować własny profil w zakładce \"Szczegóły\"." + +#: optionssimple.cpp:205 +msgid "Do you really want to remove the profile: %1" +msgstr "Naprawdę chcesz usunąć profil: %1 ?" + +#: optionssimple.cpp:206 +msgid "Remove profile?" +msgstr "Usunąć profil?" + +#: optionssimple.cpp:234 +msgid "" +"

Wave is a file format, that doesn't compress it's audio data.

\n" +"

So the quality is very high, but the file size is enormous. It is widely " +"spread and should work with every audio player.

\n" +"
http://en.wikipedia.org/wiki/Wav" +msgstr "" +"

\"Wav\" jest to format pliku w którym dane dźwiękowe nie są " +"skompresowane.

\n" +"

Jakość dźwięku jest bardzo wysoka, jednak rozmiar takiego pliku jest " +"bardzo duży. Format ten jest szeroko stosowany i powinien być odtwarzany " +"przez każdy odtwarzacz audio.

\n" +"
http://pl.wikipedia.org/wiki/Wav" + +#: optionssimple.cpp:235 optionssimple.cpp:242 +msgid "File format" +msgstr "Format pliku" + +#: outputdirectory.cpp:44 +msgid "By meta data" +msgstr "Według metadanych" + +#: outputdirectory.cpp:45 +msgid "Source directory" +msgstr "Katalog źródłowy" + +#: outputdirectory.cpp:46 +msgid "Specify output directory" +msgstr "Wybierz katalog wyjściowy" + +#: outputdirectory.cpp:47 +msgid "Copy directory structure" +msgstr "Kopiuj strukture katalogu" + +#: outputdirectory.cpp:61 +msgid "Clear the directory input field" +msgstr "Wyczyść pole wpisu w katalogu" + +#: outputdirectory.cpp:81 outputdirectory.cpp:345 +msgid "Choose an output directory" +msgstr "Wybierz katalog wyjściowy" + +#: outputdirectory.cpp:87 +msgid "Open Konqueror with the output directory" +msgstr "Otworz katalog wyjściowy w konquerorze" + +#: outputdirectory.cpp:184 +msgid "Unknown Artist" +msgstr "Nieznany artysta" + +#: outputdirectory.cpp:188 +msgid "Unknown Album" +msgstr "Nieznany Album" + +#: outputdirectory.cpp:192 +msgid "No Comment" +msgstr "Brak komentarza" + +#: outputdirectory.cpp:199 +msgid "Unknown Genre" +msgstr "Nieznany gatunek" + +#: outputdirectory.cpp:206 +msgid "Unknown Composer" +msgstr "Nieznany kompozytor" + +#: outputdirectory.cpp:210 +msgid "Unknown Title" +msgstr "Nieznany tytuł" + +#: outputdirectory.cpp:264 +msgid "new" +msgstr "nowy" + +#: outputdirectory.cpp:406 +msgid "Name all converted files according to the specified pattern" +msgstr "Przemianuj wszystkie ukonczone pliki według okreslonego wzoru" + +#: outputdirectory.cpp:408 +msgid "" +"

The following strings are wildcards, that will be replaced by the " +"information in the meta data:

%a - Artist
%b - Album
%c - " +"Comment
%d - Disc number
%g - Genre
%n - Track number
%p - " +"Composer
%t - Title
%y - Year
%f - Original file name

" +msgstr "" +"

Następujące ciągi znaków są wzorcami, które zostaną zastąpione przez " +"informacje zawarte w znacznikach meta:

%a - Wykonawca
%b - " +"Album
%c - Komentarz
%d - Numer dysku
%g - Gatunek
%n - Numer " +"ścieżki
%p - Kompozytor
%t - Tytuł
%y - Rok
%f - Oryginalna " +"nazwa pliku

" + +#: outputdirectory.cpp:420 +msgid "" +"Output all converted files into the same directory as the original files" +msgstr "" +"Zapisz wszystkie przekonwertowane pliki do tego samego katalogu, w którym " +"znajdują się oryginalne pliki" + +#: outputdirectory.cpp:434 +msgid "Output all converted files into the specified output directory" +msgstr "Zapisz wszystkie przekonwertowane pliki do innego katalogu" + +#: outputdirectory.cpp:448 +msgid "Copy the whole directory structure for all converted files" +msgstr "Skopiuj pełną strukture katalogu dla wszystkich zmienionych plików" + +#: paranoia.cpp:214 +msgid "MB" +msgstr "MB" + +#: paranoia.cpp:215 +msgid "KB" +msgstr "KB" + +#: paranoia.cpp:216 +msgid "Bytes" +msgstr "bajty" + +#: progressindicator.cpp:33 +msgid "Speed" +msgstr "Predkosc" + +#: progressindicator.cpp:41 +msgid "Time remaining" +msgstr "Pozostały czas" + +#: progressindicator.cpp:95 progressindicator.cpp:96 replaygainscanner.cpp:216 +msgid "Finished" +msgstr "Gotowe" + +#. i18n: file ./soundkonverterui.rc line 13 +#: rc.cpp:3 +#, no-c-format +msgid "&Conversion" +msgstr "&Konwersja" + +#: replaygain.cpp:88 +msgid "Executing" +msgstr "Uruchamianie" + +#: replaygainfilelist.cpp:137 replaygainfilelist.cpp:147 +#: replaygainfilelist.cpp:150 replaygainfilelist.cpp:180 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:669 +#: replaygainfilelist.cpp:672 replaygainfilelist.cpp:704 +#: replaygainfilelist.cpp:707 replaygainfilelist.cpp:734 +#: replaygainfilelist.cpp:737 replaygainfilelist.cpp:940 +msgid "Album" +msgstr "Album" + +#: replaygainfilelist.cpp:213 +msgid "Calculate Replay Gain tags" +msgstr "Przelicz tagi Replay Gain" + +#: replaygainfilelist.cpp:214 +msgid "Remove Replay Gain tags" +msgstr "Usuń tagi Replay Gain" + +#: replaygainfilelist.cpp:217 replaygainfilelist.cpp:825 +msgid "New album" +msgstr "Nowy album" + +#: replaygainfilelist.cpp:218 +msgid "Open all albums" +msgstr "Otworz wszystkie albumy" + +#: replaygainfilelist.cpp:219 +msgid "Cloase all albums" +msgstr "Zamknij wszystkie albumy" + +#: replaygainfilelist.cpp:223 +msgid "" +"

Replay Gain Tool

With this tool you can add Replay " +"Gain tags to your audio files and remove them.
Replay Gain adds a volume " +"correction information to the files so that they can be played at an equal " +"volume level.
" +msgstr "" +"

Replay Gain Tool

Dzięki temu narzędziu możesz " +"zarówno dodawać , jak i usuwać tagi Replay Gain.\n" +"
Replay Gain dodaje informacje dotyczące głośności do plikow, dzięki " +"czemu mogą być odtwarzane na takim samym poziomie.
" + +#: replaygainfilelist.cpp:494 +msgid "You can't place files of different formats in the same 'album'." +msgstr "Nie można umieszczać plików o różnych formatach w tym samym albumie." + +#: replaygainfilelist.cpp:494 +msgid "Different file formats" +msgstr "Różne formaty pliku" + +#: replaygainfilelist.cpp:987 +msgid "Removing Replay Gain" +msgstr "Usuwanie Replay Gain" + +#: replaygainfilelist.cpp:1148 +msgid "built-in" +msgstr "wbudowany" + +#: replaygainscanner.cpp:33 replaygainscanner.cpp:216 +#: replaygainscanner.cpp:231 +msgid "Replay Gain Tool" +msgstr "Narzędzie Replay Gain" + +#: replaygainscanner.cpp:43 +msgid "Add Folder ..." +msgstr "Dodaj katalog ..." + +#: replaygainscanner.cpp:44 +msgid "Add Files ..." +msgstr "Dodaj pliki ..." + +#: replaygainscanner.cpp:52 +msgid "Force recalculation" +msgstr "Wymuś powtórne przeliczenie" + +#: replaygainscanner.cpp:53 +msgid "" +"Recalculate Replay Gain tag for files that already have a Replay Gain tag " +"set." +msgstr "" +"Przelicz ponownie znacznik Replay Gain dla plików, które już mają znacznik " +"Replay Gain." + +#: replaygainscanner.cpp:102 +msgid "Tag untagged" +msgstr "Dodaj znaczniki do plików nie posiadających jeszcze znacznika" + +#: replaygainscanner.cpp:103 +msgid "" +"Calculate Replay Gain tag for all files in the file list without Replay Gain " +"tag." +msgstr "" +"Przelicz tagi Replay Gain dla wszystkich plików z listy nie posiadających " +"jeszcze znaczników." + +#: replaygainscanner.cpp:109 +msgid "Untag tagged" +msgstr "Odznacz zaznaczone tagi" + +#: replaygainscanner.cpp:110 +msgid "Remove the Replay Gain tag from all files in the file list." +msgstr "Usuń tagi Replay Gain ze wszystkich plików na liście" + +#: replaygainscanner.cpp:151 +msgid "Choose files!" +msgstr "Wybierz pliki" + +#: soundkonverter.cpp:107 +msgid "Choose your prefered output options and click on \"Add files ...\"!" +msgstr "" +"Wybierz preferowaną opcje wyjściową, następnie kliknij na \"Dodaj pliki\"" + +#: soundkonverter.cpp:110 soundkonverter.cpp:405 soundkonverter.cpp:448 +msgid "&Start conversion" +msgstr "&Rozpocznij konwersje" + +#: soundkonverter.cpp:112 +msgid "&Replay Gain Tool ..." +msgstr "&Narzędzie Replay Gain" + +#: soundkonverter.cpp:114 +msgid "C&uesheet Editor ..." +msgstr "Edytor plików c&ue..." + +#: soundkonverter.cpp:115 +msgid "Show &Log ..." +msgstr "Pokaż p&lik dziennika" + +#: soundkonverter.cpp:118 +msgid "S&top after current file is complete" +msgstr "Zatrzymaj po udanej konwersji pliku" + +#: soundkonverter.cpp:119 +msgid "&Continue after current file is complete" +msgstr "Kontynuj po udanej konwersji pliku" + +#: soundkonverter.cpp:120 +msgid "Stop &immediately" +msgstr "Zatrzymaj natychmiast" + +#: soundkonverter.cpp:148 +msgid "A&dd Files ..." +msgstr "dodaj pliki" + +#: soundkonverter.cpp:149 +msgid "Add &Folder ..." +msgstr "Dodaj folder" + +#: soundkonverter.cpp:150 +msgid "Add CD &tracks ..." +msgstr "Dodaj ścieżki CD" + +#: soundkonverter.cpp:151 +msgid "Add &URL ..." +msgstr "Dodaj adres URL" + +#: soundkonverter.cpp:154 +msgid "L&oad file list" +msgstr "Załaduj liste plików" + +#: soundkonverter.cpp:155 +msgid "Sa&ve file list" +msgstr "Zapisz liste plików" + +#: soundkonverter.cpp:229 +msgid "Add files ..." +msgstr "Dodaj pliki" + +#: soundkonverter.cpp:230 +msgid "Add folder ..." +msgstr "Dddaj folder" + +#: soundkonverter.cpp:231 +msgid "Add CD tracks ..." +msgstr "Dodaj Scieżki CD" + +#: soundkonverter.cpp:232 +msgid "Add URL ..." +msgstr "Dodaj link" + +#: soundkonverter.cpp:240 +msgid "Start" +msgstr "Zacznij" + +#: soundkonverter.cpp:417 +msgid "&Start queue" +msgstr "&Rozpocznij Kolejkę" + +#: soundkonverter.cpp:489 +msgid "Choose files to convert" +msgstr "Wybierz pliki do konwersji" + +#: soundkonverter.cpp:617 +msgid "Open URL" +msgstr "Otwórz link" + +#: soundkonverter.cpp:617 +msgid "Enter a URL:" +msgstr "Wpisz link" diff --git a/po/pt_BR.po b/po/pt_BR.po new file mode 100644 index 0000000..952e569 --- /dev/null +++ b/po/pt_BR.po @@ -0,0 +1,1642 @@ +# Brazilian Portuguese translation for soundkonverter +# Copyright (c) 2007 Rosetta Contributors and Canonical Ltd 2007 +# This file is distributed under the same license as the soundkonverter package. +# FIRST AUTHOR , 2007. +# +msgid "" +msgstr "" +"Project-Id-Version: soundkonverter\n" +"Report-Msgid-Bugs-To: FULL NAME \n" +"POT-Creation-Date: 2008-02-25 17:22+0100\n" +"PO-Revision-Date: 2007-09-14 15:38+0000\n" +"Last-Translator: Pedro M. V. Martins \n" +"Language-Team: Brazilian Portuguese \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2008-04-06 10:52+0000\n" +"X-Generator: Launchpad (build Unknown)\n" + +#: _translatorinfo.cpp:1 +msgid "Your names" +msgstr ",Launchpad Contributions:,Pedro M. V. Martins" + +#: _translatorinfo.cpp:3 +msgid "Your emails" +msgstr ",," + +#: cddb.cpp:368 +msgid "No Title" +msgstr "Sem título" + +#: cddb.cpp:372 cdmanager.cpp:97 convert.cpp:513 convert.cpp:514 +#: convert.cpp:515 convert.cpp:517 convert.cpp:519 convert.cpp:520 +#: convert.cpp:1547 convert.cpp:1557 convert.cpp:1571 +#: replaygainfilelist.cpp:136 replaygainfilelist.cpp:137 +#: replaygainfilelist.cpp:144 replaygainfilelist.cpp:150 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:666 +#: replaygainfilelist.cpp:672 replaygainfilelist.cpp:701 +#: replaygainfilelist.cpp:707 replaygainfilelist.cpp:731 +#: replaygainfilelist.cpp:737 replaygainfilelist.cpp:945 +msgid "Unknown" +msgstr "Desconhecido" + +#: cddb.cpp:380 +msgid "Track %1" +msgstr "Faixa %1" + +#: cddb.cpp:479 +msgid "Searching local cddb entry ..." +msgstr "Buscando entrada cddb local ..." + +#: cddb.cpp:504 +msgid "Searching remote cddb entry ..." +msgstr "Buscando entrada cddb remota ..." + +#: cddb.cpp:528 +msgid "Found exact match cddb entry ..." +msgstr "Encontrada uma entrada exata no cddb ..." + +#: cddb.cpp:585 +msgid "Found close cddb entry ..." +msgstr "Encontrada uma entrada aproximada no cddb ..." + +#: cddb.cpp:608 +msgid "CDDB Matches" +msgstr "Correspondentes CDDB" + +#: cddb.cpp:608 +msgid "Several close CDDB entries found. Choose one:" +msgstr "Foram encontradas várias entradas CDDB próximas . Escolha uma:" + +#: cdmanager.cpp:46 filelist.cpp:618 +msgid "Audio CD" +msgstr "CD de áudio" + +#: cdmanager.cpp:46 +msgid "Several audio CDs found. Choose one:" +msgstr "Vários CDs de áudio encontrados. Escolha um:" + +#: cdmanager.cpp:104 +msgid "No audio CD found." +msgstr "Nenhum CD de áudio encontrado." + +#: cdopener.cpp:41 +msgid "Add CD tracks" +msgstr "Adicionar faixas do CD" + +#: cdopener.cpp:52 cdopener.cpp:178 optionseditor.cpp:123 +msgid "Artist:" +msgstr "Artista:" + +#: cdopener.cpp:57 cdopener.cpp:480 cdopener.cpp:485 cdopener.cpp:538 +#: cdopener.cpp:567 cdopener.cpp:682 cdopener.cpp:697 +msgid "Various Artists" +msgstr "Vários artistas" + +#: cdopener.cpp:66 cdopener.cpp:193 optionseditor.cpp:138 +msgid "Composer:" +msgstr "Compositor:" + +#: cdopener.cpp:71 cdopener.cpp:496 cdopener.cpp:501 cdopener.cpp:548 +#: cdopener.cpp:579 cdopener.cpp:683 cdopener.cpp:698 +msgid "Various Composer" +msgstr "Vários compositores" + +#: cdopener.cpp:83 optionseditor.cpp:158 +msgid "Album:" +msgstr "Álbum:" + +#: cdopener.cpp:91 optionseditor.cpp:178 +msgid "Disc No.:" +msgstr "Disco nº:" + +#: cdopener.cpp:96 optionseditor.cpp:194 +msgid "Year:" +msgstr "Ano:" + +#: cdopener.cpp:100 optionseditor.cpp:210 +msgid "Genre:" +msgstr "Gênero" + +#: cdopener.cpp:114 cdopener.cpp:532 filelist.cpp:578 filelist.cpp:587 +#: replaygainfilelist.cpp:136 replaygainfilelist.cpp:141 +#: replaygainfilelist.cpp:144 replaygainfilelist.cpp:178 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:663 +#: replaygainfilelist.cpp:666 replaygainfilelist.cpp:698 +#: replaygainfilelist.cpp:701 replaygainfilelist.cpp:728 +#: replaygainfilelist.cpp:731 +msgid "Track" +msgstr "Faixa" + +#: cdopener.cpp:115 cdopener.cpp:568 cdopener.cpp:571 cdopener.cpp:607 +msgid "Artist" +msgstr "Artista" + +#: cdopener.cpp:116 cdopener.cpp:580 cdopener.cpp:583 cdopener.cpp:620 +msgid "Composer" +msgstr "Compositor" + +#: cdopener.cpp:117 cdopener.cpp:594 +msgid "Title" +msgstr "Título" + +#: cdopener.cpp:118 +msgid "Time" +msgstr "Tempo" + +#: cdopener.cpp:131 +msgid "No track selected" +msgstr "Nenhuma faixa selecionada" + +#: cdopener.cpp:159 optionseditor.cpp:88 +msgid "Title:" +msgstr "Título:" + +#: cdopener.cpp:212 optionseditor.cpp:235 +msgid "Comment:" +msgstr "Comentário:" + +#: cdopener.cpp:242 +msgid "Save cuesheet ..." +msgstr "Salvar tabela cue..." + +#: cdopener.cpp:250 +msgid "Add all tracks" +msgstr "Adicionar todas as faixas" + +#: cdopener.cpp:251 +msgid "Add selected tracks" +msgstr "Adicionar as faixas selecionadas" + +#: cdopener.cpp:253 +msgid "Add full CD as one file" +msgstr "Adicionar o CD todo como um arquivo" + +#: cdopener.cpp:440 +msgid "All tracks" +msgstr "Todas as faixas" + +#: cdopener.cpp:443 +msgid "Tracks" +msgstr "Faixas" + +#: cdopener.cpp:742 +msgid "" +"A file with this name already exists.\n" +"\n" +"Do you want to overwrite the existing one?" +msgstr "" +"Já existe um arquivo com este nome.\n" +"\n" +"Você quer sobrescrever o existente?" + +#: cdopener.cpp:743 +msgid "File already exists" +msgstr "O arquivo já existe" + +#: config.cpp:103 config.cpp:104 config.cpp:1197 config.cpp:1206 +#: config.cpp:1237 configgeneralpage.cpp:37 configgeneralpage.cpp:60 +#: configgeneralpage.cpp:62 configgeneralpage.cpp:269 +#: configgeneralpage.cpp:273 configgeneralpage.cpp:297 +#: configgeneralpage.cpp:306 configgeneralpage.cpp:316 options.cpp:153 +#: optionsdetailed.cpp:363 optionssimple.cpp:49 optionssimple.cpp:221 +#: optionssimple.cpp:518 soundkonverter.cpp:308 soundkonverter.cpp:309 +msgid "Last used" +msgstr "Último usado" + +#: config.cpp:508 +msgid "Convert with soundKonverter ..." +msgstr "Converter com o soundKonverter..." + +#: config.cpp:543 +msgid "Add Replay Gain with soundKonverter ..." +msgstr "Adicionar fator de ganho com o soundKonverter..." + +#: config.cpp:1228 config.cpp:1229 configgeneralpage.cpp:57 +#: configgeneralpage.cpp:302 convert.cpp:431 filelist.cpp:1379 +#: optionsdetailed.cpp:361 optionsdetailed.cpp:427 optionsdetailed.cpp:477 +#: optionsdetailed.cpp:527 optionsdetailed.cpp:604 optionssimple.cpp:46 +#: optionssimple.cpp:140 optionssimple.cpp:180 optionssimple.cpp:218 +#: optionssimple.cpp:407 optionssimple.cpp:515 optionssimple.cpp:535 +msgid "Lossless" +msgstr "Sem perdas" + +#: config.cpp:1232 config.cpp:1233 configgeneralpage.cpp:58 +#: configgeneralpage.cpp:312 convert.cpp:434 convert.cpp:1378 +#: filelist.cpp:1382 optionsdetailed.cpp:362 optionsdetailed.cpp:480 +#: optionsdetailed.cpp:618 optionssimple.cpp:47 optionssimple.cpp:141 +#: optionssimple.cpp:185 optionssimple.cpp:219 optionssimple.cpp:421 +#: optionssimple.cpp:430 optionssimple.cpp:516 optionssimple.cpp:544 +msgid "Hybrid" +msgstr "Híbrido" + +#: config.cpp:1245 config.cpp:1252 config.cpp:1259 config.cpp:1266 +#: config.cpp:1273 convert.cpp:403 convert.cpp:995 convert.cpp:1567 +#: filelist.cpp:139 filelist.cpp:752 filelist.cpp:1270 filelist.cpp:1351 +#: optionsdetailed.cpp:246 optionsdetailed.cpp:467 optionsdetailed.cpp:582 +#: optionsdetailed.cpp:641 optionssimple.cpp:38 optionssimple.cpp:283 +#: optionssimple.cpp:312 optionssimple.cpp:340 optionssimple.cpp:367 +#: optionssimple.cpp:394 +msgid "Quality" +msgstr "Qualidade" + +#: config.cpp:1248 config.cpp:1285 convert.cpp:450 filelist.cpp:1398 +#: optionsdetailed.cpp:538 optionssimple.cpp:294 +msgid "Mono" +msgstr "Mono" + +#: config.cpp:1250 config.cpp:1287 configgeneralpage.cpp:52 +#: configgeneralpage.cpp:289 optionsdetailed.cpp:356 optionssimple.cpp:41 +#: optionssimple.cpp:135 optionssimple.cpp:155 optionssimple.cpp:213 +#: optionssimple.cpp:269 optionssimple.cpp:510 optionssimple.cpp:525 +msgid "Very low" +msgstr "Muito baixa" + +#: config.cpp:1257 config.cpp:1294 configgeneralpage.cpp:53 +#: configgeneralpage.cpp:111 configgeneralpage.cpp:290 optionsdetailed.cpp:357 +#: optionssimple.cpp:42 optionssimple.cpp:136 optionssimple.cpp:160 +#: optionssimple.cpp:214 optionssimple.cpp:298 optionssimple.cpp:511 +#: optionssimple.cpp:525 +msgid "Low" +msgstr "Baixa" + +#: config.cpp:1264 config.cpp:1301 configgeneralpage.cpp:54 +#: configgeneralpage.cpp:291 optionsdetailed.cpp:358 optionseditor.cpp:713 +#: optionssimple.cpp:43 optionssimple.cpp:137 optionssimple.cpp:165 +#: optionssimple.cpp:215 optionssimple.cpp:326 optionssimple.cpp:512 +#: optionssimple.cpp:526 +msgid "Medium" +msgstr "Média" + +#: config.cpp:1271 config.cpp:1308 configgeneralpage.cpp:55 +#: configgeneralpage.cpp:292 optionsdetailed.cpp:359 optionssimple.cpp:44 +#: optionssimple.cpp:138 optionssimple.cpp:170 optionssimple.cpp:216 +#: optionssimple.cpp:353 optionssimple.cpp:513 optionssimple.cpp:526 +msgid "High" +msgstr "Alta" + +#: config.cpp:1278 config.cpp:1315 configgeneralpage.cpp:56 +#: configgeneralpage.cpp:293 optionsdetailed.cpp:360 optionssimple.cpp:45 +#: optionssimple.cpp:139 optionssimple.cpp:175 optionssimple.cpp:217 +#: optionssimple.cpp:380 optionssimple.cpp:514 optionssimple.cpp:527 +msgid "Very high" +msgstr "Muito alta" + +#: config.cpp:1282 config.cpp:1289 config.cpp:1296 config.cpp:1303 +#: config.cpp:1310 convert.cpp:387 convert.cpp:996 convert.cpp:997 +#: convert.cpp:1568 convert.cpp:1569 filelist.cpp:1234 filelist.cpp:1245 +#: filelist.cpp:1255 filelist.cpp:1335 optionsdetailed.cpp:246 +#: optionsdetailed.cpp:470 optionsdetailed.cpp:560 optionssimple.cpp:287 +#: optionssimple.cpp:316 optionssimple.cpp:344 optionssimple.cpp:371 +#: optionssimple.cpp:398 +msgid "Bitrate" +msgstr "Taxa de bits" + +#: config.cpp:1351 optionsdetailed.cpp:365 optionssimple.cpp:51 +#: optionssimple.cpp:142 optionssimple.cpp:190 optionssimple.cpp:223 +#: optionssimple.cpp:435 optionssimple.cpp:454 optionssimple.cpp:458 +#: optionssimple.cpp:468 optionssimple.cpp:472 optionssimple.cpp:520 +#: optionssimple.cpp:552 +msgid "User defined" +msgstr "Definido pelo usuário" + +#: config.cpp:1394 config.cpp:1407 config.cpp:1411 config.cpp:1457 +#: config.cpp:1461 +msgid "files" +msgstr "arquivos" + +#: config.cpp:1419 config.cpp:1469 +msgid "all supported formats" +msgstr "todos os formatos suportados" + +#: config.cpp:1419 config.cpp:1469 +msgid "all formats" +msgstr "todos os formatos" + +#: configbackendspage.cpp:42 +msgid "Legend" +msgstr "Legenda" + +#: configbackendspage.cpp:45 +msgid "Full support" +msgstr "Suporte completo" + +#: configbackendspage.cpp:48 +msgid "Most supported" +msgstr "Suporte mediano" + +#: configbackendspage.cpp:51 +msgid "Basic support" +msgstr "Suporte básico" + +#: configbackendspage.cpp:57 +msgid "CD Ripper" +msgstr "Extrator de CD" + +#: configbackendspage.cpp:243 +msgid "Encoder" +msgstr "Codificador" + +#: configbackendspage.cpp:256 +msgid "Strength" +msgstr "Força" + +#: configbackendspage.cpp:263 +msgid "" +"Set the compression strength:\n" +"\n" +"Left = fast conversion\n" +"Right = good resultant file" +msgstr "" +"Definir a força da compressão:\n" +"\n" +"Esquerda = conversão rápida\n" +"Direita = melhor arquivo resultante" + +#: configbackendspage.cpp:272 +msgid "Decoder" +msgstr "Decodificador" + +#: configbackendspage.cpp:286 convert.cpp:593 convert.cpp:1580 +#: optionsdetailed.cpp:168 +msgid "Replay Gain" +msgstr "Fator de ganho" + +#: configbackendspage.cpp:295 +msgid "Use internal Replay Gain" +msgstr "Use o fator de ganho interno" + +#: configbackendspage.cpp:296 +msgid "Use the internal Replay Gain calculator of the encoder" +msgstr "Use o calculador de fator de ganho interno do codificador" + +#: configbackendspage.cpp:320 +msgid "KDE audio CD protocol" +msgstr "Protocolo de CD de áudio do KDE" + +#: configdialog.cpp:31 +msgid "Settings" +msgstr "Configurações" + +#: configdialog.cpp:56 +msgid "General" +msgstr "Geral" + +#: configdialog.cpp:68 +msgid "Plugins" +msgstr "Plugins" + +#: configdialog.cpp:80 +msgid "Environment" +msgstr "Ambiente" + +#: configdialog.cpp:92 +msgid "Backends" +msgstr "Programas" + +#: configenvironmentpage.cpp:32 +msgid "Directories to be scanned" +msgstr "Diretórios a serem verificados" + +#: configenvironmentpage.cpp:50 +msgid "" +"Move selected directory one position up.\n" +"This effects which backend will be chosen, if there are several versions." +msgstr "" +"Move o diretório selecionado uma posição acima.\n" +"Isto afeta qual programa será escolhido, se houver várias versões." + +#: configenvironmentpage.cpp:60 +msgid "" +"Move selected directory one position down.\n" +"This effects which backend will be chosen, if there are several versions." +msgstr "" +"Move o diretório selecionado uma posição abaixo.\n" +"Isto afeta qual programa será escolhido, se houver várias versões." + +#: configenvironmentpage.cpp:67 configpluginspage.cpp:50 +msgid "Add ..." +msgstr "Adicionar..." + +#: configenvironmentpage.cpp:87 +msgid "Programs found" +msgstr "Programas encontrados" + +#: configenvironmentpage.cpp:96 +msgid "Programs not found" +msgstr "Programas não encontrados" + +#: configgeneralpage.cpp:34 +msgid "Start in Mode" +msgstr "Iniciar no modo" + +#: configgeneralpage.cpp:38 options.cpp:36 +msgid "Simple" +msgstr "Simples" + +#: configgeneralpage.cpp:39 options.cpp:41 +msgid "Detailed" +msgstr "Detalhado" + +#: configgeneralpage.cpp:49 +msgid "Default profile" +msgstr "Perfil padrão" + +#: configgeneralpage.cpp:72 +msgid "Default format" +msgstr "Formato padrão" + +#: configgeneralpage.cpp:107 +msgid "Process priority of the backends" +msgstr "Processar prioridade dos programas" + +#: configgeneralpage.cpp:110 +msgid "Normal" +msgstr "Normal" + +#: configgeneralpage.cpp:122 +msgid "Use FAT compatible output file names" +msgstr "Usar nomes de arquivos de saída compatíveis com FAT" + +#: configgeneralpage.cpp:123 +msgid "Replaces some special characters like '?' by '_'." +msgstr "Trocar alguns caracteres especiais como '?' por '_'." + +#: configgeneralpage.cpp:133 +msgid "Conflict handling" +msgstr "" + +#: configgeneralpage.cpp:136 +msgid "Do that if the output file already exists" +msgstr "" + +#: configgeneralpage.cpp:137 +msgid "Generate new file name" +msgstr "" + +#: configgeneralpage.cpp:138 +msgid "Skip file" +msgstr "" + +#: configgeneralpage.cpp:149 +msgid "Number of files to convert at once" +msgstr "Quantidade de arquivos para converter de uma vez" + +#: configgeneralpage.cpp:160 +msgid "Status update delay (time in msec.)" +msgstr "Atualização de status (tempo em mseg.)" + +#: configgeneralpage.cpp:163 +msgid "Update the progress bar in this interval (time in milliseconds)" +msgstr "" +"Atualiza a barra de progresso neste intervalo (tempo em milisegundos)" + +#: configgeneralpage.cpp:172 +msgid "Ask for new options, when adding files from external program" +msgstr "Pedir novas opções quando adicionar arquivos de um programa externo" + +#: configgeneralpage.cpp:173 +msgid "" +"If you open a file with soundKonverter and soundKonverter is already " +"running,\n" +"you can either be asked to define new converting options\n" +"or the current settings from the soundKonverter main window are used." +msgstr "" +"Se você abrir um arquivo com o soundKonverter e ele já estiver rodando,\n" +"pode ser necessário definir novas opções de conversão, ou as\n" +"configurações atuais da janela principal do soundKonverter serão usadas." + +#: configgeneralpage.cpp:183 +msgid "Execute user script (for advanced users)" +msgstr "" + +#: configgeneralpage.cpp:184 +msgid "" +"Executes a script after every finished conversion. Have a look at " +"$KDEDIR/soundkonverter/userscript.sh" +msgstr "" + +#: configpluginspage.cpp:39 +msgid "Installed plugins" +msgstr "Plugins instalados" + +#: configpluginspage.cpp:228 +msgid "*.soundkonverter.xml|Plugins (*.soundkonverter.xml)" +msgstr "*.soundkonverter.xml|Plugins (*.soundkonverter.xml)" + +#: configpluginspage.cpp:228 +msgid "Choose a plugin to add!" +msgstr "Escolha um plugin para adicionar!" + +#: configpluginspage.cpp:253 configpluginspage.cpp:546 +msgid "" +"The plugin could not be installed. Please ensure that you have selected a " +"valid soundKonverter plugin file." +msgstr "" +"Não foi possível instalar o plugin. Favor verificar se que você selecionou " +"um arquivo de plugin do soundKonverter válido." + +#: configpluginspage.cpp:254 configpluginspage.cpp:294 +#: configpluginspage.cpp:547 configpluginspage.cpp:587 +msgid "Error while installing plugin" +msgstr "Erro ao instalar o plugin" + +#: configpluginspage.cpp:279 configpluginspage.cpp:572 +msgid "" +"The plugin was installed successfully. Please restart soundKonverter in " +"order to activate it." +msgstr "" +"O plugin foi instalado com sucesso. Favor reiniciar o soundKonverter para " +"poder ativá-lo." + +#: configpluginspage.cpp:280 configpluginspage.cpp:573 +msgid "Plugin successfully installed" +msgstr "Plugin instalado com sucesso" + +#: configpluginspage.cpp:293 configpluginspage.cpp:586 +msgid "" +"The plugin could not be installed. Please ensure that you have write " +"permission on your whole user directory." +msgstr "" +"Não foi possível instalar o plugin. Favor verificar se você tem permissão de " +"escrita em seu próprio diretório de usuário." + +#: configpluginspage.cpp:311 configpluginspage.cpp:330 +#: configpluginspage.cpp:349 +msgid "" +"The plugin was removed successfully. Please restart soundKonverter in order " +"to deactivate it." +msgstr "" +"O plugin foi removido com sucesso. Favor reiniciar o soundKonverter para " +"poder desativá-lo." + +#: configpluginspage.cpp:312 configpluginspage.cpp:331 +#: configpluginspage.cpp:350 +msgid "Plugin successfully removed" +msgstr "Plugin removido com sucesso" + +#: configpluginspage.cpp:316 configpluginspage.cpp:335 +#: configpluginspage.cpp:354 +msgid "" +"The plugin could not be removed. Please ensure that you have write " +"permission on your whole user directory." +msgstr "" +"Não foi possível remover o plugin. Favor verificar se você tem permissão de " +"escrita em seu próprio diretório de usuário." + +#: configpluginspage.cpp:317 configpluginspage.cpp:336 +#: configpluginspage.cpp:355 +msgid "Error while removing plugin" +msgstr "Erro ao remover o plugin" + +#: configpluginspage.cpp:383 configpluginspage.cpp:395 +#: configpluginspage.cpp:407 +msgid "Version" +msgstr "Versão" + +#: configpluginspage.cpp:384 configpluginspage.cpp:396 +#: configpluginspage.cpp:408 +msgid "Author" +msgstr "Autor" + +#: configpluginspage.cpp:417 configpluginspage.cpp:472 +msgid "No new plugins available!" +msgstr "Nenhum plugin novo disponível!" + +#: configpluginspage.cpp:477 +msgid "" +"The plugin list could not be downloaded. Please ensure, that your internet " +"connection works correct.\n" +"Maybe our server is busy at the moment, please try it again later." +msgstr "" +"Não foi possível baixar a lista de plugins. Favor verificar se sua conexão " +"com a internet está funcionando corretamente.\n" +"Talvez nossos servidores estejam ocupados no momento, favor tentar de novo " +"mais tarde." + +#: configpluginspage.cpp:478 +msgid "Error while loading plugin list" +msgstr "Erro ao baixar a lista de plugins" + +#: configpluginspage.cpp:626 configpluginspage.cpp:632 +msgid "" +"The plugin info could not be downloaded. Please ensure, that your internet " +"connection works correctly." +msgstr "" +"Não foi possível baixar a lista de plugins. Favor verificar se sua conexão " +"com a internet está funcionando corretamente." + +#: configpluginspage.cpp:627 configpluginspage.cpp:633 +msgid "Error while loading plugin info" +msgstr "Erro ao carregar a informação do plugin" + +#: convert.cpp:83 convert.cpp:86 convert.cpp:1538 +msgid "Getting file" +msgstr "Obtendo arquivo" + +#: convert.cpp:86 convert.cpp:130 convert.cpp:190 convert.cpp:260 +#: convert.cpp:314 convert.cpp:555 convert.cpp:593 convert.cpp:603 +#: convert.cpp:617 convert.cpp:661 convert.cpp:694 convert.cpp:1538 +#: convert.cpp:1542 convert.cpp:1547 convert.cpp:1551 convert.cpp:1557 +#: convert.cpp:1561 convert.cpp:1571 convert.cpp:1575 convert.cpp:1580 +#: convert.cpp:1583 convert.cpp:1587 filelist.cpp:136 filelist.cpp:638 +#: filelist.cpp:641 filelist.cpp:650 filelist.cpp:651 filelist.cpp:696 +#: filelist.cpp:726 filelist.cpp:729 filelist.cpp:733 filelist.cpp:860 +#: filelist.cpp:861 filelist.cpp:918 filelist.cpp:955 filelist.cpp:956 +msgid "State" +msgstr "Estado" + +#: convert.cpp:116 convert.cpp:130 convert.cpp:1542 +msgid "Getting correction file" +msgstr "Obtendo arquivo de correção" + +#: convert.cpp:122 +msgid "Aborting, file does not exist" +msgstr "Abortando, o arquivo não existe" + +#: convert.cpp:157 convert.cpp:190 convert.cpp:260 convert.cpp:1547 +#: convert.cpp:1551 +msgid "Ripping" +msgstr "Extraindo" + +#: convert.cpp:270 convert.cpp:314 convert.cpp:1557 convert.cpp:1561 +msgid "Decoding" +msgstr "Decodificando" + +#: convert.cpp:334 convert.cpp:555 convert.cpp:1571 convert.cpp:1575 +msgid "Encoding" +msgstr "Codificando" + +#: convert.cpp:453 filelist.cpp:1401 optionsdetailed.cpp:541 +msgid "Stereo" +msgstr "Stereo" + +#: convert.cpp:456 filelist.cpp:1404 optionsdetailed.cpp:544 +msgid "Joint-Stereo" +msgstr "Joint-Stereo" + +#: convert.cpp:459 filelist.cpp:1407 optionsdetailed.cpp:547 +msgid "Forced Joint-Stereo" +msgstr "Joint-Stereo forçado" + +#: convert.cpp:462 filelist.cpp:1410 optionsdetailed.cpp:550 +msgid "Dual Channels" +msgstr "Canais duplos" + +#: convert.cpp:563 replaygainfilelist.cpp:914 +msgid "Applying Replay Gain" +msgstr "Aplicando fator de ganho" + +#: convert.cpp:598 convert.cpp:603 +msgid "Writing tags" +msgstr "Escrevendo rótulos" + +#: convert.cpp:611 convert.cpp:617 convert.cpp:1583 +msgid "Moving file" +msgstr "Movendo arquivo" + +#: convert.cpp:649 convert.cpp:661 convert.cpp:1587 +msgid "Moving correction file" +msgstr "Movendo arquivo de correção" + +#: convert.cpp:688 convert.cpp:694 +msgid "Running user script" +msgstr "" + +#: convert.cpp:713 +msgid "Executing next step" +msgstr "Executando o próximo passo" + +#: convert.cpp:857 convert.cpp:874 convert.cpp:1123 convert.cpp:1147 +msgid "Got file" +msgstr "Arquivo obtido" + +#: convert.cpp:891 convert.cpp:1204 convert.cpp:1216 +msgid "Could not write to file: `%1'" +msgstr "Não foi possível gravar no arquivo:`%1'" + +#: convert.cpp:903 convert.cpp:918 convert.cpp:1228 convert.cpp:1255 +msgid "File moved" +msgstr "Arquivo movido" + +#: convert.cpp:941 filelist.cpp:70 filelist.cpp:138 filelist.cpp:750 +#: outputdirectory.cpp:39 replaygainfilelist.cpp:1141 +msgid "Output" +msgstr "Saída" + +#: convert.cpp:1292 +msgid "Adding new item to conversion list: `%1'" +msgstr "" + +#: convert.cpp:1299 +msgid "Got log ID: %1" +msgstr "ID de log obtida: %1" + +#: convert.cpp:1302 +msgid "Tags successfully read" +msgstr "Rótulos lidos com sucesso" + +#: convert.cpp:1303 +msgid "Reading tags failed" +msgstr "Falha na leitura dos rótulos" + +#: convert.cpp:1443 convert.cpp:1453 replaygainfilelist.cpp:1025 +msgid "Killing process ..." +msgstr "Matando processo..." + +#: convert.cpp:1446 replaygainfilelist.cpp:1028 +msgid "Killing process failed. Stopping after files are completed ..." +msgstr "Falha ao matar processo. Parou após os arquivos serem completados..." + +#: convert.cpp:1468 +msgid "Removing file from conversion list. Exit code %1" +msgstr "Remover arquivo da lista de conversão. Código de saída %1" + +#: convert.cpp:1475 +msgid "Executing command: \"%1\"" +msgstr "Executando comando: \"%1\"" + +#: cuesheeteditor.cpp:29 +msgid "Cuesheet Editor" +msgstr "Editor de Tabelas Cue" + +#: cuesheeteditor.cpp:76 +msgid "Generate" +msgstr "Gerar" + +#: cuesheeteditor.cpp:82 +msgid "Format" +msgstr "Formato" + +#: cuesheeteditor.cpp:88 +msgid "Shift Title/Performer" +msgstr "Mudar título/intérprete" + +#: cuesheeteditor.cpp:113 +msgid "" +"

With this small tool you can process cue files as they are used for " +"burning music mixes and for organizing them in media players like " +"amaroK.

You can generate a new file by pasting text into the input " +"area. It must be formated the following way:

Title - Artist " +"[time]
Title - Artist [3:25]
Title - Artist [2:37]
...
A tip: " +"Use kwrite and regular expressions to format it this way.

" +msgstr "" +"

Com esta pequena ferramenta você pode processar arquivos .cue da mesma " +"forma que eles são usados para queimar coleções de músicas e organizá-las em " +"tocadores de mídia como o amaroK.

Você pode gerar um novo arquivo " +"colando texto na área de entrada. Deve estar formatado da seguinte " +"forma:

Título - Artista [tempo]
Título - Artista [3:25]
Título -" +" Artista [2:37]
...
Uma dica: Use kwrite e expressões regulares para " +"formatar desta forma.

" + +#: cuesheeteditor.cpp:114 +msgid "Cuesheet Editor - Help" +msgstr "Ajuda do Editor de Tabelas Cue" + +#: dirdialog.cpp:24 +msgid "Add folder" +msgstr "Adicionar pasta" + +#: dirdialog.cpp:33 +msgid "Directory:" +msgstr "Pasta:" + +#: dirdialog.cpp:63 +msgid "Select all" +msgstr "Selecionar tudo" + +#: dirdialog.cpp:69 +msgid "Select none" +msgstr "Cancelar seleção" + +#: dirdialog.cpp:75 +msgid "Recursive" +msgstr "" + +#: dirdialog.cpp:106 dirdialog.cpp:133 +msgid "Choose a directory" +msgstr "Escolha um diretório" + +#: filelist.cpp:70 filelist.cpp:137 filelist.cpp:736 filelist.cpp:737 +msgid "Input" +msgstr "Entrada" + +#: filelist.cpp:170 +msgid "Edit options ..." +msgstr "Editar opções..." + +#: filelist.cpp:171 +msgid "Start conversion" +msgstr "Iniciar conversão" + +#: filelist.cpp:172 +msgid "Stop conversion" +msgstr "Parar conversão" + +#: filelist.cpp:184 +msgid "" +"

File List

Select your desired output options in " +"the form above and add some files.
You can add files by clicking on " +"\"Add files ...\" or dropping them here.
" +msgstr "" +"

Lista de Arquivos

Selecione suas opções de saída " +"desejadas no formulário acima e adicione alguns arquivos.
Você pode " +"adicionar arquivos clicando em \"Adicionar arquivos...\" ou arrastando-os " +"aqui.
" + +#: filelist.cpp:578 filelist.cpp:593 +msgid "Audio CD (%1)" +msgstr "CD de áudio (%1)" + +#: filelist.cpp:609 filelist.cpp:624 +msgid "Full audio CD (%1)" +msgstr "CD de áudio completo (%1)" + +#: filelist.cpp:638 filelist.cpp:650 filelist.cpp:955 +msgid "Stopped" +msgstr "Parado" + +#: filelist.cpp:641 filelist.cpp:650 filelist.cpp:955 +msgid "Failed" +msgstr "Falhou" + +#: filelist.cpp:650 filelist.cpp:726 filelist.cpp:860 filelist.cpp:955 +msgid "Will be skipped" +msgstr "" + +#: filelist.cpp:651 filelist.cpp:696 filelist.cpp:729 filelist.cpp:861 +#: filelist.cpp:918 filelist.cpp:956 progressindicator.cpp:49 +msgid "Waiting" +msgstr "Esperando" + +#: filelist.cpp:733 +msgid "Converting" +msgstr "Convertendo" + +#: logger.cpp:136 +msgid "Finished logging" +msgstr "Finalizando arquivo de log" + +#: logviewer.cpp:83 +msgid "Log Viewer" +msgstr "Visualizador de Log" + +#: logviewer.cpp:90 +msgid "Job/File" +msgstr "Trabalho/Arquivo" + +#: main.cpp:12 +msgid "" +"soundKonverter is a frontend to various sound en- and decoding programs." +msgstr "" +"O soundKonverter é uma interface gráfica para vários programas codificadores " +"e decodificadores." + +#: main.cpp:18 +msgid "Open the Replay Gain tool an add all given files" +msgstr "" +"Abrir a ferramenta de fator de ganho e adicionar todos os arquivos dados" + +#: main.cpp:20 +msgid "List all tracks on the cd drive , 'auto' will search for a cd" +msgstr "" +"Lista todas as faixas do drive de CD , 'auto' irá procurar por um CD" + +#: main.cpp:21 +msgid "Add all files using the given profile" +msgstr "Adicionar todos os arquivos usando o perfil especificado" + +#: main.cpp:22 +msgid "Add all files using the given format" +msgstr "Adicionar todos os arquivos usando o formato especificado" + +#: main.cpp:23 +msgid "Output all files to " +msgstr "Enviar todos os arquivos para " + +#: main.cpp:24 +msgid "Start soundKonverter invisible" +msgstr "Iniciar soundKonverter invisível" + +#: main.cpp:25 +msgid "" +"Close soundKonverter after all files are converted (enabled when using '--" +"invisible')" +msgstr "" +"Fechar soundKonverter depois que todos os arquivos forem convertidos " +"(habilitado ao usar '--invisible')" + +#: main.cpp:26 +msgid "Execute after each file has been converted" +msgstr "Executar depois que cada arquivo for convertido" + +#: main.cpp:27 +msgid "Audio file(s) to append to the file list" +msgstr "Arquivo(s) de áudio par adicionar à lista de arquivos" + +#: main.cpp:33 +msgid "soundKonverter" +msgstr "soundKonverter" + +#: options.cpp:127 +msgid "" +"soundKonverter either found new backends or misses some.\n" +"Click on this button in order to open the configuration dialog." +msgstr "" +"O soundKonverter encontrou novos programas ou sente a falta de algum.\n" +"Clique neste botão para abrir a janela de configuração." + +#: options.cpp:136 +msgid "Advanced Options" +msgstr "Opções avançadas" + +#: optionsdetailed.cpp:45 +msgid "Convert" +msgstr "Converter" + +#: optionsdetailed.cpp:73 +msgid "" +"vbr - variable bitrate\n" +"abr - average bitrate\n" +"cbr - constant bitrate" +msgstr "" +"vbr - taxa de bits variável\n" +"abr - taxa de bits média\n" +"cbr - taxa de bits constante" + +#: optionsdetailed.cpp:83 +msgid "Bitrate range" +msgstr "Faixa de taxa de bits" + +#: optionsdetailed.cpp:84 +msgid "" +"Use it only if, you know what you are doing, you could reduce the quality." +msgstr "" +"Use isto apenas se você souber o que está fazendo, você poderá reduzir a " +"qualidade" + +#: optionsdetailed.cpp:119 +msgid "Resample" +msgstr "Amostragem" + +#: optionsdetailed.cpp:147 +msgid "Channels" +msgstr "Canais" + +#: optionsdetailed.cpp:170 +msgid "Add a Replay Gain tag to the converted file." +msgstr "Adicionar um rótulo de fator de ganho ao arquivo convertido" + +#: optionsdetailed.cpp:171 +msgid "" +"Replay Gain is a volume correction technique. A volume difference is " +"calculated and stored in a tag. This way audio players can automatically " +"adjust the volume and the original music data is not modified (like at " +"normalization)." +msgstr "" +"Fator de ganho é uma técnica de correção de volume. Uma diferença de volume " +"é calculada e armazenada em um rótulo. Desta forma, os tocadores de áudio " +"poderão ajustar o volume automaticamente e os dados originais da música não " +"serão modificados (como em uma normalização)." + +#: optionsdetailed.cpp:192 +msgid "Save current options as a profile" +msgstr "Salvar as opções atuais como um perfil" + +#: optionsdetailed.cpp:208 +msgid "Command" +msgstr "Comando" + +#: optionsdetailed.cpp:219 +#, c-format +msgid "%p: The parameters generated by soundKonverter" +msgstr "%p: Os parâmetros gerados pelo soundKonverter" + +#: optionsdetailed.cpp:225 +#, c-format +msgid "%i: The input file ; %o: The output file" +msgstr "%i: O arquivo de entrada ; %o: O arquivo de saída" + +#: optionsdetailed.cpp:353 +msgid "New profile" +msgstr "Novo perfil" + +#: optionsdetailed.cpp:353 +msgid "Enter a name for the new profile:" +msgstr "Digite um nome para o novo perfil" + +#: optionsdetailed.cpp:368 +msgid "You cannot overwrite the built-in profiles." +msgstr "Você não pode sobrescrever perfis internos." + +#: optionsdetailed.cpp:369 optionsdetailed.cpp:379 +msgid "Profile already exists" +msgstr "Perfil já existe" + +#: optionsdetailed.cpp:378 +msgid "" +"A profile with this name already exists.\n" +"\n" +"Do you want to overwrite the existing one?" +msgstr "" +"Um perfil com este nome já existe.\n" +"Você quer sobrescrever o existente?" + +#: optionsdetailed.cpp:473 optionsdetailed.cpp:628 +msgid "Unchanged" +msgstr "Sem alterações" + +#: optionsdetailed.cpp:483 optionsdetailed.cpp:604 +msgid "Undefined" +msgstr "Indefinido" + +#: optionsdetailed.cpp:561 optionsdetailed.cpp:619 +msgid "Kilobit per second" +msgstr "Kilobits por segundo" + +#: optionsdetailed.cpp:689 +msgid "" +"This is a relative quality between 0 and 100.\n" +"The higher this number the higher is the quality.\n" +"soundKonverter will convert it into the file format's quality format.\n" +"See the \"What's this?\" for more informations.\n" +"\n" +"Current parameter: \"%1\"" +msgstr "" +"Isto é uma relação de qualidade entre 0 e 100.\n" +"Quanto maior for este número maior será a qualidade.\n" +"O soundKonverter converterá para o formato de qualidade do formato de " +"arquivo.\n" +"Veja \"O que é isto?\" para mais informações." + +#: optionseditor.cpp:28 +msgid "Options Editor" +msgstr "Editor de Opções" + +#: optionseditor.cpp:55 +msgid "Conversion" +msgstr "Conversão" + +#: optionseditor.cpp:55 +msgid "Conversion options" +msgstr "Opções de conversão" + +#: optionseditor.cpp:59 +msgid "Choose your prefered output options and click on \"Close\"!" +msgstr "Escolha suas opções de saída preferidas e clique em \"Fechar\"!" + +#: optionseditor.cpp:70 +msgid "Edit conversion options" +msgstr "Editar opções de conversão" + +#: optionseditor.cpp:79 +msgid "Tags" +msgstr "Rótulos" + +#: optionseditor.cpp:103 +msgid "Track No.:" +msgstr "Faixa número:" + +#: optionseditor.cpp:256 +msgid "Edit tags" +msgstr "Editar rótulos" + +#: optionseditor.cpp:330 +msgid "No file selected" +msgstr "Nenhum arquivo selecionado" + +#: optionseditor.cpp:358 +msgid "" +"The tags could not be read, because this file isn't a local one.\n" +"soundKonverter will try to read the tags, when it is about to convert the " +"file.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags." +msgstr "" +"Não foi possível ler os rótulos porque o arquivo não é local.\n" +"O soundKonverter tentará ler os rótulos quando estiver para converter o " +"arquivo.\n" +"Se você quer editá-los, você pode pressionar o botão abaixo, mas então\n" +"o soundKonverter não tentará ler os rótulos." + +#: optionseditor.cpp:367 +msgid "" +"Reading the tags of this file failed.\n" +"soundKonverter will try to read the tags a second time, when it is about to " +"convert the file.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags a second time." +msgstr "" +"Falha na leitura de rótulos deste arquivo.\n" +"O soundKonverter tentarar ler os rótulos pela segunda vez, quando estiver " +"para converter o arquivo.\n" +"Se você quer editá-los, você pode pressionar o botão abaixo, mas então\n" +"o soundKonverter não tentará ler os rótulos uma segunda vez." + +#: optionseditor.cpp:387 +msgid "%1 Files" +msgstr "%1 arquivos" + +#: optionseditor.cpp:402 +msgid "" +"You have selected multiple files with different conversion options.\n" +"You can change the options of all files by hitting the button below." +msgstr "" +"Você selecionou vários arquivos com opções de conversão diferentes.\n" +"Você pode alterar as opções de todos os arquivos pressionando o botão abaixo." + +#: optionseditor.cpp:408 +msgid "" +"Reading the tags of one or more files failed.\n" +"soundKonverter will try to read the tags a second time, when it is about to " +"convert the files.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags a second time." +msgstr "" +"Falha ao ler os rótulos de um ou mais arquivos.\n" +"O soundKonverter tentará ler os rótulos pela segunda vez, quando estiver " +"para converter os arquivos.\n" +"Se você quer editá-los, você pode pressionar o botão abaixo, mas então\n" +"o soundKonverter não tentará ler os rótulos uma segunda vez." + +#: optionsrequester.cpp:18 +msgid "Choose output options" +msgstr "Escolha as opções de saída" + +#: optionsrequester.cpp:28 +msgid "Click on \"Ok\" to add the files to the list in the main window!" +msgstr "" +"Clique em \"Ok\" para adicionar os arquivos à lista da janela principal!" + +#: optionsrequester.cpp:43 +msgid "" +"Warning: If you select \"wav\" as output format, your wav files will not be " +"added to the list." +msgstr "" +"Cuidado: se você selecionar o formato de saída \"wav\", seus arquivos wav " +"não serão adicionados à lista." + +#: optionsrequester.cpp:59 +msgid "Ok" +msgstr "Ok" + +#: optionssimple.cpp:64 +msgid "Remove the selected profile" +msgstr "Remover o perfil selecionado" + +#: optionssimple.cpp:70 optionssimple.cpp:90 +msgid "Info" +msgstr "Informação" + +#: optionssimple.cpp:71 +msgid "Information about the selected profile" +msgstr "Informação sobre o perfil selecionado" + +#: optionssimple.cpp:78 +msgid "Output format" +msgstr "Formato de saída" + +#: optionssimple.cpp:91 +msgid "Information about the selected file format" +msgstr "Informação sobre o formado de arquivo selecionado" + +#: optionssimple.cpp:157 +msgid "" +"This produces sound files of a very low quality.\n" +"That can be useful, if you have a mobile device, where your memory cell is " +"limited. It is not recommended to save your music in this quality without a " +"copy with higher quality.\n" +"It can also be used to save audio files with voices." +msgstr "" +"Isto produz arquivos de som com uma qualidade muito baixa.\n" +"Isso pode ser útil, se você tiver um dispositivo móvel, onde a quantidade de " +"memória é limitada. Não é recomendável salvar suas músicas nesta qualidade " +"sem ter uma cópia com uma qualidade maior.\n" +"Também pode ser usado para gravar arquivos de áudio com vozes." + +#: optionssimple.cpp:158 optionssimple.cpp:163 optionssimple.cpp:168 +#: optionssimple.cpp:173 optionssimple.cpp:178 optionssimple.cpp:183 +#: optionssimple.cpp:188 optionssimple.cpp:193 +msgid "Profile" +msgstr "Perfil" + +#: optionssimple.cpp:162 +msgid "" +"This produces sound files of a low quality.\n" +"That can be useful if you habe a mobile device where your memory cell is " +"limited. It is not recommended to save your music in this quality without a " +"copy with higher quality." +msgstr "" +"Isto produz arquivos de som com uma qualidade baixa.\n" +"Isso pode ser útil, se você tiver um dispositivo móvel, onde a quantidade de " +"memória é limitada. Não é recomendável salvar suas músicas nesta qualidade " +"sem ter uma cópia com uma qualidade maior." + +#: optionssimple.cpp:167 +msgid "" +"This produces sound files of a medium quality.\n" +"If your disc space is limited, you can use this to save your music." +msgstr "" +"Isto produz arquivos de som com uma qualidade média.\n" +"Se seu espaço em disco é limitado, você pode usá-lo para gravar suas músicas." + +#: optionssimple.cpp:172 +msgid "" +"This produces sound files of a high quality.\n" +"If you have enough disc space available, you can use this to save your music." +msgstr "" +"Isto produz arquivos de som com uma qualidade alta.\n" +"Se você tiver espaço em disco disponível, você pode usá-lo para salvar suas " +"músicas." + +#: optionssimple.cpp:177 +msgid "" +"This produces sound files of a very high quality.\n" +"You should only use this, if you are a quality freak and have enough disc " +"space available." +msgstr "" +"Isto produz arquivos de som com uma qualidade muito alta.\n" +"Você só deve usá-lo se for um obcecado por qualidade e tiver espaço em disco " +"suficiente." + +#: optionssimple.cpp:182 +msgid "" +"This produces files, that have exact the same quality as the input files.\n" +"This files are very big and definitely only for quality freaks." +msgstr "" +"Isto produz arquivos de som com a mesma qualidade dos arquivos de entrada.\n" +"Estes arquivos são muito grandes e definitivamente apenas para obcecados por " +"qualidade." + +#: optionssimple.cpp:187 +msgid "" +"This produces two files. One lossy compressed playable file and one " +"correction file.\n" +"Both files together result in a file that is equivalent to the input file." +msgstr "" +"Isto produz dois arquivos. Um arquivo tocável comprimido com perdas e um " +"arquivo de correção.\n" +"Ambos arquivos juntos resultam em um arquivo que é equivalente ao arquivo de " +"estrada." + +#: optionssimple.cpp:192 +msgid "You can define your own profile in the \"detailed\" tab." +msgstr "Você pode definir seu próprio perfil na aba \"detalhado\"." + +#: optionssimple.cpp:205 +msgid "Do you really want to remove the profile: %1" +msgstr "Você realmente quer remover o perfil: %1" + +#: optionssimple.cpp:206 +msgid "Remove profile?" +msgstr "Remover perfil?" + +#: optionssimple.cpp:234 +msgid "" +"

Wave is a file format, that doesn't compress it's audio data.

\n" +"

So the quality is very high, but the file size is enormous. It is widely " +"spread and should work with every audio player.

\n" +"
http://en.wikipedia.org/wiki/Wav" +msgstr "" +"

Wave é um formato de arquivo que não comprime os dados de áudio.

\n" +"

Desta forma, a qualidade é muito alta, mas o tamanho do arquivo é enorme. " +"É amplamente utilizado e deve funcionar com qualquer tocador de áudio.

\n" +"
http://pt.wikipedia.org/wiki/Wav" + +#: optionssimple.cpp:235 optionssimple.cpp:242 +msgid "File format" +msgstr "Formato de arquivo" + +#: outputdirectory.cpp:44 +msgid "By meta data" +msgstr "Por meta dados" + +#: outputdirectory.cpp:45 +msgid "Source directory" +msgstr "Diretório de origem" + +#: outputdirectory.cpp:46 +msgid "Specify output directory" +msgstr "Especificar o diretório de saída" + +#: outputdirectory.cpp:47 +msgid "Copy directory structure" +msgstr "Copiar a estrutura do diretório" + +#: outputdirectory.cpp:61 +msgid "Clear the directory input field" +msgstr "Limpar o campo de entrada do diretório" + +#: outputdirectory.cpp:81 outputdirectory.cpp:345 +msgid "Choose an output directory" +msgstr "Escolher um diretório de saída" + +#: outputdirectory.cpp:87 +msgid "Open Konqueror with the output directory" +msgstr "Abrir o Konqueror com o diretório de saída" + +#: outputdirectory.cpp:184 +msgid "Unknown Artist" +msgstr "Artista desconhecido" + +#: outputdirectory.cpp:188 +msgid "Unknown Album" +msgstr "Álbum desconhecido" + +#: outputdirectory.cpp:192 +msgid "No Comment" +msgstr "Nenhum comentário" + +#: outputdirectory.cpp:199 +msgid "Unknown Genre" +msgstr "Gênero desconhecido" + +#: outputdirectory.cpp:206 +msgid "Unknown Composer" +msgstr "Compositor desconhecido" + +#: outputdirectory.cpp:210 +msgid "Unknown Title" +msgstr "Título Desconhecido" + +#: outputdirectory.cpp:264 +msgid "new" +msgstr "novo" + +#: outputdirectory.cpp:406 +msgid "Name all converted files according to the specified pattern" +msgstr "" +"Nomeie todos os arquivos convertidos de acordo com o padrão especificado" + +#: outputdirectory.cpp:408 +msgid "" +"

The following strings are wildcards, that will be replaced by the " +"information in the meta data:

%a - Artist
%b - Album
%c - " +"Comment
%d - Disc number
%g - Genre
%n - Track number
%p - " +"Composer
%t - Title
%y - Year
%f - Original file name

" +msgstr "" +"

Os códigos a seguir são marcadores, que serão substituídos pelas " +"informações nos meta dados:

%a - Artista
%b - Álbum
%c - " +"Comentário
%d - Número do disco
%g - Gênero
%n - Número da " +"faixa
%p - Compositor
%t - Título
%y - Ano
%f - Nome do arquivo " +"original

" + +#: outputdirectory.cpp:420 +msgid "" +"Output all converted files into the same directory as the original files" +msgstr "" +"Envia todos os arquivos convertidos para o mesmo diretório dos originais" + +#: outputdirectory.cpp:434 +msgid "Output all converted files into the specified output directory" +msgstr "" +"Envia todos os arquivos convertidos para o diretório de saída especificado" + +#: outputdirectory.cpp:448 +msgid "Copy the whole directory structure for all converted files" +msgstr "" +"Copia a estrutura de diretório inteira para todos os arquivos convertidos" + +#: paranoia.cpp:214 +msgid "MB" +msgstr "MB" + +#: paranoia.cpp:215 +msgid "KB" +msgstr "KB" + +#: paranoia.cpp:216 +msgid "Bytes" +msgstr "Bytes" + +#: progressindicator.cpp:33 +msgid "Speed" +msgstr "Velocidade" + +#: progressindicator.cpp:41 +msgid "Time remaining" +msgstr "Tempo restante" + +#: progressindicator.cpp:95 progressindicator.cpp:96 replaygainscanner.cpp:216 +msgid "Finished" +msgstr "Completado" + +#. i18n: file ./soundkonverterui.rc line 13 +#: rc.cpp:3 +#, no-c-format +msgid "&Conversion" +msgstr "&Conversão" + +#: replaygain.cpp:88 +msgid "Executing" +msgstr "Executando" + +#: replaygainfilelist.cpp:137 replaygainfilelist.cpp:147 +#: replaygainfilelist.cpp:150 replaygainfilelist.cpp:180 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:669 +#: replaygainfilelist.cpp:672 replaygainfilelist.cpp:704 +#: replaygainfilelist.cpp:707 replaygainfilelist.cpp:734 +#: replaygainfilelist.cpp:737 replaygainfilelist.cpp:940 +msgid "Album" +msgstr "Álbum" + +#: replaygainfilelist.cpp:213 +msgid "Calculate Replay Gain tags" +msgstr "Calcular rótulos de fator de ganho" + +#: replaygainfilelist.cpp:214 +msgid "Remove Replay Gain tags" +msgstr "Remover rótulos de fator de ganho" + +#: replaygainfilelist.cpp:217 replaygainfilelist.cpp:825 +msgid "New album" +msgstr "Novo álbum" + +#: replaygainfilelist.cpp:218 +msgid "Open all albums" +msgstr "Abrir todos os álbuns" + +#: replaygainfilelist.cpp:219 +msgid "Cloase all albums" +msgstr "Fechar todos os álbuns" + +#: replaygainfilelist.cpp:223 +msgid "" +"

Replay Gain Tool

With this tool you can add Replay " +"Gain tags to your audio files and remove them.
Replay Gain adds a volume " +"correction information to the files so that they can be played at an equal " +"volume level.
" +msgstr "" +"

Ferramenta de Fator de Ganho

Com esta ferramenta, " +"você pode adicionar e remover rótulos de fator de ganho a seus arquivos de " +"áudio.
Fator de ganho adiciona uma informação de correção de volume aos " +"arquivos para que eles sejam tocados no mesmo nível de volume.
" + +#: replaygainfilelist.cpp:494 +msgid "You can't place files of different formats in the same 'album'." +msgstr "" +"Você não pode colocar arquivos de formatos diferentes no mesmo 'álbum'." + +#: replaygainfilelist.cpp:494 +msgid "Different file formats" +msgstr "Formatos de arquivo diferentes" + +#: replaygainfilelist.cpp:987 +msgid "Removing Replay Gain" +msgstr "Remover fator de ganho" + +#: replaygainfilelist.cpp:1148 +msgid "built-in" +msgstr "embutido" + +#: replaygainscanner.cpp:33 replaygainscanner.cpp:216 +#: replaygainscanner.cpp:231 +msgid "Replay Gain Tool" +msgstr "Ferramenta de Fator de Ganho" + +#: replaygainscanner.cpp:43 +msgid "Add Folder ..." +msgstr "Adicionar diretório..." + +#: replaygainscanner.cpp:44 +msgid "Add Files ..." +msgstr "Adicionar arquivos..." + +#: replaygainscanner.cpp:52 +msgid "Force recalculation" +msgstr "Forçar novos cálculos" + +#: replaygainscanner.cpp:53 +msgid "" +"Recalculate Replay Gain tag for files that already have a Replay Gain tag " +"set." +msgstr "" +"Recalcula rótulos de fator de ganho para arquivos que já tenham rótulos " +"definidos." + +#: replaygainscanner.cpp:102 +msgid "Tag untagged" +msgstr "Rótulo apagado" + +#: replaygainscanner.cpp:103 +msgid "" +"Calculate Replay Gain tag for all files in the file list without Replay Gain " +"tag." +msgstr "" +"Calcula os rótulos de fator de ganho para todos os arquivos da lista que não " +"tenham rótulo de fator de ganho" + +#: replaygainscanner.cpp:109 +msgid "Untag tagged" +msgstr "Retirar os rótulos" + +#: replaygainscanner.cpp:110 +msgid "Remove the Replay Gain tag from all files in the file list." +msgstr "" +"Remove o rótulo de fator de galho de todos os arquivos na lista de arquivos." + +#: replaygainscanner.cpp:151 +msgid "Choose files!" +msgstr "Escolha os arquivos!" + +#: soundkonverter.cpp:107 +msgid "Choose your prefered output options and click on \"Add files ...\"!" +msgstr "" +"Escolha suas opções de saída preferidas e clique em \"Adicionar " +"arquivos...\"!" + +#: soundkonverter.cpp:110 soundkonverter.cpp:405 soundkonverter.cpp:448 +msgid "&Start conversion" +msgstr "&Iniciar conversão" + +#: soundkonverter.cpp:112 +msgid "&Replay Gain Tool ..." +msgstr "&Ferramenta de Fator de Ganho" + +#: soundkonverter.cpp:114 +msgid "C&uesheet Editor ..." +msgstr "&Editor de Tabela Cue" + +#: soundkonverter.cpp:115 +msgid "Show &Log ..." +msgstr "&Mostrar log..." + +#: soundkonverter.cpp:118 +msgid "S&top after current file is complete" +msgstr "&Parar depois que o arquivo atual for completado" + +#: soundkonverter.cpp:119 +msgid "&Continue after current file is complete" +msgstr "&Continuar depois que o arquivo atual for completado" + +#: soundkonverter.cpp:120 +msgid "Stop &immediately" +msgstr "Parar &imediatamente" + +#: soundkonverter.cpp:148 +msgid "A&dd Files ..." +msgstr "&Adicionar arquivos..." + +#: soundkonverter.cpp:149 +msgid "Add &Folder ..." +msgstr "A&dicionar diretórios..." + +#: soundkonverter.cpp:150 +msgid "Add CD &tracks ..." +msgstr "Adicionar &faixas de CD..." + +#: soundkonverter.cpp:151 +msgid "Add &URL ..." +msgstr "Adicionar &URL..." + +#: soundkonverter.cpp:154 +msgid "L&oad file list" +msgstr "&Carregar lista de arquivos" + +#: soundkonverter.cpp:155 +msgid "Sa&ve file list" +msgstr "&Salvar lista de arquivos" + +#: soundkonverter.cpp:229 +msgid "Add files ..." +msgstr "Adicionar arquivos..." + +#: soundkonverter.cpp:230 +msgid "Add folder ..." +msgstr "Adicionar diretório..." + +#: soundkonverter.cpp:231 +msgid "Add CD tracks ..." +msgstr "Adicionar faixas de CD..." + +#: soundkonverter.cpp:232 +msgid "Add URL ..." +msgstr "Adicionar URL..." + +#: soundkonverter.cpp:240 +msgid "Start" +msgstr "Iníciar" + +#: soundkonverter.cpp:417 +msgid "&Start queue" +msgstr "&Iniciar fila" + +#: soundkonverter.cpp:489 +msgid "Choose files to convert" +msgstr "Escolha os arquivos para converter" + +#: soundkonverter.cpp:617 +msgid "Open URL" +msgstr "Abrir URL" + +#: soundkonverter.cpp:617 +msgid "Enter a URL:" +msgstr "Digite uma URL:" diff --git a/po/pt_PT.po b/po/pt_PT.po new file mode 100644 index 0000000..9719959 --- /dev/null +++ b/po/pt_PT.po @@ -0,0 +1,1688 @@ +# translation of soundkonverter_pt_PT.po to +# This file is put in the public domain. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: soundkonverter_pt_PT\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-02-25 17:22+0100\n" +"PO-Revision-Date: 2007-09-10 17:54+0000\n" +"Last-Translator: Sérgio Lopes \n" +"Language-Team: Traduções 1 \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2008-04-06 10:52+0000\n" +"X-Generator: Launchpad (build Unknown)\n" + +#~ msgid "Available plugins" +#~ msgstr "Plugin disponíveis" + +#~ msgid "Refresh" +#~ msgstr "Actualizar" + +#~ msgid "Download the latest list of available plugins." +#~ msgstr "Descarrege a lista de plugins mais recente" + +#~ msgid "Install" +#~ msgstr "Instalar" + +#~ msgid "" +#~ "Download the selected plugin and install it into the soundKonverter " +#~ "directory." +#~ msgstr "Descarregar o plugin, e instalá-lo na pasta do soundKonverter." + +#~ msgid "Check for new plugins on every startup" +#~ msgstr "Verificar a existência de novos plugins no arranque" + +#~ msgid "Adding new item to conversion list: `%1')" +#~ msgstr "Adicionando um novo item à lista de conversão: `%1')" + +#~ msgid "Choose a directory!" +#~ msgstr "Escolha uma directoria!" + +#~ msgid "" +#~ "There are new plugin updates available.\n" +#~ "Click on this button in order to open the configuration dialog." +#~ msgstr "" +#~ "Há novas actualizações de plugins disponíveis.\n" +#~ "Carregue neste butão para abrir a janela de configuração." + +#: _translatorinfo.cpp:1 +msgid "Your names" +msgstr "" +"Equipa de Traduções 1 do www.portugal-a-programar.org,,Launchpad " +"Contributions:,Sérgio Lopes" + +#: _translatorinfo.cpp:3 +msgid "Your emails" +msgstr "traducoes-1@portugal-a-programar.org,,,knitter.is@gmail.com" + +#: cddb.cpp:368 +msgid "No Title" +msgstr "Sem título" + +#: cddb.cpp:372 cdmanager.cpp:97 convert.cpp:513 convert.cpp:514 +#: convert.cpp:515 convert.cpp:517 convert.cpp:519 convert.cpp:520 +#: convert.cpp:1547 convert.cpp:1557 convert.cpp:1571 +#: replaygainfilelist.cpp:136 replaygainfilelist.cpp:137 +#: replaygainfilelist.cpp:144 replaygainfilelist.cpp:150 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:666 +#: replaygainfilelist.cpp:672 replaygainfilelist.cpp:701 +#: replaygainfilelist.cpp:707 replaygainfilelist.cpp:731 +#: replaygainfilelist.cpp:737 replaygainfilelist.cpp:945 +msgid "Unknown" +msgstr "Desconhecido" + +#: cddb.cpp:380 +msgid "Track %1" +msgstr "Faixa %1" + +#: cddb.cpp:479 +msgid "Searching local cddb entry ..." +msgstr "A procurar entrada na cddb local ..." + +#: cddb.cpp:504 +msgid "Searching remote cddb entry ..." +msgstr "A procurar entrada na cddb remota ..." + +#: cddb.cpp:528 +msgid "Found exact match cddb entry ..." +msgstr "Correspondência de cddb exacta encontrada..." + +#: cddb.cpp:585 +msgid "Found close cddb entry ..." +msgstr "Correspondência de cddb semelhante encontrada..." + +#: cddb.cpp:608 +msgid "CDDB Matches" +msgstr "CDDB Correspondentes" + +#: cddb.cpp:608 +msgid "Several close CDDB entries found. Choose one:" +msgstr "Várias correspondências de cddb encontradas. Escolha uma..." + +#: cdmanager.cpp:46 filelist.cpp:618 +msgid "Audio CD" +msgstr "CD de Áudio" + +#: cdmanager.cpp:46 +msgid "Several audio CDs found. Choose one:" +msgstr "Encontrados vários CDs de Áudio. Escolha um:" + +#: cdmanager.cpp:104 +msgid "No audio CD found." +msgstr "Nenhum CD de audio encontrado." + +#: cdopener.cpp:41 +msgid "Add CD tracks" +msgstr "Adicionar faixas do CD" + +#: cdopener.cpp:52 cdopener.cpp:178 optionseditor.cpp:123 +msgid "Artist:" +msgstr "Artista:" + +#: cdopener.cpp:57 cdopener.cpp:480 cdopener.cpp:485 cdopener.cpp:538 +#: cdopener.cpp:567 cdopener.cpp:682 cdopener.cpp:697 +msgid "Various Artists" +msgstr "Vários Artistas" + +#: cdopener.cpp:66 cdopener.cpp:193 optionseditor.cpp:138 +msgid "Composer:" +msgstr "Compositor:" + +#: cdopener.cpp:71 cdopener.cpp:496 cdopener.cpp:501 cdopener.cpp:548 +#: cdopener.cpp:579 cdopener.cpp:683 cdopener.cpp:698 +msgid "Various Composer" +msgstr "Vários Compositores" + +#: cdopener.cpp:83 optionseditor.cpp:158 +msgid "Album:" +msgstr "Álbum" + +#: cdopener.cpp:91 optionseditor.cpp:178 +msgid "Disc No.:" +msgstr "Disco Nr.:" + +#: cdopener.cpp:96 optionseditor.cpp:194 +msgid "Year:" +msgstr "Ano:" + +#: cdopener.cpp:100 optionseditor.cpp:210 +msgid "Genre:" +msgstr "Género:" + +#: cdopener.cpp:114 cdopener.cpp:532 filelist.cpp:578 filelist.cpp:587 +#: replaygainfilelist.cpp:136 replaygainfilelist.cpp:141 +#: replaygainfilelist.cpp:144 replaygainfilelist.cpp:178 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:663 +#: replaygainfilelist.cpp:666 replaygainfilelist.cpp:698 +#: replaygainfilelist.cpp:701 replaygainfilelist.cpp:728 +#: replaygainfilelist.cpp:731 +msgid "Track" +msgstr "Faixa" + +#: cdopener.cpp:115 cdopener.cpp:568 cdopener.cpp:571 cdopener.cpp:607 +msgid "Artist" +msgstr "Artista" + +#: cdopener.cpp:116 cdopener.cpp:580 cdopener.cpp:583 cdopener.cpp:620 +msgid "Composer" +msgstr "Compositor" + +#: cdopener.cpp:117 cdopener.cpp:594 +msgid "Title" +msgstr "Título" + +#: cdopener.cpp:118 +msgid "Time" +msgstr "Tempo" + +#: cdopener.cpp:131 +msgid "No track selected" +msgstr "Nenhuma faixa seleccionada" + +#: cdopener.cpp:159 optionseditor.cpp:88 +msgid "Title:" +msgstr "Título:" + +#: cdopener.cpp:212 optionseditor.cpp:235 +msgid "Comment:" +msgstr "Comentário:" + +#: cdopener.cpp:242 +msgid "Save cuesheet ..." +msgstr "Salvar Lista de Músicas ..." + +#: cdopener.cpp:250 +msgid "Add all tracks" +msgstr "Adicionar todas as faixas" + +#: cdopener.cpp:251 +msgid "Add selected tracks" +msgstr "Adicionar faixas selecionadas" + +#: cdopener.cpp:253 +msgid "Add full CD as one file" +msgstr "Adicionar o CD completo como um ficheiro" + +#: cdopener.cpp:440 +msgid "All tracks" +msgstr "Todas as faixas" + +#: cdopener.cpp:443 +msgid "Tracks" +msgstr "Faixas" + +#: cdopener.cpp:742 +msgid "" +"A file with this name already exists.\n" +"\n" +"Do you want to overwrite the existing one?" +msgstr "" +"Já existe um ficheiro com o mesmo nome.\n" +"\n" +"Deseja substituir o ficheiro já existente?" + +#: cdopener.cpp:743 +msgid "File already exists" +msgstr "O ficheiro já existente" + +#: config.cpp:103 config.cpp:104 config.cpp:1197 config.cpp:1206 +#: config.cpp:1237 configgeneralpage.cpp:37 configgeneralpage.cpp:60 +#: configgeneralpage.cpp:62 configgeneralpage.cpp:269 +#: configgeneralpage.cpp:273 configgeneralpage.cpp:297 +#: configgeneralpage.cpp:306 configgeneralpage.cpp:316 options.cpp:153 +#: optionsdetailed.cpp:363 optionssimple.cpp:49 optionssimple.cpp:221 +#: optionssimple.cpp:518 soundkonverter.cpp:308 soundkonverter.cpp:309 +msgid "Last used" +msgstr "Usado pela última vez" + +#: config.cpp:508 +msgid "Convert with soundKonverter ..." +msgstr "Converter com o soundKonverter" + +#: config.cpp:543 +msgid "Add Replay Gain with soundKonverter ..." +msgstr "Normalizar com o soundKonverter" + +#: config.cpp:1228 config.cpp:1229 configgeneralpage.cpp:57 +#: configgeneralpage.cpp:302 convert.cpp:431 filelist.cpp:1379 +#: optionsdetailed.cpp:361 optionsdetailed.cpp:427 optionsdetailed.cpp:477 +#: optionsdetailed.cpp:527 optionsdetailed.cpp:604 optionssimple.cpp:46 +#: optionssimple.cpp:140 optionssimple.cpp:180 optionssimple.cpp:218 +#: optionssimple.cpp:407 optionssimple.cpp:515 optionssimple.cpp:535 +msgid "Lossless" +msgstr "Formato Lossless" + +#: config.cpp:1232 config.cpp:1233 configgeneralpage.cpp:58 +#: configgeneralpage.cpp:312 convert.cpp:434 convert.cpp:1378 +#: filelist.cpp:1382 optionsdetailed.cpp:362 optionsdetailed.cpp:480 +#: optionsdetailed.cpp:618 optionssimple.cpp:47 optionssimple.cpp:141 +#: optionssimple.cpp:185 optionssimple.cpp:219 optionssimple.cpp:421 +#: optionssimple.cpp:430 optionssimple.cpp:516 optionssimple.cpp:544 +msgid "Hybrid" +msgstr "Formato Híbrido" + +#: config.cpp:1245 config.cpp:1252 config.cpp:1259 config.cpp:1266 +#: config.cpp:1273 convert.cpp:403 convert.cpp:995 convert.cpp:1567 +#: filelist.cpp:139 filelist.cpp:752 filelist.cpp:1270 filelist.cpp:1351 +#: optionsdetailed.cpp:246 optionsdetailed.cpp:467 optionsdetailed.cpp:582 +#: optionsdetailed.cpp:641 optionssimple.cpp:38 optionssimple.cpp:283 +#: optionssimple.cpp:312 optionssimple.cpp:340 optionssimple.cpp:367 +#: optionssimple.cpp:394 +msgid "Quality" +msgstr "Qualidade" + +#: config.cpp:1248 config.cpp:1285 convert.cpp:450 filelist.cpp:1398 +#: optionsdetailed.cpp:538 optionssimple.cpp:294 +msgid "Mono" +msgstr "Mono" + +#: config.cpp:1250 config.cpp:1287 configgeneralpage.cpp:52 +#: configgeneralpage.cpp:289 optionsdetailed.cpp:356 optionssimple.cpp:41 +#: optionssimple.cpp:135 optionssimple.cpp:155 optionssimple.cpp:213 +#: optionssimple.cpp:269 optionssimple.cpp:510 optionssimple.cpp:525 +msgid "Very low" +msgstr "Muito baixa" + +#: config.cpp:1257 config.cpp:1294 configgeneralpage.cpp:53 +#: configgeneralpage.cpp:111 configgeneralpage.cpp:290 optionsdetailed.cpp:357 +#: optionssimple.cpp:42 optionssimple.cpp:136 optionssimple.cpp:160 +#: optionssimple.cpp:214 optionssimple.cpp:298 optionssimple.cpp:511 +#: optionssimple.cpp:525 +msgid "Low" +msgstr "Baixa" + +#: config.cpp:1264 config.cpp:1301 configgeneralpage.cpp:54 +#: configgeneralpage.cpp:291 optionsdetailed.cpp:358 optionseditor.cpp:713 +#: optionssimple.cpp:43 optionssimple.cpp:137 optionssimple.cpp:165 +#: optionssimple.cpp:215 optionssimple.cpp:326 optionssimple.cpp:512 +#: optionssimple.cpp:526 +msgid "Medium" +msgstr "Média" + +#: config.cpp:1271 config.cpp:1308 configgeneralpage.cpp:55 +#: configgeneralpage.cpp:292 optionsdetailed.cpp:359 optionssimple.cpp:44 +#: optionssimple.cpp:138 optionssimple.cpp:170 optionssimple.cpp:216 +#: optionssimple.cpp:353 optionssimple.cpp:513 optionssimple.cpp:526 +msgid "High" +msgstr "Alta" + +#: config.cpp:1278 config.cpp:1315 configgeneralpage.cpp:56 +#: configgeneralpage.cpp:293 optionsdetailed.cpp:360 optionssimple.cpp:45 +#: optionssimple.cpp:139 optionssimple.cpp:175 optionssimple.cpp:217 +#: optionssimple.cpp:380 optionssimple.cpp:514 optionssimple.cpp:527 +msgid "Very high" +msgstr "Muito alta" + +#: config.cpp:1282 config.cpp:1289 config.cpp:1296 config.cpp:1303 +#: config.cpp:1310 convert.cpp:387 convert.cpp:996 convert.cpp:997 +#: convert.cpp:1568 convert.cpp:1569 filelist.cpp:1234 filelist.cpp:1245 +#: filelist.cpp:1255 filelist.cpp:1335 optionsdetailed.cpp:246 +#: optionsdetailed.cpp:470 optionsdetailed.cpp:560 optionssimple.cpp:287 +#: optionssimple.cpp:316 optionssimple.cpp:344 optionssimple.cpp:371 +#: optionssimple.cpp:398 +msgid "Bitrate" +msgstr "Taxa de Bits" + +#: config.cpp:1351 optionsdetailed.cpp:365 optionssimple.cpp:51 +#: optionssimple.cpp:142 optionssimple.cpp:190 optionssimple.cpp:223 +#: optionssimple.cpp:435 optionssimple.cpp:454 optionssimple.cpp:458 +#: optionssimple.cpp:468 optionssimple.cpp:472 optionssimple.cpp:520 +#: optionssimple.cpp:552 +msgid "User defined" +msgstr "Definido pelo utilizador" + +#: config.cpp:1394 config.cpp:1407 config.cpp:1411 config.cpp:1457 +#: config.cpp:1461 +msgid "files" +msgstr "ficheiros" + +#: config.cpp:1419 config.cpp:1469 +msgid "all supported formats" +msgstr "todos os formatos suportados" + +#: config.cpp:1419 config.cpp:1469 +msgid "all formats" +msgstr "todos os formatos" + +#: configbackendspage.cpp:42 +msgid "Legend" +msgstr "Legenda" + +#: configbackendspage.cpp:45 +msgid "Full support" +msgstr "Suporte completo" + +#: configbackendspage.cpp:48 +msgid "Most supported" +msgstr "Bem suportado" + +#: configbackendspage.cpp:51 +msgid "Basic support" +msgstr "Suporte básico" + +#: configbackendspage.cpp:57 +msgid "CD Ripper" +msgstr "Ripador de CDs" + +#: configbackendspage.cpp:243 +msgid "Encoder" +msgstr "Codificador" + +#: configbackendspage.cpp:256 +msgid "Strength" +msgstr "Força" + +#: configbackendspage.cpp:263 +msgid "" +"Set the compression strength:\n" +"\n" +"Left = fast conversion\n" +"Right = good resultant file" +msgstr "" +"Defina o nível de compressão:\n" +"\n" +"Esquerda = Maior Rapidez\n" +"Direita = Maior Qualidade" + +#: configbackendspage.cpp:272 +msgid "Decoder" +msgstr "Descodificador" + +#: configbackendspage.cpp:286 convert.cpp:593 convert.cpp:1580 +#: optionsdetailed.cpp:168 +msgid "Replay Gain" +msgstr "Normalizar" + +#: configbackendspage.cpp:295 +msgid "Use internal Replay Gain" +msgstr "Utilizar Normalizador Interno" + +#: configbackendspage.cpp:296 +msgid "Use the internal Replay Gain calculator of the encoder" +msgstr "Utilizar a Normalização interna calculada pelo codificador" + +#: configbackendspage.cpp:320 +msgid "KDE audio CD protocol" +msgstr "Protocolo de CD áudio do KDE" + +#: configdialog.cpp:31 +msgid "Settings" +msgstr "Definições" + +#: configdialog.cpp:56 +msgid "General" +msgstr "Geral" + +#: configdialog.cpp:68 +msgid "Plugins" +msgstr "Plugins" + +#: configdialog.cpp:80 +msgid "Environment" +msgstr "Ambiente" + +#: configdialog.cpp:92 +msgid "Backends" +msgstr "Backend" + +#: configenvironmentpage.cpp:32 +msgid "Directories to be scanned" +msgstr "Directorias a pesquisar" + +#: configenvironmentpage.cpp:50 +msgid "" +"Move selected directory one position up.\n" +"This effects which backend will be chosen, if there are several versions." +msgstr "" +"Mover a directoria seleccionada uma posição acima.\n" +"Este procedimento afecta qual backend será escolhido, caso existam várias " +"versões." + +#: configenvironmentpage.cpp:60 +msgid "" +"Move selected directory one position down.\n" +"This effects which backend will be chosen, if there are several versions." +msgstr "" +"Mover a directoria seleccionada uma posição abaixo.\n" +"Este procedimento afecta qual backend será escolhido, caso existam várias " +"versões." + +#: configenvironmentpage.cpp:67 configpluginspage.cpp:50 +msgid "Add ..." +msgstr "Adicionar ..." + +#: configenvironmentpage.cpp:87 +msgid "Programs found" +msgstr "Programas encontrados" + +#: configenvironmentpage.cpp:96 +msgid "Programs not found" +msgstr "Não foram encontrados programas" + +#: configgeneralpage.cpp:34 +msgid "Start in Mode" +msgstr "Iniciar no modo" + +#: configgeneralpage.cpp:38 options.cpp:36 +msgid "Simple" +msgstr "Simples" + +#: configgeneralpage.cpp:39 options.cpp:41 +msgid "Detailed" +msgstr "Detalhado" + +#: configgeneralpage.cpp:49 +msgid "Default profile" +msgstr "Perfil Predefinido" + +#: configgeneralpage.cpp:72 +msgid "Default format" +msgstr "Formato Predefinido" + +#: configgeneralpage.cpp:107 +msgid "Process priority of the backends" +msgstr "Prioridade dos processos dos backends" + +#: configgeneralpage.cpp:110 +msgid "Normal" +msgstr "Normal" + +#: configgeneralpage.cpp:122 +msgid "Use FAT compatible output file names" +msgstr "Usar nomes de ficheiros compatíveis com FAT" + +#: configgeneralpage.cpp:123 +msgid "Replaces some special characters like '?' by '_'." +msgstr "Substituir alguns caracteres especiais como '?' por '_'" + +#: configgeneralpage.cpp:133 +msgid "Conflict handling" +msgstr "" + +#: configgeneralpage.cpp:136 +msgid "Do that if the output file already exists" +msgstr "" + +#: configgeneralpage.cpp:137 +msgid "Generate new file name" +msgstr "" + +#: configgeneralpage.cpp:138 +msgid "Skip file" +msgstr "" + +#: configgeneralpage.cpp:149 +msgid "Number of files to convert at once" +msgstr "Número de ficheiros a converter de cada vez" + +#: configgeneralpage.cpp:160 +msgid "Status update delay (time in msec.)" +msgstr "Atraso na actualização do estado (em milisegundos)" + +#: configgeneralpage.cpp:163 +msgid "Update the progress bar in this interval (time in milliseconds)" +msgstr "" +"Actualizar a barra de progresso neste intervalo (tempo em milisegundos)" + +#: configgeneralpage.cpp:172 +msgid "Ask for new options, when adding files from external program" +msgstr "" +"Perguntar por novas opções aquando a adição de ficheiros por programas " +"externos" + +#: configgeneralpage.cpp:173 +msgid "" +"If you open a file with soundKonverter and soundKonverter is already " +"running,\n" +"you can either be asked to define new converting options\n" +"or the current settings from the soundKonverter main window are used." +msgstr "" +"Se abrir um ficheiro com o soundKonverter e se este já estiver a correr,\n" +"poderá escolher entre definir novas opções de conversão\n" +"ou manter as definições do programa já aberto." + +#: configgeneralpage.cpp:183 +msgid "Execute user script (for advanced users)" +msgstr "" + +#: configgeneralpage.cpp:184 +msgid "" +"Executes a script after every finished conversion. Have a look at " +"$KDEDIR/soundkonverter/userscript.sh" +msgstr "" + +#: configpluginspage.cpp:39 +msgid "Installed plugins" +msgstr "Plugins instalados" + +#: configpluginspage.cpp:228 +msgid "*.soundkonverter.xml|Plugins (*.soundkonverter.xml)" +msgstr "*.soundkonverter.xml|Plugins (*.soundkonverter.xml)" + +#: configpluginspage.cpp:228 +msgid "Choose a plugin to add!" +msgstr "Escolha um plugin a adicionar" + +#: configpluginspage.cpp:253 configpluginspage.cpp:546 +msgid "" +"The plugin could not be installed. Please ensure that you have selected a " +"valid soundKonverter plugin file." +msgstr "" +"O plugin não pode ser instalado. Assegure-se de que seleccionou um Plugin do " +"soundKonverter válido." + +#: configpluginspage.cpp:254 configpluginspage.cpp:294 +#: configpluginspage.cpp:547 configpluginspage.cpp:587 +msgid "Error while installing plugin" +msgstr "Erro ao instalar o plugin" + +#: configpluginspage.cpp:279 configpluginspage.cpp:572 +msgid "" +"The plugin was installed successfully. Please restart soundKonverter in " +"order to activate it." +msgstr "" +"O plugin foi instalado com sucesso. Por favor, reinicie o soundKonverter de " +"modo a activá-lo." + +#: configpluginspage.cpp:280 configpluginspage.cpp:573 +msgid "Plugin successfully installed" +msgstr "O plugin foi instalado com sucesso" + +#: configpluginspage.cpp:293 configpluginspage.cpp:586 +msgid "" +"The plugin could not be installed. Please ensure that you have write " +"permission on your whole user directory." +msgstr "" +"O plugin não pode ser instalado. Por favor certifique-se que tem permissões " +"de escrita em toda a sua directoria de utilizador" + +#: configpluginspage.cpp:311 configpluginspage.cpp:330 +#: configpluginspage.cpp:349 +msgid "" +"The plugin was removed successfully. Please restart soundKonverter in order " +"to deactivate it." +msgstr "" +"O plugin foi removido com sucesso. Por favor, reinicie o soundKonverter para " +"o desactivar." + +#: configpluginspage.cpp:312 configpluginspage.cpp:331 +#: configpluginspage.cpp:350 +msgid "Plugin successfully removed" +msgstr "Plugin removido com sucesso" + +#: configpluginspage.cpp:316 configpluginspage.cpp:335 +#: configpluginspage.cpp:354 +msgid "" +"The plugin could not be removed. Please ensure that you have write " +"permission on your whole user directory." +msgstr "" +"O plugin não pôde ser removido. Por favor certifique-se que tem permissões " +"de escrita em toda a sua directoria de utilizador" + +#: configpluginspage.cpp:317 configpluginspage.cpp:336 +#: configpluginspage.cpp:355 +msgid "Error while removing plugin" +msgstr "Erro ao remover o plugin" + +#: configpluginspage.cpp:383 configpluginspage.cpp:395 +#: configpluginspage.cpp:407 +msgid "Version" +msgstr "Versão" + +#: configpluginspage.cpp:384 configpluginspage.cpp:396 +#: configpluginspage.cpp:408 +msgid "Author" +msgstr "Autor" + +#: configpluginspage.cpp:417 configpluginspage.cpp:472 +msgid "No new plugins available!" +msgstr "Não há novos plugins disponíveis!" + +#: configpluginspage.cpp:477 +msgid "" +"The plugin list could not be downloaded. Please ensure, that your internet " +"connection works correct.\n" +"Maybe our server is busy at the moment, please try it again later." +msgstr "" +"A lista de plugins não pode ser descarregada. Verifique se a sua ligação à " +"internet se encontra funcional.\n" +"Talvez o nosso servidor esteja ocupado neste momento, por favor tente mais " +"tarde." + +#: configpluginspage.cpp:478 +msgid "Error while loading plugin list" +msgstr "Erro ao carregar a lista de plugins" + +#: configpluginspage.cpp:626 configpluginspage.cpp:632 +msgid "" +"The plugin info could not be downloaded. Please ensure, that your internet " +"connection works correctly." +msgstr "" +"A informação do plugin não pôde ser descarregada. Assegure-se que a sua " +"ligação à Internet está funcional." + +#: configpluginspage.cpp:627 configpluginspage.cpp:633 +msgid "Error while loading plugin info" +msgstr "Erro ao carregar a informação do plugin" + +#: convert.cpp:83 convert.cpp:86 convert.cpp:1538 +msgid "Getting file" +msgstr "A obter ficheiro" + +#: convert.cpp:86 convert.cpp:130 convert.cpp:190 convert.cpp:260 +#: convert.cpp:314 convert.cpp:555 convert.cpp:593 convert.cpp:603 +#: convert.cpp:617 convert.cpp:661 convert.cpp:694 convert.cpp:1538 +#: convert.cpp:1542 convert.cpp:1547 convert.cpp:1551 convert.cpp:1557 +#: convert.cpp:1561 convert.cpp:1571 convert.cpp:1575 convert.cpp:1580 +#: convert.cpp:1583 convert.cpp:1587 filelist.cpp:136 filelist.cpp:638 +#: filelist.cpp:641 filelist.cpp:650 filelist.cpp:651 filelist.cpp:696 +#: filelist.cpp:726 filelist.cpp:729 filelist.cpp:733 filelist.cpp:860 +#: filelist.cpp:861 filelist.cpp:918 filelist.cpp:955 filelist.cpp:956 +msgid "State" +msgstr "Estado" + +#: convert.cpp:116 convert.cpp:130 convert.cpp:1542 +msgid "Getting correction file" +msgstr "A obter ficheiro de correcção" + +#: convert.cpp:122 +msgid "Aborting, file does not exist" +msgstr "A abortar, o ficheiro não existe" + +#: convert.cpp:157 convert.cpp:190 convert.cpp:260 convert.cpp:1547 +#: convert.cpp:1551 +msgid "Ripping" +msgstr "A ripar" + +#: convert.cpp:270 convert.cpp:314 convert.cpp:1557 convert.cpp:1561 +msgid "Decoding" +msgstr "A descodificar" + +#: convert.cpp:334 convert.cpp:555 convert.cpp:1571 convert.cpp:1575 +msgid "Encoding" +msgstr "A codificar" + +#: convert.cpp:453 filelist.cpp:1401 optionsdetailed.cpp:541 +msgid "Stereo" +msgstr "Stereo" + +#: convert.cpp:456 filelist.cpp:1404 optionsdetailed.cpp:544 +msgid "Joint-Stereo" +msgstr "Joint-Stereo" + +#: convert.cpp:459 filelist.cpp:1407 optionsdetailed.cpp:547 +msgid "Forced Joint-Stereo" +msgstr "Forced Joint-Stereo" + +#: convert.cpp:462 filelist.cpp:1410 optionsdetailed.cpp:550 +msgid "Dual Channels" +msgstr "Canais Duplos" + +#: convert.cpp:563 replaygainfilelist.cpp:914 +msgid "Applying Replay Gain" +msgstr "Normalizando" + +#: convert.cpp:598 convert.cpp:603 +msgid "Writing tags" +msgstr "A escrever etiquetas" + +#: convert.cpp:611 convert.cpp:617 convert.cpp:1583 +msgid "Moving file" +msgstr "A mover ficheiro" + +#: convert.cpp:649 convert.cpp:661 convert.cpp:1587 +msgid "Moving correction file" +msgstr "A mover ficheiro de correcção" + +#: convert.cpp:688 convert.cpp:694 +msgid "Running user script" +msgstr "" + +#: convert.cpp:713 +msgid "Executing next step" +msgstr "A executar o próximo passo" + +#: convert.cpp:857 convert.cpp:874 convert.cpp:1123 convert.cpp:1147 +msgid "Got file" +msgstr "Ficheiro obtido" + +#: convert.cpp:891 convert.cpp:1204 convert.cpp:1216 +msgid "Could not write to file: `%1'" +msgstr "Não foi possível escrever: `%1'" + +#: convert.cpp:903 convert.cpp:918 convert.cpp:1228 convert.cpp:1255 +msgid "File moved" +msgstr "Ficheiro movido" + +#: convert.cpp:941 filelist.cpp:70 filelist.cpp:138 filelist.cpp:750 +#: outputdirectory.cpp:39 replaygainfilelist.cpp:1141 +msgid "Output" +msgstr "Saída" + +#: convert.cpp:1292 +msgid "Adding new item to conversion list: `%1'" +msgstr "" + +#: convert.cpp:1299 +msgid "Got log ID: %1" +msgstr "Obtido log ID: %1" + +#: convert.cpp:1302 +msgid "Tags successfully read" +msgstr "Etiquetas lidas com sucesso" + +#: convert.cpp:1303 +msgid "Reading tags failed" +msgstr "Falhou a leitura das Etiquetas" + +#: convert.cpp:1443 convert.cpp:1453 replaygainfilelist.cpp:1025 +msgid "Killing process ..." +msgstr "A terminar o processo..." + +#: convert.cpp:1446 replaygainfilelist.cpp:1028 +msgid "Killing process failed. Stopping after files are completed ..." +msgstr "" +"Terminação do processo falhou. A parar depois dos ficheiros estarem " +"completos ..." + +#: convert.cpp:1468 +msgid "Removing file from conversion list. Exit code %1" +msgstr "A remover o ficheiro da lista de conversão. Código de saída %1" + +#: convert.cpp:1475 +msgid "Executing command: \"%1\"" +msgstr "A executar o comando: \"%1\"" + +#: cuesheeteditor.cpp:29 +msgid "Cuesheet Editor" +msgstr "Editor da Lista de Faixas" + +#: cuesheeteditor.cpp:76 +msgid "Generate" +msgstr "Gerar" + +#: cuesheeteditor.cpp:82 +msgid "Format" +msgstr "Formato" + +#: cuesheeteditor.cpp:88 +msgid "Shift Title/Performer" +msgstr "Trocar Título/Intérprete" + +#: cuesheeteditor.cpp:113 +msgid "" +"

With this small tool you can process cue files as they are used for " +"burning music mixes and for organizing them in media players like " +"amaroK.

You can generate a new file by pasting text into the input " +"area. It must be formated the following way:

Title - Artist " +"[time]
Title - Artist [3:25]
Title - Artist [2:37]
...
A tip: " +"Use kwrite and regular expressions to format it this way.

" +msgstr "" +"

Com esta pequena ferramenta, pode processar ficheiros CUE, usados na " +"gravação de música e na sua organização pelos reprodutores de áudio como o " +"amaroK\n" +"\n" +"Pode gerar um novo ficheiro colando texto na área de introdução. Deve estar " +"de acordo com o seguinte formato:\n" +"\n" +"Título - Artista [tempo]\n" +"Título - Artista [3:25]\n" +"Título - Artista [2:37]\n" +"...\n" +"Dica: Use o kwrite e expressões regulares para o formatar desta forma.

" + +#: cuesheeteditor.cpp:114 +msgid "Cuesheet Editor - Help" +msgstr "Editor da Lista de Faixas - Ajuda" + +#: dirdialog.cpp:24 +msgid "Add folder" +msgstr "Adicionar pasta ..." + +#: dirdialog.cpp:33 +msgid "Directory:" +msgstr "Directoria de entrada" + +#: dirdialog.cpp:63 +msgid "Select all" +msgstr "Selecionar tudo" + +#: dirdialog.cpp:69 +msgid "Select none" +msgstr "Selecionar nenhum" + +#: dirdialog.cpp:75 +msgid "Recursive" +msgstr "" + +#: dirdialog.cpp:106 dirdialog.cpp:133 +msgid "Choose a directory" +msgstr "Escolha uma directoria" + +#: filelist.cpp:70 filelist.cpp:137 filelist.cpp:736 filelist.cpp:737 +msgid "Input" +msgstr "Entrada" + +#: filelist.cpp:170 +msgid "Edit options ..." +msgstr "Editar opções ..." + +#: filelist.cpp:171 +msgid "Start conversion" +msgstr "Iniciar a conversão" + +#: filelist.cpp:172 +msgid "Stop conversion" +msgstr "Para conversão" + +#: filelist.cpp:184 +msgid "" +"

File List

Select your desired output options in " +"the form above and add some files.
You can add files by clicking on " +"\"Add files ...\" or dropping them here.
" +msgstr "" +"

Lista de ficheiros

Seleccione as opções de saída " +"desejadas no formulário acima e adicione alguns ficheiros.
Pode " +"adicionar ficheiros ao clicar em \"Adicionar ficheiros\" ou largá-los " +"aqui.
" + +#: filelist.cpp:578 filelist.cpp:593 +msgid "Audio CD (%1)" +msgstr "CD áudio (%1)" + +#: filelist.cpp:609 filelist.cpp:624 +msgid "Full audio CD (%1)" +msgstr "Audio CD completo (%1)" + +#: filelist.cpp:638 filelist.cpp:650 filelist.cpp:955 +msgid "Stopped" +msgstr "Parado" + +#: filelist.cpp:641 filelist.cpp:650 filelist.cpp:955 +msgid "Failed" +msgstr "Falhou" + +#: filelist.cpp:650 filelist.cpp:726 filelist.cpp:860 filelist.cpp:955 +msgid "Will be skipped" +msgstr "" + +#: filelist.cpp:651 filelist.cpp:696 filelist.cpp:729 filelist.cpp:861 +#: filelist.cpp:918 filelist.cpp:956 progressindicator.cpp:49 +msgid "Waiting" +msgstr "Em espera" + +#: filelist.cpp:733 +msgid "Converting" +msgstr "A converter" + +#: logger.cpp:136 +msgid "Finished logging" +msgstr "Relatório concluído" + +#: logviewer.cpp:83 +msgid "Log Viewer" +msgstr "Visualizador de relatórios" + +#: logviewer.cpp:90 +msgid "Job/File" +msgstr "Tarefa/ficheiro" + +#: main.cpp:12 +msgid "" +"soundKonverter is a frontend to various sound en- and decoding programs." +msgstr "" +"O soundKonverter é um frontend para vários codificadores e descodificadores " +"de áudio." + +#: main.cpp:18 +msgid "Open the Replay Gain tool an add all given files" +msgstr "" +"Abra a ferramenta de normalização e adicione todos os ficheiros dados." + +#: main.cpp:20 +msgid "List all tracks on the cd drive , 'auto' will search for a cd" +msgstr "" +"Listar todas as faixas na drive de cd , 'auto' irá procurar um cd" + +#: main.cpp:21 +msgid "Add all files using the given profile" +msgstr "Adicionar todos os ficheiros no perfil dado" + +#: main.cpp:22 +msgid "Add all files using the given format" +msgstr "Adicionar todos os ficheiros no formato dado" + +#: main.cpp:23 +msgid "Output all files to " +msgstr "Guardar todos os ficheiros em " + +#: main.cpp:24 +msgid "Start soundKonverter invisible" +msgstr "Iniciar o soundKonverter invisível" + +#: main.cpp:25 +msgid "" +"Close soundKonverter after all files are converted (enabled when using '--" +"invisible')" +msgstr "" +"Fechar o soundKonverter após a conversão de todos os ficheiros (ligado " +"quando usada a opção '--invisible')" + +#: main.cpp:26 +msgid "Execute after each file has been converted" +msgstr "Executar depois de cada ficheiro ter sido convertido" + +#: main.cpp:27 +msgid "Audio file(s) to append to the file list" +msgstr "Ficheiro(s) de áudio a adicionar à lista de ficheiros" + +#: main.cpp:33 +msgid "soundKonverter" +msgstr "soundKonverter" + +#: options.cpp:127 +msgid "" +"soundKonverter either found new backends or misses some.\n" +"Click on this button in order to open the configuration dialog." +msgstr "" +"O soundKonverter ou encontrou novos backends ou alguns estão em falta.\n" +"Clique aqui para abrir o painel de configuração." + +#: options.cpp:136 +msgid "Advanced Options" +msgstr "Opções avançadas" + +#: optionsdetailed.cpp:45 +msgid "Convert" +msgstr "Converter" + +#: optionsdetailed.cpp:73 +msgid "" +"vbr - variable bitrate\n" +"abr - average bitrate\n" +"cbr - constant bitrate" +msgstr "" +"vbr - taxa de bits variável\n" +"abr - taxa de bits média\n" +"cbr - taxa de bits constante" + +#: optionsdetailed.cpp:83 +msgid "Bitrate range" +msgstr "Intervalo de Taxas de Bits" + +#: optionsdetailed.cpp:84 +msgid "" +"Use it only if, you know what you are doing, you could reduce the quality." +msgstr "" +"Use apenas se souber o que está a fazer, pode ocorrer uma redução de " +"qualidade." + +#: optionsdetailed.cpp:119 +msgid "Resample" +msgstr "Reamostragem" + +#: optionsdetailed.cpp:147 +msgid "Channels" +msgstr "Canais" + +#: optionsdetailed.cpp:170 +msgid "Add a Replay Gain tag to the converted file." +msgstr "Adicionar uma etiqueta do normalizador ao ficheiro convertido" + +#: optionsdetailed.cpp:171 +msgid "" +"Replay Gain is a volume correction technique. A volume difference is " +"calculated and stored in a tag. This way audio players can automatically " +"adjust the volume and the original music data is not modified (like at " +"normalization)." +msgstr "" +"O Replay Gain é uma técnica de correcção do volume (normalização). Uma " +"diferença de volume é calculada e guardada numa etiqueta. Desta forma, os " +"reprodutores de áudio podem ajustar automaticamente o volume sem alterar o " +"ficheiro original da música." + +#: optionsdetailed.cpp:192 +msgid "Save current options as a profile" +msgstr "Guardar as opções actuais como um perfil" + +#: optionsdetailed.cpp:208 +msgid "Command" +msgstr "Comando" + +#: optionsdetailed.cpp:219 +#, c-format +msgid "%p: The parameters generated by soundKonverter" +msgstr "%p: Os parâmetros gerados pelo soundKonverter" + +#: optionsdetailed.cpp:225 +#, c-format +msgid "%i: The input file ; %o: The output file" +msgstr "%i:O ficheiro de entrada ; %o: O ficheiro de saída" + +#: optionsdetailed.cpp:353 +msgid "New profile" +msgstr "Novo Perfil" + +#: optionsdetailed.cpp:353 +msgid "Enter a name for the new profile:" +msgstr "Introduza um nome para o novo perfil:" + +#: optionsdetailed.cpp:368 +msgid "You cannot overwrite the built-in profiles." +msgstr "Não pode sobre-escrever os perfis por omissão" + +#: optionsdetailed.cpp:369 optionsdetailed.cpp:379 +msgid "Profile already exists" +msgstr "O perfil já existe" + +#: optionsdetailed.cpp:378 +msgid "" +"A profile with this name already exists.\n" +"\n" +"Do you want to overwrite the existing one?" +msgstr "" +"Já existe um perfil com este nome.\n" +"\n" +"Deseja sobreescrever o perfil existente?" + +#: optionsdetailed.cpp:473 optionsdetailed.cpp:628 +msgid "Unchanged" +msgstr "Não alterado" + +#: optionsdetailed.cpp:483 optionsdetailed.cpp:604 +msgid "Undefined" +msgstr "Não definido" + +#: optionsdetailed.cpp:561 optionsdetailed.cpp:619 +msgid "Kilobit per second" +msgstr "Kilobit por segundo" + +#: optionsdetailed.cpp:689 +msgid "" +"This is a relative quality between 0 and 100.\n" +"The higher this number the higher is the quality.\n" +"soundKonverter will convert it into the file format's quality format.\n" +"See the \"What's this?\" for more informations.\n" +"\n" +"Current parameter: \"%1\"" +msgstr "" +"Isto é uma qualidade relativa entre 0 e 100.\n" +"Quanto maior este número, maior a qualidade.\n" +"O soundKonverter vai convertê-lo para o formato apropriado da qualidade do " +"ficheiro.\n" +"Veja \"O que é isto?\" para mais informações.\n" +"\n" +"Parâmetro actual: \"%1\"" + +#: optionseditor.cpp:28 +msgid "Options Editor" +msgstr "Editor de opções" + +#: optionseditor.cpp:55 +msgid "Conversion" +msgstr "Conversão" + +#: optionseditor.cpp:55 +msgid "Conversion options" +msgstr "Opções de conversão" + +#: optionseditor.cpp:59 +msgid "Choose your prefered output options and click on \"Close\"!" +msgstr "Escolha as suas opções de saída preferidas, e carregue em \"Sair\"!" + +#: optionseditor.cpp:70 +msgid "Edit conversion options" +msgstr "Editar opções de conversão" + +#: optionseditor.cpp:79 +msgid "Tags" +msgstr "Etiquetas" + +#: optionseditor.cpp:103 +msgid "Track No.:" +msgstr "Faixa Nr.:" + +#: optionseditor.cpp:256 +msgid "Edit tags" +msgstr "Editar etiquetas" + +#: optionseditor.cpp:330 +msgid "No file selected" +msgstr "Nenhum ficheiro seleccionado" + +#: optionseditor.cpp:358 +msgid "" +"The tags could not be read, because this file isn't a local one.\n" +"soundKonverter will try to read the tags, when it is about to convert the " +"file.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags." +msgstr "" +"As etiquetas não puderam ser lidas porque o ficheiro não é local.\n" +"o soundKonverter vai tentar lê-las de novo quando estiver a converter o " +"ficheiro.\n" +"Se desejar editar as etiquetas, pode clicar no botão abaixo, mas se o fizer " +"o soundKonverter não irá\n" +"tentar lê-las." + +#: optionseditor.cpp:367 +msgid "" +"Reading the tags of this file failed.\n" +"soundKonverter will try to read the tags a second time, when it is about to " +"convert the file.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags a second time." +msgstr "" +"As etiquetas não puderam ser lidas porque o ficheiro não é local.\n" +"o soundKonverter vai tentar lê-las de novo quando estiver a converter o " +"ficheiro.\n" +"Se desejar editar as etiquetas, pode clicar no botão abaixo, mas se o fizer " +"o soundKonverter não irá\n" +"tentar lê-las novamente." + +#: optionseditor.cpp:387 +msgid "%1 Files" +msgstr "%1 Ficheiros" + +#: optionseditor.cpp:402 +msgid "" +"You have selected multiple files with different conversion options.\n" +"You can change the options of all files by hitting the button below." +msgstr "" +"Seleccionou vários ficheiros com diferentes opções de conversão.\n" +"Pode alterar as opções de todos os ficheiros clicando no botão abaixo." + +#: optionseditor.cpp:408 +msgid "" +"Reading the tags of one or more files failed.\n" +"soundKonverter will try to read the tags a second time, when it is about to " +"convert the files.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags a second time." +msgstr "" +"As etiquetas não puderam ser lidas porque o ficheiro não é local.\n" +"o soundKonverter vai tentar lê-las de novo quando estiver a converter o " +"ficheiro.\n" +"Se desejar editar as etiquetas, pode clicar no botão abaixo, mas se o fizer " +"o soundKonverter não irá\n" +"tentar lê-las novamente." + +#: optionsrequester.cpp:18 +msgid "Choose output options" +msgstr "Escolher opções de saída" + +#: optionsrequester.cpp:28 +msgid "Click on \"Ok\" to add the files to the list in the main window!" +msgstr "" +"Carregue em \"Ok\" para adicionar os ficheiros à lista na janela principal!" + +#: optionsrequester.cpp:43 +msgid "" +"Warning: If you select \"wav\" as output format, your wav files will not be " +"added to the list." +msgstr "" +"Aviso: Se você seleccionar \"wav\" como formato de saída, os seus ficheiros " +"wav não serão adicionados à lista." + +#: optionsrequester.cpp:59 +msgid "Ok" +msgstr "Ok" + +#: optionssimple.cpp:64 +msgid "Remove the selected profile" +msgstr "Remover o perfil seleccionado" + +#: optionssimple.cpp:70 optionssimple.cpp:90 +msgid "Info" +msgstr "Informação" + +#: optionssimple.cpp:71 +msgid "Information about the selected profile" +msgstr "Informação acerca do perfil seleccionado" + +#: optionssimple.cpp:78 +msgid "Output format" +msgstr "Formato de saída" + +#: optionssimple.cpp:91 +msgid "Information about the selected file format" +msgstr "Informação acerca do formato de ficheiro seleccionado" + +#: optionssimple.cpp:157 +msgid "" +"This produces sound files of a very low quality.\n" +"That can be useful, if you have a mobile device, where your memory cell is " +"limited. It is not recommended to save your music in this quality without a " +"copy with higher quality.\n" +"It can also be used to save audio files with voices." +msgstr "" +"Isto produz ficheiros de som de muito baixa qualidade.\n" +"Isso pode ser bastante util, se você tem um dispositivo móvel, com memória " +"limitada. Não é recomendado guardar a sua música nesta qualidade sem uma " +"cópia de maior qualidade.\n" +"Também pode ser utilizado para gravar ficheiros áudio com vozes." + +#: optionssimple.cpp:158 optionssimple.cpp:163 optionssimple.cpp:168 +#: optionssimple.cpp:173 optionssimple.cpp:178 optionssimple.cpp:183 +#: optionssimple.cpp:188 optionssimple.cpp:193 +msgid "Profile" +msgstr "Perfil" + +#: optionssimple.cpp:162 +msgid "" +"This produces sound files of a low quality.\n" +"That can be useful if you habe a mobile device where your memory cell is " +"limited. It is not recommended to save your music in this quality without a " +"copy with higher quality." +msgstr "" +"Isto produz ficheiros de som de baixa qualidade.\n" +"Isso pode ser bastante util, se você tem um dispositivo móvel, com memória " +"limitada. Não é recomendado guardar a sua música nesta qualidade sem uma " +"cópia de maior qualidade." + +#: optionssimple.cpp:167 +msgid "" +"This produces sound files of a medium quality.\n" +"If your disc space is limited, you can use this to save your music." +msgstr "" +"Isto produz ficheiros de som de qualidade média.\n" +"Pode ser útil se tiver espaço limitado em disco." + +#: optionssimple.cpp:172 +msgid "" +"This produces sound files of a high quality.\n" +"If you have enough disc space available, you can use this to save your music." +msgstr "" +"Isto produz ficheiros de som de alta qualidade.\n" +"Se tiver espaço suficiente em disco, pode usar esta opção para gravar a sua " +"música." + +#: optionssimple.cpp:177 +msgid "" +"This produces sound files of a very high quality.\n" +"You should only use this, if you are a quality freak and have enough disc " +"space available." +msgstr "" +"Isto produz ficheiros de qualidade muito alta.\n" +"Só deve usar esta opção se prezar a qualidade acima de tudo e se tiver " +"espaço no disco suficiente." + +#: optionssimple.cpp:182 +msgid "" +"This produces files, that have exact the same quality as the input files.\n" +"This files are very big and definitely only for quality freaks." +msgstr "" +"Isto produz ficheiros com a mesma qualidade que os originais.\n" +"Os ficheiros criados são enormes e definitivamente para quem preza qualidade " +"acima de tudo." + +#: optionssimple.cpp:187 +msgid "" +"This produces two files. One lossy compressed playable file and one " +"correction file.\n" +"Both files together result in a file that is equivalent to the input file." +msgstr "" +"Isto produz dois ficheiros: Um ficheiro reprodutível com perda de qualidade " +"e um de correcção de qualidade.\n" +"Ambos resultam num ficheiro equivalente ao original." + +#: optionssimple.cpp:192 +msgid "You can define your own profile in the \"detailed\" tab." +msgstr "Pode definir o seu próprio perfil no separador \"detalhado\"" + +#: optionssimple.cpp:205 +msgid "Do you really want to remove the profile: %1" +msgstr "De certeza que quer remover o perfil: %1" + +#: optionssimple.cpp:206 +msgid "Remove profile?" +msgstr "Remover perfil?" + +#: optionssimple.cpp:234 +msgid "" +"

Wave is a file format, that doesn't compress it's audio data.

\n" +"

So the quality is very high, but the file size is enormous. It is widely " +"spread and should work with every audio player.

\n" +"
http://en.wikipedia.org/wiki/Wav" +msgstr "" +"

O formato Wave não comprime a informação áudio

\n" +"

Por conseguinte, a qualidade é muito elevada mas o ficheiro é muito " +"grande. É um formato comum e deve funcionar em qualquer reprodutor de " +"áudio.

\n" +"
http://en.wikipedia.org/wiki/Wav" + +#: optionssimple.cpp:235 optionssimple.cpp:242 +msgid "File format" +msgstr "Formato de ficheiro" + +#: outputdirectory.cpp:44 +msgid "By meta data" +msgstr "Por meta-dados" + +#: outputdirectory.cpp:45 +msgid "Source directory" +msgstr "Directoria de entrada" + +#: outputdirectory.cpp:46 +msgid "Specify output directory" +msgstr "Especifique a directoria de saída" + +#: outputdirectory.cpp:47 +msgid "Copy directory structure" +msgstr "Copiar estrutura da directoria" + +#: outputdirectory.cpp:61 +msgid "Clear the directory input field" +msgstr "Limpar o campo da directoria de entrada" + +#: outputdirectory.cpp:81 outputdirectory.cpp:345 +msgid "Choose an output directory" +msgstr "Escolha uma directoria de destino" + +#: outputdirectory.cpp:87 +msgid "Open Konqueror with the output directory" +msgstr "Abrir o Konqueror na directoria de saída" + +#: outputdirectory.cpp:184 +msgid "Unknown Artist" +msgstr "Artista Desconhecido" + +#: outputdirectory.cpp:188 +msgid "Unknown Album" +msgstr "Álbum Desconhecido" + +#: outputdirectory.cpp:192 +msgid "No Comment" +msgstr "Sem comentário" + +#: outputdirectory.cpp:199 +msgid "Unknown Genre" +msgstr "Género Desconhecido" + +#: outputdirectory.cpp:206 +msgid "Unknown Composer" +msgstr "Compositor Desconhecido" + +#: outputdirectory.cpp:210 +msgid "Unknown Title" +msgstr "Título Desconhecido" + +#: outputdirectory.cpp:264 +msgid "new" +msgstr "novo" + +#: outputdirectory.cpp:406 +msgid "Name all converted files according to the specified pattern" +msgstr "A dar nome aos ficheiros convertidos segundo o padrão escolhido." + +#: outputdirectory.cpp:408 +msgid "" +"

The following strings are wildcards, that will be replaced by the " +"information in the meta data:

%a - Artist
%b - Album
%c - " +"Comment
%d - Disc number
%g - Genre
%n - Track number
%p - " +"Composer
%t - Title
%y - Year
%f - Original file name

" +msgstr "" +"

As strings seguintes são atalhos que serão substituidos na meta-data pela " +"informação

%a - Artista
%b - Album
%c - Comentário
%d - " +"Número do Disco
%g - Género
%n - Faixa Número
%p - Compositor
%t " +"- Título
%y - Ano
%f - Nome do Ficheiro Original

" + +#: outputdirectory.cpp:420 +msgid "" +"Output all converted files into the same directory as the original files" +msgstr "" +"Enviar todos os ficheiros convertidos para a mesma directoria que os " +"originais" + +#: outputdirectory.cpp:434 +msgid "Output all converted files into the specified output directory" +msgstr "Enviar todos os ficheiros convertidos para a directoria especificada" + +#: outputdirectory.cpp:448 +msgid "Copy the whole directory structure for all converted files" +msgstr "" +"Copiar toda a estrutura da directoria para todos os ficheiros convertidos" + +#: paranoia.cpp:214 +msgid "MB" +msgstr "MB" + +#: paranoia.cpp:215 +msgid "KB" +msgstr "KB" + +#: paranoia.cpp:216 +msgid "Bytes" +msgstr "Bytes" + +#: progressindicator.cpp:33 +msgid "Speed" +msgstr "Velocidade" + +#: progressindicator.cpp:41 +msgid "Time remaining" +msgstr "Tempo restante" + +#: progressindicator.cpp:95 progressindicator.cpp:96 replaygainscanner.cpp:216 +msgid "Finished" +msgstr "Terminado" + +#. i18n: file ./soundkonverterui.rc line 13 +#: rc.cpp:3 +#, no-c-format +msgid "&Conversion" +msgstr "&Conversão" + +#: replaygain.cpp:88 +msgid "Executing" +msgstr "A executar" + +#: replaygainfilelist.cpp:137 replaygainfilelist.cpp:147 +#: replaygainfilelist.cpp:150 replaygainfilelist.cpp:180 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:669 +#: replaygainfilelist.cpp:672 replaygainfilelist.cpp:704 +#: replaygainfilelist.cpp:707 replaygainfilelist.cpp:734 +#: replaygainfilelist.cpp:737 replaygainfilelist.cpp:940 +msgid "Album" +msgstr "Álbum" + +#: replaygainfilelist.cpp:213 +msgid "Calculate Replay Gain tags" +msgstr "Calcular etiquetas de normalização" + +#: replaygainfilelist.cpp:214 +msgid "Remove Replay Gain tags" +msgstr "Remover etiquetas de normalização" + +#: replaygainfilelist.cpp:217 replaygainfilelist.cpp:825 +msgid "New album" +msgstr "Novo álbum" + +#: replaygainfilelist.cpp:218 +msgid "Open all albums" +msgstr "Abrir todos os álbuns" + +#: replaygainfilelist.cpp:219 +msgid "Cloase all albums" +msgstr "Fechar todos os albuns" + +#: replaygainfilelist.cpp:223 +msgid "" +"

Replay Gain Tool

With this tool you can add Replay " +"Gain tags to your audio files and remove them.
Replay Gain adds a volume " +"correction information to the files so that they can be played at an equal " +"volume level.
" +msgstr "" +"

Ferramenta Replay Gain

Com esta ferramenta pode " +"adicionar e remover etiquetas de normalização aos ficheiros de áudio.
A " +"normalização assegura que todos os ficheiros áudio são reproduzidos ao mesmo " +"volume.
" + +#: replaygainfilelist.cpp:494 +msgid "You can't place files of different formats in the same 'album'." +msgstr "Não pode colocar ficheiros de diferentes formatos no mesmo 'álbum'." + +#: replaygainfilelist.cpp:494 +msgid "Different file formats" +msgstr "Diferentes formatos de ficheiro" + +#: replaygainfilelist.cpp:987 +msgid "Removing Replay Gain" +msgstr "A remover normalização" + +#: replaygainfilelist.cpp:1148 +msgid "built-in" +msgstr "imbutido" + +#: replaygainscanner.cpp:33 replaygainscanner.cpp:216 +#: replaygainscanner.cpp:231 +msgid "Replay Gain Tool" +msgstr "Ferramenta de Normalização" + +#: replaygainscanner.cpp:43 +msgid "Add Folder ..." +msgstr "Adicionar Pasta ..." + +#: replaygainscanner.cpp:44 +msgid "Add Files ..." +msgstr "Adicionar Ficheiros ..." + +#: replaygainscanner.cpp:52 +msgid "Force recalculation" +msgstr "Forçar cálculo" + +#: replaygainscanner.cpp:53 +msgid "" +"Recalculate Replay Gain tag for files that already have a Replay Gain tag " +"set." +msgstr "" +"A recalcular a normalização para os ficheiros que já possuem uma etiqueta de " +"normalização definida." + +#: replaygainscanner.cpp:102 +msgid "Tag untagged" +msgstr "Etiquetar as não etiquetadas" + +#: replaygainscanner.cpp:103 +msgid "" +"Calculate Replay Gain tag for all files in the file list without Replay Gain " +"tag." +msgstr "" +"Calcular a etiqueta de normalização para todos os ficheiros da lista que não " +"a tenham." + +#: replaygainscanner.cpp:109 +msgid "Untag tagged" +msgstr "Desetiquetar as etiquetadas" + +#: replaygainscanner.cpp:110 +msgid "Remove the Replay Gain tag from all files in the file list." +msgstr "Remover as etiquetas de normalização de todos os ficheiros da lista." + +#: replaygainscanner.cpp:151 +msgid "Choose files!" +msgstr "Escolha ficheiros!" + +#: soundkonverter.cpp:107 +msgid "Choose your prefered output options and click on \"Add files ...\"!" +msgstr "" +"Escolha as suas opções de saída e pressione \"Adicionar ficheiros ...\"" + +#: soundkonverter.cpp:110 soundkonverter.cpp:405 soundkonverter.cpp:448 +msgid "&Start conversion" +msgstr "&Iniciar conversão" + +#: soundkonverter.cpp:112 +msgid "&Replay Gain Tool ..." +msgstr "&Ferramenta de Normalização ..." + +#: soundkonverter.cpp:114 +msgid "C&uesheet Editor ..." +msgstr "E&ditor da Lista de Faixas" + +#: soundkonverter.cpp:115 +msgid "Show &Log ..." +msgstr "Mostrar &Registo" + +#: soundkonverter.cpp:118 +msgid "S&top after current file is complete" +msgstr "&Parar depois da conclusão do ficheiro actual" + +#: soundkonverter.cpp:119 +msgid "&Continue after current file is complete" +msgstr "&Continuar depois da conclusão do ficheiro actual" + +#: soundkonverter.cpp:120 +msgid "Stop &immediately" +msgstr "Parar a&gora" + +#: soundkonverter.cpp:148 +msgid "A&dd Files ..." +msgstr "A&dicionar Ficheiros ..." + +#: soundkonverter.cpp:149 +msgid "Add &Folder ..." +msgstr "Adicionar &Pasta ..." + +#: soundkonverter.cpp:150 +msgid "Add CD &tracks ..." +msgstr "Adicionar &Faixas de CD ..." + +#: soundkonverter.cpp:151 +msgid "Add &URL ..." +msgstr "Adicionar &URL ..." + +#: soundkonverter.cpp:154 +msgid "L&oad file list" +msgstr "C&arregar lista de ficheiros" + +#: soundkonverter.cpp:155 +msgid "Sa&ve file list" +msgstr "&Guardar lista de ficheiros" + +#: soundkonverter.cpp:229 +msgid "Add files ..." +msgstr "Adicionar ficheiros ..." + +#: soundkonverter.cpp:230 +msgid "Add folder ..." +msgstr "Adicionar pasta ..." + +#: soundkonverter.cpp:231 +msgid "Add CD tracks ..." +msgstr "Adicionar faixas de CD" + +#: soundkonverter.cpp:232 +msgid "Add URL ..." +msgstr "Adicionar URL ..." + +#: soundkonverter.cpp:240 +msgid "Start" +msgstr "Iniciar" + +#: soundkonverter.cpp:417 +msgid "&Start queue" +msgstr "&Iniciar fila" + +#: soundkonverter.cpp:489 +msgid "Choose files to convert" +msgstr "Escolha os ficheiros a converter" + +#: soundkonverter.cpp:617 +msgid "Open URL" +msgstr "Abrir URL" + +#: soundkonverter.cpp:617 +msgid "Enter a URL:" +msgstr "Introduza um URL:" diff --git a/po/ru.po b/po/ru.po new file mode 100644 index 0000000..9b8f840 --- /dev/null +++ b/po/ru.po @@ -0,0 +1,1632 @@ +# translation of ru.po to +# translation of de.po to +# This file is put in the public domain. +# +# Daniel Faust , 2006, 2007. +# Ivan Bobrov , 2007. +msgid "" +msgstr "" +"Project-Id-Version: ru\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2008-02-25 17:22+0100\n" +"PO-Revision-Date: 2007-09-07 20:09+0000\n" +"Last-Translator: Иван Бобров \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Launchpad-Export-Date: 2008-04-06 10:52+0000\n" +"X-Generator: Launchpad (build Unknown)\n" + +#: _translatorinfo.cpp:1 +msgid "Your names" +msgstr "Иван Бобров,,Launchpad Contributions:,Qiwichupa,Иван Бобров" + +#: _translatorinfo.cpp:3 +msgid "Your emails" +msgstr "ibobrik@gmail.com,,,scorpion@matrixagents.net,ibobrik@gmail.com" + +#: cddb.cpp:368 +msgid "No Title" +msgstr "Заголовок отсутствует" + +#: cddb.cpp:372 cdmanager.cpp:97 convert.cpp:513 convert.cpp:514 +#: convert.cpp:515 convert.cpp:517 convert.cpp:519 convert.cpp:520 +#: convert.cpp:1547 convert.cpp:1557 convert.cpp:1571 +#: replaygainfilelist.cpp:136 replaygainfilelist.cpp:137 +#: replaygainfilelist.cpp:144 replaygainfilelist.cpp:150 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:666 +#: replaygainfilelist.cpp:672 replaygainfilelist.cpp:701 +#: replaygainfilelist.cpp:707 replaygainfilelist.cpp:731 +#: replaygainfilelist.cpp:737 replaygainfilelist.cpp:945 +msgid "Unknown" +msgstr "Не известный" + +#: cddb.cpp:380 +msgid "Track %1" +msgstr "Дорожка %1" + +#: cddb.cpp:479 +msgid "Searching local cddb entry ..." +msgstr "Поиск в локальной базе cddb ..." + +#: cddb.cpp:504 +msgid "Searching remote cddb entry ..." +msgstr "Поиск в удалённой базе cddb ..." + +#: cddb.cpp:528 +msgid "Found exact match cddb entry ..." +msgstr "Найдено точное совпадение в базе cddb ..." + +#: cddb.cpp:585 +msgid "Found close cddb entry ..." +msgstr "В базе cddb найден закрытый элемент ..." + +#: cddb.cpp:608 +msgid "CDDB Matches" +msgstr "Совпадение CDDB" + +#: cddb.cpp:608 +msgid "Several close CDDB entries found. Choose one:" +msgstr "Несколько похожих записей cddb найдено. Выберите одну:" + +#: cdmanager.cpp:46 filelist.cpp:618 +msgid "Audio CD" +msgstr "Аудио-диск" + +#: cdmanager.cpp:46 +msgid "Several audio CDs found. Choose one:" +msgstr "Обнаружено несколько айдио-дисков. Выберите один из:" + +#: cdmanager.cpp:104 +msgid "No audio CD found." +msgstr "Не найдено ни одного аудио диска." + +#: cdopener.cpp:41 +msgid "Add CD tracks" +msgstr "Добавить космозиции аудио-диска" + +#: cdopener.cpp:52 cdopener.cpp:178 optionseditor.cpp:123 +msgid "Artist:" +msgstr "Исполнитель:" + +#: cdopener.cpp:57 cdopener.cpp:480 cdopener.cpp:485 cdopener.cpp:538 +#: cdopener.cpp:567 cdopener.cpp:682 cdopener.cpp:697 +msgid "Various Artists" +msgstr "Разные исполнители" + +#: cdopener.cpp:66 cdopener.cpp:193 optionseditor.cpp:138 +msgid "Composer:" +msgstr "Композитор:" + +#: cdopener.cpp:71 cdopener.cpp:496 cdopener.cpp:501 cdopener.cpp:548 +#: cdopener.cpp:579 cdopener.cpp:683 cdopener.cpp:698 +msgid "Various Composer" +msgstr "Разные композиторы" + +#: cdopener.cpp:83 optionseditor.cpp:158 +msgid "Album:" +msgstr "Альбом:" + +#: cdopener.cpp:91 optionseditor.cpp:178 +msgid "Disc No.:" +msgstr "Диск №:" + +#: cdopener.cpp:96 optionseditor.cpp:194 +msgid "Year:" +msgstr "Год:" + +#: cdopener.cpp:100 optionseditor.cpp:210 +msgid "Genre:" +msgstr "Жанр:" + +#: cdopener.cpp:114 cdopener.cpp:532 filelist.cpp:578 filelist.cpp:587 +#: replaygainfilelist.cpp:136 replaygainfilelist.cpp:141 +#: replaygainfilelist.cpp:144 replaygainfilelist.cpp:178 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:663 +#: replaygainfilelist.cpp:666 replaygainfilelist.cpp:698 +#: replaygainfilelist.cpp:701 replaygainfilelist.cpp:728 +#: replaygainfilelist.cpp:731 +msgid "Track" +msgstr "Композиция" + +#: cdopener.cpp:115 cdopener.cpp:568 cdopener.cpp:571 cdopener.cpp:607 +msgid "Artist" +msgstr "Автор" + +#: cdopener.cpp:116 cdopener.cpp:580 cdopener.cpp:583 cdopener.cpp:620 +msgid "Composer" +msgstr "Композитор" + +#: cdopener.cpp:117 cdopener.cpp:594 +msgid "Title" +msgstr "Название" + +#: cdopener.cpp:118 +msgid "Time" +msgstr "Длительность" + +#: cdopener.cpp:131 +msgid "No track selected" +msgstr "Нет выбранных композиций" + +#: cdopener.cpp:159 optionseditor.cpp:88 +msgid "Title:" +msgstr "Название:" + +#: cdopener.cpp:212 optionseditor.cpp:235 +msgid "Comment:" +msgstr "Комментарий:" + +#: cdopener.cpp:242 +msgid "Save cuesheet ..." +msgstr "Сохранить таблицу cue ..." + +#: cdopener.cpp:250 +msgid "Add all tracks" +msgstr "Добавить все композиции" + +#: cdopener.cpp:251 +msgid "Add selected tracks" +msgstr "Добавить выбранные композиции" + +#: cdopener.cpp:253 +msgid "Add full CD as one file" +msgstr "Добавить диск как один файл" + +#: cdopener.cpp:440 +msgid "All tracks" +msgstr "Все композиции" + +#: cdopener.cpp:443 +msgid "Tracks" +msgstr "Композиции" + +#: cdopener.cpp:742 +msgid "" +"A file with this name already exists.\n" +"\n" +"Do you want to overwrite the existing one?" +msgstr "" +"Файл с таким именем уже существует.\n" +"\n" +"Хотите перезаписать?" + +#: cdopener.cpp:743 +msgid "File already exists" +msgstr "Такой файл уже существует" + +#: config.cpp:103 config.cpp:104 config.cpp:1197 config.cpp:1206 +#: config.cpp:1237 configgeneralpage.cpp:37 configgeneralpage.cpp:60 +#: configgeneralpage.cpp:62 configgeneralpage.cpp:269 +#: configgeneralpage.cpp:273 configgeneralpage.cpp:297 +#: configgeneralpage.cpp:306 configgeneralpage.cpp:316 options.cpp:153 +#: optionsdetailed.cpp:363 optionssimple.cpp:49 optionssimple.cpp:221 +#: optionssimple.cpp:518 soundkonverter.cpp:308 soundkonverter.cpp:309 +msgid "Last used" +msgstr "Последнее использованное" + +#: config.cpp:508 +msgid "Convert with soundKonverter ..." +msgstr "Конвертировать используя soundKonverter" + +#: config.cpp:543 +msgid "Add Replay Gain with soundKonverter ..." +msgstr "Добавить тег Replay Gain с помощью soundKonverter ..." + +#: config.cpp:1228 config.cpp:1229 configgeneralpage.cpp:57 +#: configgeneralpage.cpp:302 convert.cpp:431 filelist.cpp:1379 +#: optionsdetailed.cpp:361 optionsdetailed.cpp:427 optionsdetailed.cpp:477 +#: optionsdetailed.cpp:527 optionsdetailed.cpp:604 optionssimple.cpp:46 +#: optionssimple.cpp:140 optionssimple.cpp:180 optionssimple.cpp:218 +#: optionssimple.cpp:407 optionssimple.cpp:515 optionssimple.cpp:535 +msgid "Lossless" +msgstr "Без потерь" + +#: config.cpp:1232 config.cpp:1233 configgeneralpage.cpp:58 +#: configgeneralpage.cpp:312 convert.cpp:434 convert.cpp:1378 +#: filelist.cpp:1382 optionsdetailed.cpp:362 optionsdetailed.cpp:480 +#: optionsdetailed.cpp:618 optionssimple.cpp:47 optionssimple.cpp:141 +#: optionssimple.cpp:185 optionssimple.cpp:219 optionssimple.cpp:421 +#: optionssimple.cpp:430 optionssimple.cpp:516 optionssimple.cpp:544 +msgid "Hybrid" +msgstr "Гибридный режим" + +#: config.cpp:1245 config.cpp:1252 config.cpp:1259 config.cpp:1266 +#: config.cpp:1273 convert.cpp:403 convert.cpp:995 convert.cpp:1567 +#: filelist.cpp:139 filelist.cpp:752 filelist.cpp:1270 filelist.cpp:1351 +#: optionsdetailed.cpp:246 optionsdetailed.cpp:467 optionsdetailed.cpp:582 +#: optionsdetailed.cpp:641 optionssimple.cpp:38 optionssimple.cpp:283 +#: optionssimple.cpp:312 optionssimple.cpp:340 optionssimple.cpp:367 +#: optionssimple.cpp:394 +msgid "Quality" +msgstr "Качество" + +#: config.cpp:1248 config.cpp:1285 convert.cpp:450 filelist.cpp:1398 +#: optionsdetailed.cpp:538 optionssimple.cpp:294 +msgid "Mono" +msgstr "Моно" + +#: config.cpp:1250 config.cpp:1287 configgeneralpage.cpp:52 +#: configgeneralpage.cpp:289 optionsdetailed.cpp:356 optionssimple.cpp:41 +#: optionssimple.cpp:135 optionssimple.cpp:155 optionssimple.cpp:213 +#: optionssimple.cpp:269 optionssimple.cpp:510 optionssimple.cpp:525 +msgid "Very low" +msgstr "Очень низкое" + +#: config.cpp:1257 config.cpp:1294 configgeneralpage.cpp:53 +#: configgeneralpage.cpp:111 configgeneralpage.cpp:290 optionsdetailed.cpp:357 +#: optionssimple.cpp:42 optionssimple.cpp:136 optionssimple.cpp:160 +#: optionssimple.cpp:214 optionssimple.cpp:298 optionssimple.cpp:511 +#: optionssimple.cpp:525 +msgid "Low" +msgstr "Низкое" + +#: config.cpp:1264 config.cpp:1301 configgeneralpage.cpp:54 +#: configgeneralpage.cpp:291 optionsdetailed.cpp:358 optionseditor.cpp:713 +#: optionssimple.cpp:43 optionssimple.cpp:137 optionssimple.cpp:165 +#: optionssimple.cpp:215 optionssimple.cpp:326 optionssimple.cpp:512 +#: optionssimple.cpp:526 +msgid "Medium" +msgstr "Среднее" + +#: config.cpp:1271 config.cpp:1308 configgeneralpage.cpp:55 +#: configgeneralpage.cpp:292 optionsdetailed.cpp:359 optionssimple.cpp:44 +#: optionssimple.cpp:138 optionssimple.cpp:170 optionssimple.cpp:216 +#: optionssimple.cpp:353 optionssimple.cpp:513 optionssimple.cpp:526 +msgid "High" +msgstr "Высокое" + +#: config.cpp:1278 config.cpp:1315 configgeneralpage.cpp:56 +#: configgeneralpage.cpp:293 optionsdetailed.cpp:360 optionssimple.cpp:45 +#: optionssimple.cpp:139 optionssimple.cpp:175 optionssimple.cpp:217 +#: optionssimple.cpp:380 optionssimple.cpp:514 optionssimple.cpp:527 +msgid "Very high" +msgstr "Очень высокое" + +#: config.cpp:1282 config.cpp:1289 config.cpp:1296 config.cpp:1303 +#: config.cpp:1310 convert.cpp:387 convert.cpp:996 convert.cpp:997 +#: convert.cpp:1568 convert.cpp:1569 filelist.cpp:1234 filelist.cpp:1245 +#: filelist.cpp:1255 filelist.cpp:1335 optionsdetailed.cpp:246 +#: optionsdetailed.cpp:470 optionsdetailed.cpp:560 optionssimple.cpp:287 +#: optionssimple.cpp:316 optionssimple.cpp:344 optionssimple.cpp:371 +#: optionssimple.cpp:398 +msgid "Bitrate" +msgstr "Битрейт" + +#: config.cpp:1351 optionsdetailed.cpp:365 optionssimple.cpp:51 +#: optionssimple.cpp:142 optionssimple.cpp:190 optionssimple.cpp:223 +#: optionssimple.cpp:435 optionssimple.cpp:454 optionssimple.cpp:458 +#: optionssimple.cpp:468 optionssimple.cpp:472 optionssimple.cpp:520 +#: optionssimple.cpp:552 +msgid "User defined" +msgstr "Определяемое пользователем" + +#: config.cpp:1394 config.cpp:1407 config.cpp:1411 config.cpp:1457 +#: config.cpp:1461 +msgid "files" +msgstr "файл(ов)" + +#: config.cpp:1419 config.cpp:1469 +msgid "all supported formats" +msgstr "Все поддерживаемые форматы" + +#: config.cpp:1419 config.cpp:1469 +msgid "all formats" +msgstr "Все форматы" + +#: configbackendspage.cpp:42 +msgid "Legend" +msgstr "Подсказка" + +#: configbackendspage.cpp:45 +msgid "Full support" +msgstr "Полная поддержка" + +#: configbackendspage.cpp:48 +msgid "Most supported" +msgstr "Расширенная поддержка" + +#: configbackendspage.cpp:51 +msgid "Basic support" +msgstr "Базовая поддержка" + +#: configbackendspage.cpp:57 +msgid "CD Ripper" +msgstr "Риппер аудио-дисков" + +#: configbackendspage.cpp:243 +msgid "Encoder" +msgstr "Кодер" + +#: configbackendspage.cpp:256 +msgid "Strength" +msgstr "Сила" + +#: configbackendspage.cpp:263 +msgid "" +"Set the compression strength:\n" +"\n" +"Left = fast conversion\n" +"Right = good resultant file" +msgstr "" +"Установите силу компрессии:\n" +"\n" +"Левее - быстрее конвертация\n" +"Правее - лучше качество" + +#: configbackendspage.cpp:272 +msgid "Decoder" +msgstr "Декодер" + +#: configbackendspage.cpp:286 convert.cpp:593 convert.cpp:1580 +#: optionsdetailed.cpp:168 +msgid "Replay Gain" +msgstr "Replay Gain" + +#: configbackendspage.cpp:295 +msgid "Use internal Replay Gain" +msgstr "Использовать внутренний Replay Gain" + +#: configbackendspage.cpp:296 +msgid "Use the internal Replay Gain calculator of the encoder" +msgstr "Использовать внутренний калькулятор Replay Gain кодировщика" + +#: configbackendspage.cpp:320 +msgid "KDE audio CD protocol" +msgstr "Протокол KDE Audio CD" + +#: configdialog.cpp:31 +msgid "Settings" +msgstr "Настройки" + +#: configdialog.cpp:56 +msgid "General" +msgstr "Основные настройки" + +#: configdialog.cpp:68 +msgid "Plugins" +msgstr "Дополнения" + +#: configdialog.cpp:80 +msgid "Environment" +msgstr "Окружение" + +#: configdialog.cpp:92 +msgid "Backends" +msgstr "Используемые программы" + +#: configenvironmentpage.cpp:32 +msgid "Directories to be scanned" +msgstr "Сканируемые директории" + +#: configenvironmentpage.cpp:50 +msgid "" +"Move selected directory one position up.\n" +"This effects which backend will be chosen, if there are several versions." +msgstr "" +"Передвинуть выбранную директорию на одну позицию вверх.\n" +"Это определяет, какие программы будут использоваться при наличии различных " +"версий." + +#: configenvironmentpage.cpp:60 +msgid "" +"Move selected directory one position down.\n" +"This effects which backend will be chosen, if there are several versions." +msgstr "" +"Передвинуть выбранную директорию на одну позицию вниз.\n" +"Это определяет, какие программы будут использоваться при наличии различных " +"версий." + +#: configenvironmentpage.cpp:67 configpluginspage.cpp:50 +msgid "Add ..." +msgstr "Добавить..." + +#: configenvironmentpage.cpp:87 +msgid "Programs found" +msgstr "Найденные программы" + +#: configenvironmentpage.cpp:96 +msgid "Programs not found" +msgstr "Не найденные программы" + +#: configgeneralpage.cpp:34 +msgid "Start in Mode" +msgstr "Стартовать в режиме" + +#: configgeneralpage.cpp:38 options.cpp:36 +msgid "Simple" +msgstr "Простой" + +#: configgeneralpage.cpp:39 options.cpp:41 +msgid "Detailed" +msgstr "Детальный" + +#: configgeneralpage.cpp:49 +msgid "Default profile" +msgstr "Профиль по умолчанию" + +#: configgeneralpage.cpp:72 +msgid "Default format" +msgstr "Стандартный формат" + +#: configgeneralpage.cpp:107 +msgid "Process priority of the backends" +msgstr "Приоритет процесса программы-обработчика" + +#: configgeneralpage.cpp:110 +msgid "Normal" +msgstr "нормальный" + +#: configgeneralpage.cpp:122 +msgid "Use FAT compatible output file names" +msgstr "Использовать имена совместимые с файловой системой FAT" + +#: configgeneralpage.cpp:123 +msgid "Replaces some special characters like '?' by '_'." +msgstr "Заменить некоторые специальные символы типа '?' на '_'" + +#: configgeneralpage.cpp:133 +msgid "Conflict handling" +msgstr "" + +#: configgeneralpage.cpp:136 +msgid "Do that if the output file already exists" +msgstr "" + +#: configgeneralpage.cpp:137 +msgid "Generate new file name" +msgstr "" + +#: configgeneralpage.cpp:138 +msgid "Skip file" +msgstr "" + +#: configgeneralpage.cpp:149 +msgid "Number of files to convert at once" +msgstr "Количество файлов для одновременного конвертирования" + +#: configgeneralpage.cpp:160 +msgid "Status update delay (time in msec.)" +msgstr "Интервал обновления статуса (миллисекунды)" + +#: configgeneralpage.cpp:163 +msgid "Update the progress bar in this interval (time in milliseconds)" +msgstr "Интервал обновления прогресс-бара (миллисекунды)" + +#: configgeneralpage.cpp:172 +msgid "Ask for new options, when adding files from external program" +msgstr "" +"Спрашивать о дополнительных опциях при добавлении файлов из внешней программы" + +#: configgeneralpage.cpp:173 +msgid "" +"If you open a file with soundKonverter and soundKonverter is already " +"running,\n" +"you can either be asked to define new converting options\n" +"or the current settings from the soundKonverter main window are used." +msgstr "" +"Если вы откроете файл в soundKonverter, когда еще одна копия " +"soundKonverter\n" +"уже запущена, вам может быть предложен выбор: установить новые опции " +"конвертирования\n" +"или использовать текущие опции, используемые в первой запущенной копии " +"soundKonverter." + +#: configgeneralpage.cpp:183 +msgid "Execute user script (for advanced users)" +msgstr "" + +#: configgeneralpage.cpp:184 +msgid "" +"Executes a script after every finished conversion. Have a look at " +"$KDEDIR/soundkonverter/userscript.sh" +msgstr "" + +#: configpluginspage.cpp:39 +msgid "Installed plugins" +msgstr "Установленные плагины" + +#: configpluginspage.cpp:228 +msgid "*.soundkonverter.xml|Plugins (*.soundkonverter.xml)" +msgstr "*.soundkonverter.xml|Плагины (*.soundkonverter.xml)" + +#: configpluginspage.cpp:228 +msgid "Choose a plugin to add!" +msgstr "Выберите плагин для добавления." + +#: configpluginspage.cpp:253 configpluginspage.cpp:546 +msgid "" +"The plugin could not be installed. Please ensure that you have selected a " +"valid soundKonverter plugin file." +msgstr "" +"Плагин не может быть установлен. Убедитесь что вы выбрали правильный плагин-" +"файл." + +#: configpluginspage.cpp:254 configpluginspage.cpp:294 +#: configpluginspage.cpp:547 configpluginspage.cpp:587 +msgid "Error while installing plugin" +msgstr "Ошибка при установке плагина" + +#: configpluginspage.cpp:279 configpluginspage.cpp:572 +msgid "" +"The plugin was installed successfully. Please restart soundKonverter in " +"order to activate it." +msgstr "" +"Плагин был успешно установлен. Пожалуйста перезапустите soundKonverter для " +"его активации." + +#: configpluginspage.cpp:280 configpluginspage.cpp:573 +msgid "Plugin successfully installed" +msgstr "Плагин успешно установлен." + +#: configpluginspage.cpp:293 configpluginspage.cpp:586 +msgid "" +"The plugin could not be installed. Please ensure that you have write " +"permission on your whole user directory." +msgstr "" +"Плагин не был установлен. Пожалуйста проверьте, имеете ли вы права на запись " +"в вашей пользовательской директории." + +#: configpluginspage.cpp:311 configpluginspage.cpp:330 +#: configpluginspage.cpp:349 +msgid "" +"The plugin was removed successfully. Please restart soundKonverter in order " +"to deactivate it." +msgstr "" +"Плагин был успешно удален. Пожалуйста перезапустите soundKonverter для его " +"дезактивации." + +#: configpluginspage.cpp:312 configpluginspage.cpp:331 +#: configpluginspage.cpp:350 +msgid "Plugin successfully removed" +msgstr "Плагин успешно удален" + +#: configpluginspage.cpp:316 configpluginspage.cpp:335 +#: configpluginspage.cpp:354 +msgid "" +"The plugin could not be removed. Please ensure that you have write " +"permission on your whole user directory." +msgstr "" +"Плагин не был удален. Пожалуйста проверьте, имеете ли вы права на запись в " +"вашей пользовательской директории." + +#: configpluginspage.cpp:317 configpluginspage.cpp:336 +#: configpluginspage.cpp:355 +msgid "Error while removing plugin" +msgstr "Ошибка при удалении плагина" + +#: configpluginspage.cpp:383 configpluginspage.cpp:395 +#: configpluginspage.cpp:407 +msgid "Version" +msgstr "Версия" + +#: configpluginspage.cpp:384 configpluginspage.cpp:396 +#: configpluginspage.cpp:408 +msgid "Author" +msgstr "Автор" + +#: configpluginspage.cpp:417 configpluginspage.cpp:472 +msgid "No new plugins available!" +msgstr "Новые плагины не обнаружены." + +#: configpluginspage.cpp:477 +msgid "" +"The plugin list could not be downloaded. Please ensure, that your internet " +"connection works correct.\n" +"Maybe our server is busy at the moment, please try it again later." +msgstr "" +"Список плагинов не может быть загружен. Пожалуйста проверьте работает ли " +"ваше интернет-соединение.\n" +"Также возможно что наш сервер сейчас перегружен, пожалуйста попробуйте " +"скачать список позже." + +#: configpluginspage.cpp:478 +msgid "Error while loading plugin list" +msgstr "Ошибка при загрузке списка плагинов" + +#: configpluginspage.cpp:626 configpluginspage.cpp:632 +msgid "" +"The plugin info could not be downloaded. Please ensure, that your internet " +"connection works correctly." +msgstr "" +"Информация о плагине не может быть загружена. Пожалуйста проверьте работает " +"ли ваше интернет-соединение." + +#: configpluginspage.cpp:627 configpluginspage.cpp:633 +msgid "Error while loading plugin info" +msgstr "Ошибка при загрузке информации о плагине" + +#: convert.cpp:83 convert.cpp:86 convert.cpp:1538 +msgid "Getting file" +msgstr "Получение файла" + +#: convert.cpp:86 convert.cpp:130 convert.cpp:190 convert.cpp:260 +#: convert.cpp:314 convert.cpp:555 convert.cpp:593 convert.cpp:603 +#: convert.cpp:617 convert.cpp:661 convert.cpp:694 convert.cpp:1538 +#: convert.cpp:1542 convert.cpp:1547 convert.cpp:1551 convert.cpp:1557 +#: convert.cpp:1561 convert.cpp:1571 convert.cpp:1575 convert.cpp:1580 +#: convert.cpp:1583 convert.cpp:1587 filelist.cpp:136 filelist.cpp:638 +#: filelist.cpp:641 filelist.cpp:650 filelist.cpp:651 filelist.cpp:696 +#: filelist.cpp:726 filelist.cpp:729 filelist.cpp:733 filelist.cpp:860 +#: filelist.cpp:861 filelist.cpp:918 filelist.cpp:955 filelist.cpp:956 +msgid "State" +msgstr "Состояние" + +#: convert.cpp:116 convert.cpp:130 convert.cpp:1542 +msgid "Getting correction file" +msgstr "Получение коррекционного файла" + +#: convert.cpp:122 +msgid "Aborting, file does not exist" +msgstr "Прерывание. Файл не существует." + +#: convert.cpp:157 convert.cpp:190 convert.cpp:260 convert.cpp:1547 +#: convert.cpp:1551 +msgid "Ripping" +msgstr "Риппинг" + +#: convert.cpp:270 convert.cpp:314 convert.cpp:1557 convert.cpp:1561 +msgid "Decoding" +msgstr "Декодирование" + +#: convert.cpp:334 convert.cpp:555 convert.cpp:1571 convert.cpp:1575 +msgid "Encoding" +msgstr "Кодирование" + +#: convert.cpp:453 filelist.cpp:1401 optionsdetailed.cpp:541 +msgid "Stereo" +msgstr "Стерео" + +#: convert.cpp:456 filelist.cpp:1404 optionsdetailed.cpp:544 +msgid "Joint-Stereo" +msgstr "Совмещенное стерео" + +#: convert.cpp:459 filelist.cpp:1407 optionsdetailed.cpp:547 +msgid "Forced Joint-Stereo" +msgstr "Форсированное совмещение стерео" + +#: convert.cpp:462 filelist.cpp:1410 optionsdetailed.cpp:550 +msgid "Dual Channels" +msgstr "Два канала" + +#: convert.cpp:563 replaygainfilelist.cpp:914 +msgid "Applying Replay Gain" +msgstr "Применение Replay Gain" + +#: convert.cpp:598 convert.cpp:603 +msgid "Writing tags" +msgstr "Запись тегов" + +#: convert.cpp:611 convert.cpp:617 convert.cpp:1583 +msgid "Moving file" +msgstr "Перемещение файла" + +#: convert.cpp:649 convert.cpp:661 convert.cpp:1587 +msgid "Moving correction file" +msgstr "Перемещение файла корректировки" + +#: convert.cpp:688 convert.cpp:694 +msgid "Running user script" +msgstr "" + +#: convert.cpp:713 +msgid "Executing next step" +msgstr "Выполнение следующего шага" + +#: convert.cpp:857 convert.cpp:874 convert.cpp:1123 convert.cpp:1147 +msgid "Got file" +msgstr "Получен файл" + +#: convert.cpp:891 convert.cpp:1204 convert.cpp:1216 +msgid "Could not write to file: `%1'" +msgstr "Невозможно записать в файл: '%1'" + +#: convert.cpp:903 convert.cpp:918 convert.cpp:1228 convert.cpp:1255 +msgid "File moved" +msgstr "Файл перемещен" + +#: convert.cpp:941 filelist.cpp:70 filelist.cpp:138 filelist.cpp:750 +#: outputdirectory.cpp:39 replaygainfilelist.cpp:1141 +msgid "Output" +msgstr "Выходной файл" + +#: convert.cpp:1292 +msgid "Adding new item to conversion list: `%1'" +msgstr "" + +#: convert.cpp:1299 +msgid "Got log ID: %1" +msgstr "Получен ID журнала: %1" + +#: convert.cpp:1302 +msgid "Tags successfully read" +msgstr "Теги успешно прочитаны" + +#: convert.cpp:1303 +msgid "Reading tags failed" +msgstr "Чтение тегов завершено неудачно" + +#: convert.cpp:1443 convert.cpp:1453 replaygainfilelist.cpp:1025 +msgid "Killing process ..." +msgstr "Убийство процесса..." + +#: convert.cpp:1446 replaygainfilelist.cpp:1028 +msgid "Killing process failed. Stopping after files are completed ..." +msgstr "" +"Ошибка завершения процесса. Остановка после завершения списка файлов ..." + +#: convert.cpp:1468 +msgid "Removing file from conversion list. Exit code %1" +msgstr "Удаление файла из списка конвертации. Код выхода %1" + +#: convert.cpp:1475 +msgid "Executing command: \"%1\"" +msgstr "Выполнение команды: \"%1\"" + +#: cuesheeteditor.cpp:29 +msgid "Cuesheet Editor" +msgstr "Редактор таблицы образа cue" + +#: cuesheeteditor.cpp:76 +msgid "Generate" +msgstr "Сгенерировать" + +#: cuesheeteditor.cpp:82 +msgid "Format" +msgstr "Формат" + +#: cuesheeteditor.cpp:88 +msgid "Shift Title/Performer" +msgstr "Сместить Заголовок/Исполнителя" + +#: cuesheeteditor.cpp:113 +msgid "" +"

With this small tool you can process cue files as they are used for " +"burning music mixes and for organizing them in media players like " +"amaroK.

You can generate a new file by pasting text into the input " +"area. It must be formated the following way:

Title - Artist " +"[time]
Title - Artist [3:25]
Title - Artist [2:37]
...
A tip: " +"Use kwrite and regular expressions to format it this way.

" +msgstr "" +"

С помощью этого маленького инструмента вы можете работать с файлами cue, " +"которые используются для прожигания музыкальных миксов и для организации их " +"в плеерах как amaroK.

Вы можете создать новый файл вставкой текста в " +"поле ввода. Ввод должен быть форматирован следующим " +"образом:

Заголовок - Исполнитель [время]
Заголовок - Исполнитель " +"[3:25]
Заголовок - Исполнитель [2:37]
...
Подсказка: Используйте " +"kwrite и регулярные выражения для форматирования.

" + +#: cuesheeteditor.cpp:114 +msgid "Cuesheet Editor - Help" +msgstr "Редактор таблицы cue - Помощь" + +#: dirdialog.cpp:24 +msgid "Add folder" +msgstr "Добавить директорию" + +#: dirdialog.cpp:33 +msgid "Directory:" +msgstr "Директория:" + +#: dirdialog.cpp:63 +msgid "Select all" +msgstr "Выбрать все" + +#: dirdialog.cpp:69 +msgid "Select none" +msgstr "Отменить выбор" + +#: dirdialog.cpp:75 +msgid "Recursive" +msgstr "" + +#: dirdialog.cpp:106 dirdialog.cpp:133 +msgid "Choose a directory" +msgstr "Выбрать директорию" + +#: filelist.cpp:70 filelist.cpp:137 filelist.cpp:736 filelist.cpp:737 +msgid "Input" +msgstr "Вход" + +#: filelist.cpp:170 +msgid "Edit options ..." +msgstr "Опции" + +#: filelist.cpp:171 +msgid "Start conversion" +msgstr "Начать конвертирование" + +#: filelist.cpp:172 +msgid "Stop conversion" +msgstr "Остановить конвертирование" + +#: filelist.cpp:184 +msgid "" +"

File List

Select your desired output options in " +"the form above and add some files.
You can add files by clicking on " +"\"Add files ...\" or dropping them here.
" +msgstr "" +"

Список файлов

Выберите опции вывода в форме выше и " +"добавьте файлы.
Вы можете добавить файлы выбором \"Добавить файлы ...\" " +"или перетаскиванием их сюда.
" + +#: filelist.cpp:578 filelist.cpp:593 +msgid "Audio CD (%1)" +msgstr "Аудио-диск (%1)" + +#: filelist.cpp:609 filelist.cpp:624 +msgid "Full audio CD (%1)" +msgstr "Весь аудио диск (%1)" + +#: filelist.cpp:638 filelist.cpp:650 filelist.cpp:955 +msgid "Stopped" +msgstr "Остановлено" + +#: filelist.cpp:641 filelist.cpp:650 filelist.cpp:955 +msgid "Failed" +msgstr "Завершено неудачно" + +#: filelist.cpp:650 filelist.cpp:726 filelist.cpp:860 filelist.cpp:955 +msgid "Will be skipped" +msgstr "" + +#: filelist.cpp:651 filelist.cpp:696 filelist.cpp:729 filelist.cpp:861 +#: filelist.cpp:918 filelist.cpp:956 progressindicator.cpp:49 +msgid "Waiting" +msgstr "В ожидании" + +#: filelist.cpp:733 +msgid "Converting" +msgstr "Конвертируется" + +#: logger.cpp:136 +msgid "Finished logging" +msgstr "Запись журнала завершена" + +#: logviewer.cpp:83 +msgid "Log Viewer" +msgstr "Программа просмотра журналов" + +#: logviewer.cpp:90 +msgid "Job/File" +msgstr "Задание/Файл" + +#: main.cpp:12 +msgid "" +"soundKonverter is a frontend to various sound en- and decoding programs." +msgstr "soundKonverter это оболочка для различных аудио кодеков и декодеров" + +#: main.cpp:18 +msgid "Open the Replay Gain tool an add all given files" +msgstr "Откройте Replay Gain и добавьте все заданные файлы" + +#: main.cpp:20 +msgid "List all tracks on the cd drive , 'auto' will search for a cd" +msgstr "Список всех дорожек на диске , 'auto' осуществит поиск диска" + +#: main.cpp:21 +msgid "Add all files using the given profile" +msgstr "Добавить все файлы с использованием указанного профиля" + +#: main.cpp:22 +msgid "Add all files using the given format" +msgstr "Добавить все файлы с использованием указанного формата" + +#: main.cpp:23 +msgid "Output all files to " +msgstr "Записать все файлы в <директорию>" + +#: main.cpp:24 +msgid "Start soundKonverter invisible" +msgstr "Запустить soundKonverter скрытым" + +#: main.cpp:25 +msgid "" +"Close soundKonverter after all files are converted (enabled when using '--" +"invisible')" +msgstr "" +"Закрыть soundKonverter после конвертирования всех файлов (активно при " +"использовании ключа '--invisible')" + +#: main.cpp:26 +msgid "Execute after each file has been converted" +msgstr "Выполнять <команду> после конвертирования каждого файла" + +#: main.cpp:27 +msgid "Audio file(s) to append to the file list" +msgstr "Файл(ы) для добавления к списку" + +#: main.cpp:33 +msgid "soundKonverter" +msgstr "soundKonverter" + +#: options.cpp:127 +msgid "" +"soundKonverter either found new backends or misses some.\n" +"Click on this button in order to open the configuration dialog." +msgstr "" +"soundKonverter также нашел новые или потерял внешние программы.\n" +"Нажмите на кнопку для открытия диалога настройки." + +#: options.cpp:136 +msgid "Advanced Options" +msgstr "Дополнительные параметры" + +#: optionsdetailed.cpp:45 +msgid "Convert" +msgstr "Конвертировать" + +#: optionsdetailed.cpp:73 +msgid "" +"vbr - variable bitrate\n" +"abr - average bitrate\n" +"cbr - constant bitrate" +msgstr "" +"vbr - переменный битрейт\n" +"abr - средний битрейт\n" +"cbr - постоянный битрейт" + +#: optionsdetailed.cpp:83 +msgid "Bitrate range" +msgstr "Пределы битрейта" + +#: optionsdetailed.cpp:84 +msgid "" +"Use it only if, you know what you are doing, you could reduce the quality." +msgstr "" +"Используйте только если знаете что вы делаете, вы можете ухудшить качество." + +#: optionsdetailed.cpp:119 +msgid "Resample" +msgstr "Новая частота дискретизации" + +#: optionsdetailed.cpp:147 +msgid "Channels" +msgstr "Каналы" + +#: optionsdetailed.cpp:170 +msgid "Add a Replay Gain tag to the converted file." +msgstr "Добавить тег Replay Gain к выходному файлы." + +#: optionsdetailed.cpp:171 +msgid "" +"Replay Gain is a volume correction technique. A volume difference is " +"calculated and stored in a tag. This way audio players can automatically " +"adjust the volume and the original music data is not modified (like at " +"normalization)." +msgstr "" +"Replay Gain это техника коррекции громкости. Различия в громкости " +"обрабатываются и записываются в тег. Это позволяет плеерам автоматически " +"настроить громкость, а оригинальные данные не будут изменены (как при " +"нормализации)." + +#: optionsdetailed.cpp:192 +msgid "Save current options as a profile" +msgstr "Сохранить текущие установки в профиль" + +#: optionsdetailed.cpp:208 +msgid "Command" +msgstr "Команда" + +#: optionsdetailed.cpp:219 +#, c-format +msgid "%p: The parameters generated by soundKonverter" +msgstr "%p: Параметры, созданные soundKonverter" + +#: optionsdetailed.cpp:225 +#, c-format +msgid "%i: The input file ; %o: The output file" +msgstr "%i: Файл ввода ; %o: Файл вывода" + +#: optionsdetailed.cpp:353 +msgid "New profile" +msgstr "Новый профиль" + +#: optionsdetailed.cpp:353 +msgid "Enter a name for the new profile:" +msgstr "Введите имя нового профиля" + +#: optionsdetailed.cpp:368 +msgid "You cannot overwrite the built-in profiles." +msgstr "Вы не можете перезаписывать встроенные профили." + +#: optionsdetailed.cpp:369 optionsdetailed.cpp:379 +msgid "Profile already exists" +msgstr "Профиль уже существует" + +#: optionsdetailed.cpp:378 +msgid "" +"A profile with this name already exists.\n" +"\n" +"Do you want to overwrite the existing one?" +msgstr "" +"Профиль с таким именем уже существует.\n" +"Вы хотите перезаписать его?" + +#: optionsdetailed.cpp:473 optionsdetailed.cpp:628 +msgid "Unchanged" +msgstr "Не изменено" + +#: optionsdetailed.cpp:483 optionsdetailed.cpp:604 +msgid "Undefined" +msgstr "Не определено" + +#: optionsdetailed.cpp:561 optionsdetailed.cpp:619 +msgid "Kilobit per second" +msgstr "Килобит в секунду" + +#: optionsdetailed.cpp:689 +msgid "" +"This is a relative quality between 0 and 100.\n" +"The higher this number the higher is the quality.\n" +"soundKonverter will convert it into the file format's quality format.\n" +"See the \"What's this?\" for more informations.\n" +"\n" +"Current parameter: \"%1\"" +msgstr "" +"Это относительное качество между 0 и 100.\n" +"Более высокий номер обозначает более высокое качество.\n" +"soundKonverter переведет это в формат качества выходного файла.\n" +"Смотрите \"Что это?\" для подробной информации.\n" +"\n" +"Текущий параметр: \"%1\"" + +#: optionseditor.cpp:28 +msgid "Options Editor" +msgstr "Редактор настроек" + +#: optionseditor.cpp:55 +msgid "Conversion" +msgstr "Конвертирование" + +#: optionseditor.cpp:55 +msgid "Conversion options" +msgstr "Параметры конвертации" + +#: optionseditor.cpp:59 +msgid "Choose your prefered output options and click on \"Close\"!" +msgstr "Выберите необходимые настройки и нажмите \"Закрыть\"!" + +#: optionseditor.cpp:70 +msgid "Edit conversion options" +msgstr "Редактировать параметры конвертации" + +#: optionseditor.cpp:79 +msgid "Tags" +msgstr "Тэги" + +#: optionseditor.cpp:103 +msgid "Track No.:" +msgstr "Композиция №:" + +#: optionseditor.cpp:256 +msgid "Edit tags" +msgstr "Редактировать тэги" + +#: optionseditor.cpp:330 +msgid "No file selected" +msgstr "Файл не выбран" + +#: optionseditor.cpp:358 +msgid "" +"The tags could not be read, because this file isn't a local one.\n" +"soundKonverter will try to read the tags, when it is about to convert the " +"file.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags." +msgstr "" +"Теги не могут быть прочитаны, потому что это не локальный файл.\n" +"soundKonverter попробует прочитать теги при конвертировании файла.\n" +"Если вы хотите редактировать теги, то нажмите на кнопку ниже,\n" +"но тогда теги не будут читаться." + +#: optionseditor.cpp:367 +msgid "" +"Reading the tags of this file failed.\n" +"soundKonverter will try to read the tags a second time, when it is about to " +"convert the file.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags a second time." +msgstr "" +"Чтение тэгов данного файла закончено неуспешно.\n" +"soundKonverter попробует прочитать их вторично при конвертации файла.\n" +"Если вы хотите редактировать тэги, вы можете нажать кнопку ниже, но\n" +"тогда soundKonverter не будет пытаться прочитать теги вторично." + +#: optionseditor.cpp:387 +msgid "%1 Files" +msgstr "%1 файлов" + +#: optionseditor.cpp:402 +msgid "" +"You have selected multiple files with different conversion options.\n" +"You can change the options of all files by hitting the button below." +msgstr "" +"Вы выбрали несколько файлов с разными параметрами конвертации.\n" +"Вы можете изменить параметры для всех файлов нажав на кнопку ниже." + +#: optionseditor.cpp:408 +msgid "" +"Reading the tags of one or more files failed.\n" +"soundKonverter will try to read the tags a second time, when it is about to " +"convert the files.\n" +"If you want to edit the tags, you can hit the button below but then " +"soundKonverter will not try\n" +"to read the tags a second time." +msgstr "" +"Чтение тэгов одного или нескольких файлов закончено неуспешно.\n" +"soundKonverter попробует прочитать их вторично при конвертации файла(ов).\n" +"Если вы хотите редактировать тэги, вы можете нажать кнопку ниже, но\n" +"тогда soundKonverter не будет пытаться прочитать теги вторично." + +#: optionsrequester.cpp:18 +msgid "Choose output options" +msgstr "Выберите параметры вывода" + +#: optionsrequester.cpp:28 +msgid "Click on \"Ok\" to add the files to the list in the main window!" +msgstr "Нажмите \"ОК\" чтобы добавить файлы в список главного окна." + +#: optionsrequester.cpp:43 +msgid "" +"Warning: If you select \"wav\" as output format, your wav files will not be " +"added to the list." +msgstr "" +"Внимание: если вы выберите \"wav\" как формат вывода, ваши wav-файлы не " +"будут добавлены в список." + +#: optionsrequester.cpp:59 +msgid "Ok" +msgstr "OK" + +#: optionssimple.cpp:64 +msgid "Remove the selected profile" +msgstr "Удалить выбранный профиль" + +#: optionssimple.cpp:70 optionssimple.cpp:90 +msgid "Info" +msgstr "Сведения" + +#: optionssimple.cpp:71 +msgid "Information about the selected profile" +msgstr "Сведения о выбранном профиле" + +#: optionssimple.cpp:78 +msgid "Output format" +msgstr "Формат вывода" + +#: optionssimple.cpp:91 +msgid "Information about the selected file format" +msgstr "Сведения о выбранном формате" + +#: optionssimple.cpp:157 +msgid "" +"This produces sound files of a very low quality.\n" +"That can be useful, if you have a mobile device, where your memory cell is " +"limited. It is not recommended to save your music in this quality without a " +"copy with higher quality.\n" +"It can also be used to save audio files with voices." +msgstr "" +"Сохранить файлы в очень низком качестве.\n" +"Это может быть полезно, если у вас есть мобильное устройство с малым объемом " +"памяти.\n" +"Не рекомендуется сохранять музыку в этом качестве без сохранения копии в " +"высоком качестве.\n" +"Также низкое качество годно для сохранения записей голоса." + +#: optionssimple.cpp:158 optionssimple.cpp:163 optionssimple.cpp:168 +#: optionssimple.cpp:173 optionssimple.cpp:178 optionssimple.cpp:183 +#: optionssimple.cpp:188 optionssimple.cpp:193 +msgid "Profile" +msgstr "Профиль" + +#: optionssimple.cpp:162 +msgid "" +"This produces sound files of a low quality.\n" +"That can be useful if you habe a mobile device where your memory cell is " +"limited. It is not recommended to save your music in this quality without a " +"copy with higher quality." +msgstr "" +"Сохранить файлы в низком качестве.\n" +"Это может быть полезно, если у вас есть мобильное устройство с малым объемом " +"памяти.\n" +"Не рекомендуется сохранять музыку в этом качестве без сохранения копии в " +"высоком качестве." + +#: optionssimple.cpp:167 +msgid "" +"This produces sound files of a medium quality.\n" +"If your disc space is limited, you can use this to save your music." +msgstr "" +"Сохранить файлы в среднем качестве.\n" +"Если на вашем жестком диске мало свободного места, \n" +"вы можете использовать среднее качество для сохранения вашей музыки." + +#: optionssimple.cpp:172 +msgid "" +"This produces sound files of a high quality.\n" +"If you have enough disc space available, you can use this to save your music." +msgstr "" +"Сохранить файлы в высоком качестве.\n" +"Если на вашем жестком диске достаточно свободного места,\n" +"вы можете использовать высокое качество для сохранения вашей музыки." + +#: optionssimple.cpp:177 +msgid "" +"This produces sound files of a very high quality.\n" +"You should only use this, if you are a quality freak and have enough disc " +"space available." +msgstr "" +"Сохранить файлы в очень высоком качестве.\n" +"Вы можете использовать это качество, если... если вы настоящий фрик и " +"помешаны на качестве, а также у вас дохрена свободного места на диске =)" + +#: optionssimple.cpp:182 +msgid "" +"This produces files, that have exact the same quality as the input files.\n" +"This files are very big and definitely only for quality freaks." +msgstr "" +"Сохранить файлы в качестве входных файлов.\n" +"Эти файлы очень большие, определенно только для истинно помешанных на " +"качестве =)" + +#: optionssimple.cpp:187 +msgid "" +"This produces two files. One lossy compressed playable file and one " +"correction file.\n" +"Both files together result in a file that is equivalent to the input file." +msgstr "" +"Предоставляет два файла. Один с потерями, доступный для проигрывания, и один " +"коррекционный файл.\n" +"Два файла вместе дают в результате файл, идентичный входному файлу." + +#: optionssimple.cpp:192 +msgid "You can define your own profile in the \"detailed\" tab." +msgstr "" +"Вы можете определить свой собственный профиль во вкладке \"Эксперт\"." + +#: optionssimple.cpp:205 +msgid "Do you really want to remove the profile: %1" +msgstr "Вы действительно хотите удалить профиль: %1?" + +#: optionssimple.cpp:206 +msgid "Remove profile?" +msgstr "Удалить файл?" + +#: optionssimple.cpp:234 +msgid "" +"

Wave is a file format, that doesn't compress it's audio data.

\n" +"

So the quality is very high, but the file size is enormous. It is widely " +"spread and should work with every audio player.

\n" +"
http://en.wikipedia.org/wiki/Wav" +msgstr "" +"

Wave это формат файла, в котором аудио данные не сжимаются.

\n" +"

Качество таких файлов очень высоко, но их размер просто огромен. Формат " +"широко распространен и должен работать с каждым аудио плеером.

\n" +"
http://en.wikipedia.org/wiki/Wav" + +#: optionssimple.cpp:235 optionssimple.cpp:242 +msgid "File format" +msgstr "Формат файла" + +#: outputdirectory.cpp:44 +msgid "By meta data" +msgstr "По метаданным" + +#: outputdirectory.cpp:45 +msgid "Source directory" +msgstr "Исходный каталог" + +#: outputdirectory.cpp:46 +msgid "Specify output directory" +msgstr "Указать директорию вывода" + +#: outputdirectory.cpp:47 +msgid "Copy directory structure" +msgstr "Копировать структуру директории" + +#: outputdirectory.cpp:61 +msgid "Clear the directory input field" +msgstr "Очистить поле ввода директории" + +#: outputdirectory.cpp:81 outputdirectory.cpp:345 +msgid "Choose an output directory" +msgstr "Выбрать директорию вывода" + +#: outputdirectory.cpp:87 +msgid "Open Konqueror with the output directory" +msgstr "Открыть Konqueror в директории вывода" + +#: outputdirectory.cpp:184 +msgid "Unknown Artist" +msgstr "Неизвестный исполнитель" + +#: outputdirectory.cpp:188 +msgid "Unknown Album" +msgstr "Неизвестный альбом" + +#: outputdirectory.cpp:192 +msgid "No Comment" +msgstr "Нет комментария" + +#: outputdirectory.cpp:199 +msgid "Unknown Genre" +msgstr "Неизвестный жанр" + +#: outputdirectory.cpp:206 +msgid "Unknown Composer" +msgstr "Неизвестный композитор" + +#: outputdirectory.cpp:210 +msgid "Unknown Title" +msgstr "Неизвестный заголовок" + +#: outputdirectory.cpp:264 +msgid "new" +msgstr "создать" + +#: outputdirectory.cpp:406 +msgid "Name all converted files according to the specified pattern" +msgstr "Называть конечные файлы с учетом указанного шаблона" + +#: outputdirectory.cpp:408 +msgid "" +"

The following strings are wildcards, that will be replaced by the " +"information in the meta data:

%a - Artist
%b - Album
%c - " +"Comment
%d - Disc number
%g - Genre
%n - Track number
%p - " +"Composer
%t - Title
%y - Year
%f - Original file name

" +msgstr "" +"

Следующие строки являются переменными, которые будут заменены информацией " +"из тегов:

%a - Исполнитель
%b - Альбом
%c - Комментарий
%d - " +"Номер диска
%g - Жанр
%n - Номер дорожки
%p - Композитор
%t - " +"Заголовок
%y - Год
%f - Оригинальное имя файла

" + +#: outputdirectory.cpp:420 +msgid "" +"Output all converted files into the same directory as the original files" +msgstr "" +"Выводить все конвертированные файлы в директорию с оригинальными файлами" + +#: outputdirectory.cpp:434 +msgid "Output all converted files into the specified output directory" +msgstr "Выводить все конвертированные файлы в указанную директорию" + +#: outputdirectory.cpp:448 +msgid "Copy the whole directory structure for all converted files" +msgstr "Копировать всю структуру директорий для всех конвертированных файлов" + +#: paranoia.cpp:214 +msgid "MB" +msgstr "МБ" + +#: paranoia.cpp:215 +msgid "KB" +msgstr "КБ" + +#: paranoia.cpp:216 +msgid "Bytes" +msgstr "Байт" + +#: progressindicator.cpp:33 +msgid "Speed" +msgstr "Скорость" + +#: progressindicator.cpp:41 +msgid "Time remaining" +msgstr "Оставшееся время" + +#: progressindicator.cpp:95 progressindicator.cpp:96 replaygainscanner.cpp:216 +msgid "Finished" +msgstr "Завершено" + +#. i18n: file ./soundkonverterui.rc line 13 +#: rc.cpp:3 +#, no-c-format +msgid "&Conversion" +msgstr "&Конвертирование" + +#: replaygain.cpp:88 +msgid "Executing" +msgstr "Выполнение" + +#: replaygainfilelist.cpp:137 replaygainfilelist.cpp:147 +#: replaygainfilelist.cpp:150 replaygainfilelist.cpp:180 +#: replaygainfilelist.cpp:565 replaygainfilelist.cpp:669 +#: replaygainfilelist.cpp:672 replaygainfilelist.cpp:704 +#: replaygainfilelist.cpp:707 replaygainfilelist.cpp:734 +#: replaygainfilelist.cpp:737 replaygainfilelist.cpp:940 +msgid "Album" +msgstr "Альбом" + +#: replaygainfilelist.cpp:213 +msgid "Calculate Replay Gain tags" +msgstr "Высчитать тег Replay Gain" + +#: replaygainfilelist.cpp:214 +msgid "Remove Replay Gain tags" +msgstr "Удалить тег Replay Gain" + +#: replaygainfilelist.cpp:217 replaygainfilelist.cpp:825 +msgid "New album" +msgstr "Новый альбом" + +#: replaygainfilelist.cpp:218 +msgid "Open all albums" +msgstr "Открыть все альбомы" + +#: replaygainfilelist.cpp:219 +msgid "Cloase all albums" +msgstr "Закрыть все альбомы" + +#: replaygainfilelist.cpp:223 +msgid "" +"

Replay Gain Tool

With this tool you can add Replay " +"Gain tags to your audio files and remove them.
Replay Gain adds a volume " +"correction information to the files so that they can be played at an equal " +"volume level.
" +msgstr "" +"

Инструмент Replay Gain

С помощью этого инструмента " +"вы можете добавить или удалить теги Replay Gain в ваших аудио " +"файлах.
Replay Gain добавляет информацию о корректировании громкости, " +"чтобы они могли проигрываться на эквивалентной громкости.
" + +#: replaygainfilelist.cpp:494 +msgid "You can't place files of different formats in the same 'album'." +msgstr "Вы можете поместить файлы разных форматов в один 'альбом'." + +#: replaygainfilelist.cpp:494 +msgid "Different file formats" +msgstr "Различные форматы файлов" + +#: replaygainfilelist.cpp:987 +msgid "Removing Replay Gain" +msgstr "Удаление Replay Gain" + +#: replaygainfilelist.cpp:1148 +msgid "built-in" +msgstr "встроено" + +#: replaygainscanner.cpp:33 replaygainscanner.cpp:216 +#: replaygainscanner.cpp:231 +msgid "Replay Gain Tool" +msgstr "Инструмент Replay Gain" + +#: replaygainscanner.cpp:43 +msgid "Add Folder ..." +msgstr "Добавить директорию ..." + +#: replaygainscanner.cpp:44 +msgid "Add Files ..." +msgstr "Добавить файлы ..." + +#: replaygainscanner.cpp:52 +msgid "Force recalculation" +msgstr "Принудительное пересчитывание" + +#: replaygainscanner.cpp:53 +msgid "" +"Recalculate Replay Gain tag for files that already have a Replay Gain tag " +"set." +msgstr "Пересчитать тег Replay Gain для файлов, которые его уже имеют." + +#: replaygainscanner.cpp:102 +msgid "Tag untagged" +msgstr "Установить" + +#: replaygainscanner.cpp:103 +msgid "" +"Calculate Replay Gain tag for all files in the file list without Replay Gain " +"tag." +msgstr "" +"Просчитать тег Replay Gain для всех файлов в списке, которы его не имеют." + +#: replaygainscanner.cpp:109 +msgid "Untag tagged" +msgstr "Удалить" + +#: replaygainscanner.cpp:110 +msgid "Remove the Replay Gain tag from all files in the file list." +msgstr "Удалить тег Replay Gain из всех файлов в списке файлов." + +#: replaygainscanner.cpp:151 +msgid "Choose files!" +msgstr "Выберите файлы!" + +#: soundkonverter.cpp:107 +msgid "Choose your prefered output options and click on \"Add files ...\"!" +msgstr "Выберите необходимые опции и нажмите \"Добавить файлы ...\"!" + +#: soundkonverter.cpp:110 soundkonverter.cpp:405 soundkonverter.cpp:448 +msgid "&Start conversion" +msgstr "Зап&уск конвертирования" + +#: soundkonverter.cpp:112 +msgid "&Replay Gain Tool ..." +msgstr "&Инструмент Replay Gain ..." + +#: soundkonverter.cpp:114 +msgid "C&uesheet Editor ..." +msgstr "Р&едактор таблицы cue ..." + +#: soundkonverter.cpp:115 +msgid "Show &Log ..." +msgstr "П&оказать журнал ..." + +#: soundkonverter.cpp:118 +msgid "S&top after current file is complete" +msgstr "Ос&тановить после текущего файла" + +#: soundkonverter.cpp:119 +msgid "&Continue after current file is complete" +msgstr "П&родолжить после текущего файла" + +#: soundkonverter.cpp:120 +msgid "Stop &immediately" +msgstr "Остановить &немедленно" + +#: soundkonverter.cpp:148 +msgid "A&dd Files ..." +msgstr "&Добавить файлы ..." + +#: soundkonverter.cpp:149 +msgid "Add &Folder ..." +msgstr "Добавить д&иректорию ..." + +#: soundkonverter.cpp:150 +msgid "Add CD &tracks ..." +msgstr "Добавить &аудио дорожки ..." + +#: soundkonverter.cpp:151 +msgid "Add &URL ..." +msgstr "Добавить &URL ..." + +#: soundkonverter.cpp:154 +msgid "L&oad file list" +msgstr "За&грузить список файлов" + +#: soundkonverter.cpp:155 +msgid "Sa&ve file list" +msgstr "&Сохранить список файлов" + +#: soundkonverter.cpp:229 +msgid "Add files ..." +msgstr "Добавить файлы ..." + +#: soundkonverter.cpp:230 +msgid "Add folder ..." +msgstr "Добавить директорию ..." + +#: soundkonverter.cpp:231 +msgid "Add CD tracks ..." +msgstr "Добавить аудио дорожки ..." + +#: soundkonverter.cpp:232 +msgid "Add URL ..." +msgstr "Добавить URL ..." + +#: soundkonverter.cpp:240 +msgid "Start" +msgstr "Запуск" + +#: soundkonverter.cpp:417 +msgid "&Start queue" +msgstr "За&пуск очереди" + +#: soundkonverter.cpp:489 +msgid "Choose files to convert" +msgstr "Выберите файлы для конвертирования" + +#: soundkonverter.cpp:617 +msgid "Open URL" +msgstr "Открыть URL" + +#: soundkonverter.cpp:617 +msgid "Enter a URL:" +msgstr "Введите URL:" diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..c758fb3 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,58 @@ +# set the include path for X, qt and KDE +INCLUDES = $(all_includes) -I$(top_srcdir)/src/metadata/ \ + -I$(top_srcdir)/src/pluginloader/ + +# these are the headers for your project +noinst_HEADERS = cdmanager.h cdopener.h combobutton.h config.h \ + configbackendspage.h configdialog.h configenvironmentpage.h configgeneralpage.h \ + configpagebase.h configpluginspage.h conversionoptions.h convert.h cuesheeteditor.h \ + dcopinterface.h dirdialog.h filelist.h logger.h logviewer.h options.h optionsdetailed.h \ + optionseditor.h optionsrequester.h optionssimple.h outputdirectory.h \ + progressindicator.h replaygain.h replaygainfilelist.h replaygainscanner.h soundkonverter.h \ + soundkonverterapp.h + +# let automoc handle all of the meta source files (moc) +METASOURCES = AUTO + +messages: rc.cpp + $(EXTRACTRC) `find . -name \*.ui -o -name \*.rc` > rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/soundkonverter.pot + +KDE_ICON = AUTO + +######################################################################### +# APPLICATION SECTION +######################################################################### +# this is the program that gets installed. it's name is used for all +# of the other Makefile.am variables +bin_PROGRAMS = soundkonverter + +# the application source, library search path, and link libraries +soundkonverter_SOURCES = cddb.cpp cdmanager.cpp cdopener.cpp combobutton.cpp \ + config.cpp configbackendspage.cpp configdialog.cpp configenvironmentpage.cpp \ + configgeneralpage.cpp configpagebase.cpp configpluginspage.cpp conversionoptions.cpp \ + convert.cpp cuesheeteditor.cpp dcopinterface.skel dirdialog.cpp filelist.cpp \ + logger.cpp logviewer.cpp main.cpp options.cpp optionsdetailed.cpp \ + optionseditor.cpp optionsrequester.cpp optionssimple.cpp outputdirectory.cpp paranoia.cpp \ + progressindicator.cpp replaygain.cpp replaygainfilelist.cpp replaygainscanner.cpp \ + soundkonverter.cpp soundkonverterapp.cpp +soundkonverter_LDFLAGS = $(KDE_RPATH) $(all_libraries) +soundkonverter_LDADD = $(LIB_KDEUI) $(LIB_KFILE) metadata/libmetadata.la \ + pluginloader/libpluginloader.la -lcdda_interface -lcdda_paranoia + +xdg_apps_DATA = soundkonverter.desktop + +# this is where the shell's XML-GUI resource file goes +shellrcdir = $(kde_datadir)/soundkonverter +shellrc_DATA = soundkonverterui.rc + +SUBDIRS = amarokscript metadata pics pluginloader plugins +soundkonverter_DEPENDENCIES = metadata/libmetadata.la \ + pluginloader/libpluginloader.la +amarokscriptsdir = $(kde_datadir)/amarok/scripts +servicemenusdir = $(kde_datadir)/konqueror/servicemenus +servicemenus_DATA = audiocd_extract_with_soundkonverter.desktop +amarokscriptdir = $(kde_datadir)/soundkonverter/amarokscript +bin_SCRIPTS = userscript.sh +userscriptdir = $(kde_datadir)/soundkonverter +userscript_SCRIPTS = userscript.sh diff --git a/src/amarokscript/Makefile.am b/src/amarokscript/Makefile.am new file mode 100755 index 0000000..b8049a7 --- /dev/null +++ b/src/amarokscript/Makefile.am @@ -0,0 +1,3 @@ +amarokscriptdir = $(kde_datadir)/soundkonverter/amarokscript +amarokscript_DATA = README \ + soundKonverter.rb diff --git a/src/amarokscript/README b/src/amarokscript/README new file mode 100644 index 0000000..1186231 --- /dev/null +++ b/src/amarokscript/README @@ -0,0 +1,43 @@ +
soundKonverter amaroK-Script (v0.3.8)
+ +

+About:
+This script only adds a context menu for easily accesssing the soundKonverter tool.
This version was designed to work with soundKonverter 0.2.80+
With soundKonverter you can convert audio files into another audio format. And you can add/remove the ReplayGain tag to/from audio files. +

+ +

+Usage:
+Just run this script and click on one or multiple files in your playlist with the right mouse button. Select soundKonverter and your desired action. After that soundKonverter should start (if you have installed it). Look into the handbook of soundKonverter for further information. +

+ +

+Dependencies:
+

    +
  • amaroK 1.4.0
  • +
  • Ruby 1.6
  • +
  • soundKonverter 0.2.80+
  • +
+

+ +

+ChangeLog:
+Version 0.1:
+

    +
  • initial release
  • +
+Version 0.2.80:
+
    +
  • add: cd ripping menu
  • +
+

+ +

+License:
+GNU General Public License V2 +

+ +

+Author:
+Daniel Faust (daniel@kaligames.de) +

+ diff --git a/src/amarokscript/soundKonverter.rb b/src/amarokscript/soundKonverter.rb new file mode 100755 index 0000000..144c0c8 --- /dev/null +++ b/src/amarokscript/soundKonverter.rb @@ -0,0 +1,296 @@ +#!/usr/bin/env ruby +# +# amaroK-Script for integrating soundKonverter into amaroK +# +# (c) 2005 Daniel Faust +# License: GNU General Public License V2 + + +# FIXME after adding some files to soundkonverter, it is impossible to repeat that, until soundkonverter gets closed. + +# FIXME don't open files on every request. load options on startup and save on exit! + +#`dcop amarok playlist addMedia KURL` +#`dcop amarok playlist addMediaList KURL::List` +#`dcop amarok collection scanCollectionChanges` + + +require "uri" + +begin + require "Qt" +rescue LoadError + error = 'Qt Ruby bindings are required for this script.' + `dcop amarok playlist popupMessage "soundKonverter: #{error}"` + exit +end + +class MainWidget < Qt::Dialog + +slots 'accept()' + +def initialize(parent = nil, name = nil) + super + + box = Qt::VBoxLayout.new( self, 11, 6 ); + + lTitle = Qt::Label.new('soundKonverter plugin settings', self) + box.addWidget( lTitle ) + lTitle.setAlignment(Qt::AlignCenter) + font = Qt::Font.new() + font.setPixelSize(18) + font.setBold(true) + lTitle.setFont(font) + + box.addSpacing( 5 ) + + mediaDeviceBox = Qt::GroupBox.new( 1, Qt::Vertical, "Options for transfering to media devices", self ) + box.addWidget( mediaDeviceBox ) + mediaDeviceBox.layout().setSpacing( 6 ) + mediaDeviceBox.layout().setMargin( 6 ) + Qt::Label.new('Profile for lossy conversion:', mediaDeviceBox) + @cTranscodeProfile = Qt::ComboBox.new(mediaDeviceBox) + @cTranscodeProfile.insertItem("Very low") + @cTranscodeProfile.insertItem("Low") + @cTranscodeProfile.insertItem("Medium") + @cTranscodeProfile.insertItem("High") + @cTranscodeProfile.insertItem("Very high") + @cTranscodeProfile.setCurrentItem( 1 ) + +# box.addSpacing( 5 ) +# +# rippingBox = Qt::GroupBox.new( 2, Qt::Horizontal, "Use pre-defined options for CD ripping", self ) +# box.addWidget( rippingBox ) +# rippingBox.layout().setSpacing( 6 ) +# rippingBox.layout().setMargin( 6 ) +# rippingBox.setCheckable( true ) +# rippingBox.setEnabled( false ) +# +# profileBox = Qt::HBoxLayout.new( rippingBox, 6 ); +# lRippingProfile = Qt::Label.new('Profile:', rippingBox) +# profileBox.addWidget( lRippingProfile ) +# @cRippingProfile = Qt::ComboBox.new(rippingBox) +# profileBox.addWidget( @cRippingProfile ) +# @cRippingProfile.insertItem("Very low") +# @cRippingProfile.insertItem("Low") +# @cRippingProfile.insertItem("Medium") +# @cRippingProfile.insertItem("High") +# @cRippingProfile.insertItem("Very high") +# @cRippingProfile.insertItem("Lossless") +# @cRippingProfile.insertItem("Last used") +# @cRippingProfile.setCurrentItem(3) +# lRippingFormat = Qt::Label.new('Format:', rippingBox) +# profileBox.addWidget( lRippingFormat ) +# @cRippingFormat = Qt::ComboBox.new(rippingBox) +# profileBox.addWidget( @cRippingFormat ) +# @cRippingFormat.insertItem("ogg") +# @cRippingFormat.insertItem("mp3") +# @cRippingFormat.insertItem("flac") +# directoryBox = Qt::HBoxLayout.new( rippingBox, 6 ); +# lRippingDirectory = Qt::Label.new('Directory:', rippingBox) +# directoryBox.addWidget( lRippingDirectory ) +# @cRippingDirectory = Qt::ComboBox.new(rippingBox) +# directoryBox.addWidget( @cRippingDirectory ) +# @cRippingDirectory.setEditable(true) +# @cRippingDirectory.insertItem("/home/daniel/soundKonverter/%b/%d - %n - %t") +# @cRippingDirectory.insertItem("Last used") + + box.addSpacing( 5 ) + + buttonsBox = Qt::HBoxLayout.new(box) + buttonsBox.setSpacing(6) + buttonsBox.addStretch() + okPushButton = Qt::PushButton.new( self, "ok" ) + buttonsBox.addWidget( okPushButton ) + okPushButton.setText( "OK" ) + okPushButton.setDefault( true ) + + connect( okPushButton, SIGNAL( 'clicked()' ), + self, SLOT( 'accept()' ) + ) + + cancelPushButton = Qt::PushButton.new( self, "cancel" ) + buttonsBox.addWidget( cancelPushButton ) + cancelPushButton.setText( "Cancel" ) + cancelPushButton.setAccel( Qt::KeySequence.new(Key_Escape) ) + + connect( cancelPushButton, SIGNAL( 'clicked()' ), + self, SLOT( 'reject()' ) + ) + + file = Qt::File.new( File.dirname( File.expand_path( __FILE__ ) ) + "/config" ) + if file.open( Qt::IO_ReadOnly ) + ts = Qt::TextStream.new( file ) + content = '' + ts >> content + if content == 'Very_low' + @cTranscodeProfile.setCurrentItem( 0 ) + elsif content == 'Low' + @cTranscodeProfile.setCurrentItem( 1 ) + elsif content == 'Medium' + @cTranscodeProfile.setCurrentItem( 2 ) + elsif content == 'High' + @cTranscodeProfile.setCurrentItem( 3 ) + elsif content == 'Very_high' + @cTranscodeProfile.setCurrentItem( 4 ) + end + file.close() + end + +# file = Qt::File.new( File.dirname( File.expand_path( __FILE__ ) ) + "/profiles" ) +# if file.open( Qt::IO_ReadOnly ) +# ts = Qt::TextStream.new( file ) +# while !ts.eof() +# content = '' +# ts >> content +# @cProfile.insertItem( content ) +# ts >> content +# end +# +# file.close() +# end +end + + +def accept() + file = Qt::File.new( File.dirname( File.expand_path( __FILE__ ) ) + "/config" ) + if file.open( Qt::IO_WriteOnly ) + ts = Qt::TextStream.new( file ) + if @cTranscodeProfile.currentText() == 'Very low' + content = 'Very_low' + elsif @cTranscodeProfile.currentText() == 'Low' + content = 'Low' + elsif @cTranscodeProfile.currentText() == 'Medium' + content = 'Medium' + elsif @cTranscodeProfile.currentText() == 'High' + content = 'High' + elsif @cTranscodeProfile.currentText() == 'Very high' + content = 'Very_high' + end + ts << content + "\n" + file.close() + end + + super +end + +end + + +MenuItemName1 = "soundKonverter \"Convert selected files\"" +MenuItemName2 = "soundKonverter \"Add Replay Gain to selected files\"" +MenuItemName3 = "soundKonverter \"Rip and play audio CD\"" + + +def cleanup() + `dcop amarok script removeCustomMenuItem #{MenuItemName1}` + `dcop amarok script removeCustomMenuItem #{MenuItemName2}` + `dcop amarok script removeCustomMenuItem #{MenuItemName3}` +end + + +trap( "SIGTERM" ) { cleanup() } + +`dcop amarok script addCustomMenuItem #{MenuItemName1}` +`dcop amarok script addCustomMenuItem #{MenuItemName2}` +`dcop amarok script addCustomMenuItem #{MenuItemName3}` + +loop do + message = gets().chomp() + command = /[A-Za-z]*/.match( message ).to_s() + + case command + when "configure" + app = Qt::Application.new(ARGV) + widget = MainWidget.new + app.setMainWidget(widget) + widget.show() + app.exec() + + when "transcode" + args = message.split() + filename = args[1] + #uri = URI.parse( args[1] ) + #filename = URI.unescape( uri.path() ) + filetype = args[2] + profile = '' + + file = Qt::File.new( File.dirname( File.expand_path( __FILE__ ) ) + "/formats" ) + if file.open( Qt::IO_ReadOnly ) + ts = Qt::TextStream.new( file ) + while !ts.eof() + mode = '' + formats = '' + ts >> mode + ts >> formats + if formats.split(',').include?( filetype ) + profile = mode + end + end + file.close() + end + + if profile == '' + file = Qt::File.new( File.dirname( File.expand_path( __FILE__ ) ) + "/config" ) + if file.open( Qt::IO_ReadOnly ) + ts = Qt::TextStream.new( file ) + content = '' + ts >> content + if content == 'Very_low' + profile = 'Very low' + elsif content == 'Low' + profile = 'Low' + elsif content == 'Medium' + profile = 'Medium' + elsif content == 'High' + profile = 'High' + elsif content == 'Very_high' + profile = 'Very high' + end + file.close() + else + profile = 'Low' + end + end + + `dcop amarok playlist shortStatusMessage "starting soundKonverter in background"` + `soundkonverter --invisible --profile '#{profile}' --format '#{filetype}' --output '/tmp' --command "dcop amarok mediabrowser transcodingFinished %u file://%o" '#{filename}'` + + when "customMenuClicked" + if message.include?( "Convert selected files" ) + args = message.split() + # Remove the command args + 5.times() { args.delete_at( 0 ) } + + # Iterate over all selected files + files = '' + args.each() do |arg| + uri = URI.parse( arg ) + file = URI.unescape( uri.path() ) + files += ' "'+file+'"' + end + `dcop amarok playlist shortStatusMessage "starting soundKonverter"` + `soundkonverter #{files}` + end + if message.include?( "Add Replay Gain to selected files" ) + args = message.split() + # Remove the command args + 8.times() { args.delete_at( 0 ) } + + files = '' + args.each() do |arg| + uri = URI.parse( arg ) + file = URI.unescape( uri.path() ) + files += ' "'+file+'"' + end + `dcop amarok playlist shortStatusMessage "starting soundKonverter"` + `soundkonverter --replaygain #{files}` + end + if message.include?( "Rip and play audio CD" ) + `dcop amarok playlist popupMessage "Select all tracks to rip and press 'Start' in order to start ripping.\nThe tracks will be added to the playlist, when they are ready."` + #`dcop amarok playlist shortStatusMessage "starting soundKonverter"` + `soundkonverter --invisible --rip auto --command "dcop amarok playlist addMedia %o"` + end + end +end + diff --git a/src/audiocd_extract_with_soundkonverter.desktop b/src/audiocd_extract_with_soundkonverter.desktop new file mode 100755 index 0000000..a6d4120 --- /dev/null +++ b/src/audiocd_extract_with_soundkonverter.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Actions=ExtractSoundKonverter +ServiceTypes=media/audiocd +Icon=soundkonverter +X-KDE-Priority=TopLevel + +[Desktop Action ExtractSoundKonverter] +Exec=soundkonverter --rip %u +Icon=soundkonverter +Name=Extract with soundKonverter +Name[de]=Mit soundKonverter auslesen diff --git a/src/cddb.cpp b/src/cddb.cpp new file mode 100755 index 0000000..58ebde7 --- /dev/null +++ b/src/cddb.cpp @@ -0,0 +1,669 @@ +/* + Copyright (C) 2000 Michael Matz + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#ifdef HAVE_SYS_TIME_H +#include +#endif +#include +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_SYS_SELECT_H +#include +#endif +#include +#include +#include +#include +#include +//#include +#include +// #include +//#include +#include +#include +#include +#include + +#include "cddb.h" +#include "cddb.moc" + +// FIXME //kdDebug + +CDDB::CDDB() + : ks(0), port(80), remote(false), save_local(false) +{ + QString s = QDir::homeDirPath()+"/.cddb"; + cddb_dirs +=s; +} + + + +CDDB::~CDDB() +{ + deinit(); +} + + + +bool +CDDB::set_server(const char *hostname, unsigned short int _port) +{ + if (ks) + { + if (h_name == hostname && port == _port) + return true; + deinit(); + } + remote = (hostname != 0) && (*hostname != 0); + //kdDebug(7101) << "CDDB: set_server, host=" << hostname << "port=" << _port << endl; + if (remote) + { + ks = new KExtendedSocket(hostname, _port); + if (ks->connect() < 0) + { + //kdDebug(7101) << "CDDB: Can't connect!" << endl; + delete ks; + ks = 0; + return false; + } + + h_name = hostname; + port = _port; + QCString r; + readLine(r); // the server greeting + writeLine("cddb hello kde-user blubb kio_audiocd 0.4"); + readLine(r); + } + return true; +} + + + +bool +CDDB::deinit() +{ + if (ks) + { + writeLine("quit"); + QCString r; + readLine(r); + ks->close(); + } + h_name.resize(0); + port = 0; + remote = false; + ks = 0; + return true; +} + + + +bool +CDDB::readLine(QCString& ret) +{ + int read_length = 0; + char small_b[128]; + //fd_set set; + + ret.resize(0); + while (read_length < 40000) + { + // Look for a \n in buf + int ni = buf.find('\n'); + if (ni >= 0) + { + // Nice, so return this substring (without the \n), + // and truncate buf accordingly + ret = buf.left(ni); + if (ret.length() && ret[ret.length()-1] == '\r') + ret.resize(ret.length()); + buf.remove(0, ni+1); + //kdDebug(7101) << "CDDB: got `" << ret << "'" << endl; + return true; + } + + // Try to refill the buffer + ks->waitForMore(60 * 1000); + ssize_t l = ks->readBlock(small_b, sizeof(small_b)-1); + if (l <= 0) + { + // l==0 normally means fd got closed, but we really need a lineend + return false; + } + small_b[l] = 0; + read_length += l; + buf += small_b; + } + return false; +} + + + +bool +CDDB::writeLine(const QCString& line) +{ + const char *b = line.data(); + int l = line.length(); + //kdDebug(7101) << "CDDB: send `" << line << "'" << endl; + while (l) + { + ssize_t wl = ks->writeBlock(b, l); + if (wl < 0 && errno != EINTR) + return false; + if (wl < 0) + wl = 0; + l -= wl; + b += wl; + } + l = line.length(); + if (l && line.data()[l-1] != '\n') + { + char c = '\n'; + ssize_t wl; + do { + wl = ks->writeBlock(&c, 1); + } while (wl <= 0 && errno == EINTR); + if (wl<=0 && errno != EINTR) + return false; + } + return true; +} + + + +unsigned int +CDDB::get_discid(QValueList& track_ofs) +{ + unsigned int id = 0; + int num_tracks = track_ofs.count() - 2; + + // the last two track_ofs[] are disc begin and disc end + + for (int i = num_tracks - 1; i >= 0; i--) + { + int n = track_ofs[i]; + n /= 75; + while (n > 0) + { + id += n % 10; + n /= 10; + } + } + unsigned int l = track_ofs[num_tracks + 1]; + l -= track_ofs[num_tracks]; + l /= 75; + id = ((id % 255) << 24) | (l << 8) | num_tracks; + return id; +} + + + +static int +get_code (const QCString &s) +{ + bool ok; + int code = s.left(3).toInt(&ok); + if (!ok) + code = -1; + return code; +} + + + +static void +parse_query_resp (const QCString& _r, QCString& catg, QCString& d_id, QCString& title) +{ + QCString r = _r.stripWhiteSpace(); + int i = r.find(' '); + if (i) + { + catg = r.left(i).stripWhiteSpace(); + r.remove(0, i+1); + r = r.stripWhiteSpace(); + } + i = r.find(' '); + if (i) + { + d_id = r.left(i).stripWhiteSpace(); + r.remove(0, i+1); + r = r.stripWhiteSpace(); + } + title = r; +} + + + +QString +CDDB::track(int i) const +{ + if (i < 0 || i >= int(m_names.count())) + return QString(); + return m_names[i].utf8(); +} + + + + +QString +CDDB::artist(int i) const +{ + if (i < 0 || i >= int(m_artists.count())) + return QString(); + return m_artists[i].utf8(); +} + + + +bool +CDDB::parse_read_resp(QTextStream *stream, QTextStream *write_stream) +{ + /* Note, that m_names and m_title should be empty */ + QCString end = "."; + + m_disc = 0; + m_year = 0; + m_genre = ""; + + /* Fill table, so we can index it below. */ + for (int i = 0; i < m_tracks; i++) + { + m_names.append(""); + m_artists.append(""); + } + while (1) + { + QCString r; + if (stream) + { + if (stream->atEnd()) + break; + r = stream->readLine().latin1(); + } + else + { + if (!readLine(r)) + return false; + } + /* Normally the "." is not saved into the local files, but be + tolerant about this. */ + if (r == end) + break; + if (write_stream) + *write_stream << r << endl; + r = r.stripWhiteSpace(); + if (r.isEmpty() || r[0] == '#') + continue; + if (r.left(7) == "DTITLE=") + { + r.remove(0, 7); + m_title += QString::fromLocal8Bit(r.stripWhiteSpace()); + } + else if (r.left(6) == "TTITLE") + { + r.remove(0, 6); + int e = r.find('='); + if (e) + { + bool ok; + int i = r.left(e).toInt(&ok); + if (ok && i >= 0 && i < m_tracks) + { + r.remove(0, e+1); + m_names[i] += QString::fromLocal8Bit(r); + } + } + } + else if (r.left(6) == "DYEAR=") + { + r.remove(0, 6); + QString year = QString::fromLocal8Bit(r.stripWhiteSpace()); + m_year = year.toInt(); + //kdDebug(7101) << "CDDB: found Year: " << QString().sprintf("%04i",m_year) << endl; + } + else if (r.left(7) == "DGENRE=") + { + r.remove(0, 7); + m_genre = QString::fromLocal8Bit(r.stripWhiteSpace()); + //kdDebug(7101) << "CDDB: found Genre: " << m_genre << endl; + } + } + + /* XXX We should canonicalize the strings ("\n" --> '\n' e.g.) */ + + int si = m_title.find(" / "); + if (si > 0) + { + m_artist = m_title.left(si).stripWhiteSpace(); + m_title.remove(0, si+3); + m_title = m_title.stripWhiteSpace(); + } + + si = m_title.find(" - CD"); + if (si > 0) + { + QString disc = m_title.right(m_title.length()-(si+5)).stripWhiteSpace(); + m_disc = disc.toInt(); + //kdDebug(7101) << "CDDB: found Disc: " << disc << endl; + m_title = m_title.left(si).stripWhiteSpace(); + } + + if (m_title.isEmpty()) + m_title = i18n("No Title"); + /*else + m_title.replace(QRegExp("/"), "%2f");*/ + if (m_artist.isEmpty()) + m_artist = i18n("Unknown"); + /*else + m_artist.replace(QRegExp("/"), "%2f");*/ + + //kdDebug(7101) << "CDDB: found Title: `" << m_title << "'" << endl; + for (int i = 0; i < m_tracks; i++) + { + if (m_names[i].isEmpty()) + m_names[i] += i18n("Track %1").arg(i); + //m_names[i].replace(QRegExp("/"), "%2f"); + si = m_names[i].find(" - "); + if (si < 0) + { + si = m_names[i].find(" / "); + } + if (si > 0) + { + m_artists[i] = m_names[i].left(si).stripWhiteSpace(); + m_names[i].remove(0, si+3); + m_names[i] = m_names[i].stripWhiteSpace(); + } + else + { + m_artists[i] = m_artist; + } + //kdDebug(7101) << "CDDB: found Track " << i+1 << ": `" << m_names[i] << "'" << endl; + } + return true; +} + + + +void +CDDB::add_cddb_dirs(const QStringList& list) +{ + QString s = QDir::homeDirPath()+"/.cddb"; + + cddb_dirs = list; + if (cddb_dirs.isEmpty()) + cddb_dirs += s; +} + + + +/* Locates and opens the local file corresponding to that discid. + Returns TRUE, if file is found and ready for reading. + Returns FALSE, if file isn't found. In this case ret_file is initialized + with a QFile which resides in the first cddb_dir, and has a temp name + (the ID + getpid()). You can open it for writing. */ +bool +CDDB::searchLocal(unsigned int id, QFile *ret_file) +{ + QDir dir; + QString filename; + filename = QString("%1").arg(id, 0, 16).rightJustify(8, '0'); + QStringList::ConstIterator it; + for (it = cddb_dirs.begin(); it != cddb_dirs.end(); ++it) + { + dir.setPath(*it); + if (!dir.exists()) + continue; + /* First look in dir directly. */ + ret_file->setName (*it + "/" + filename); + if (ret_file->exists() && ret_file->open(IO_ReadOnly)) + return true; + /* And then in the subdirs of dir (representing the categories normally). + */ + const QFileInfoList *subdirs = dir.entryInfoList (QDir::Dirs); + QFileInfoListIterator fiit(*subdirs); + QFileInfo *fi; + while ((fi = fiit.current()) != 0) + { + ret_file->setName (*it + "/" + fi->fileName() + "/" + filename); + if (ret_file->exists() && ret_file->open(IO_ReadOnly)) + return true; + ++fiit; + } + } + QString pid; + pid.setNum(::getpid()); + ret_file->setName (cddb_dirs[0] + "/" + filename + "." + pid); + /* Try to create the save location. */ + dir.setPath(cddb_dirs[0]); + if (save_local && !dir.exists()) + { + //dir = QDir::current(); + dir.mkdir(cddb_dirs[0]); + } + return false; +} + + + +bool +CDDB::queryCD(QValueList& track_ofs) +{ + int num_tracks = track_ofs.count() - 2; + if (num_tracks < 1) + return false; + unsigned int id = get_discid(track_ofs); + QFile file; + bool local; + + /* Already read this ID. */ + if (id == m_discid) + return true; + + emit cddbMessage(i18n("Searching local cddb entry ...")); + qApp->processEvents(); + + /* First look for a local file. */ + local = searchLocal (id, &file); + /* If we have no local file, and no remote connection, barf. */ + if (!local && (!remote || ks == 0)) + return false; + + m_tracks = num_tracks; + m_title = ""; + m_artist = ""; + m_names.clear(); + m_discid = id; + if (local) + { + QTextStream stream(&file); + /* XXX Hmm, what encoding is used by CDDB files? local? Unicode? + Nothing? */ + //stream.setEncoding(QTextStream::Locale); + parse_read_resp(&stream, 0); + file.close(); + return true; + } + + emit cddbMessage(i18n("Searching remote cddb entry ...")); + qApp->processEvents(); + + /* Remote CDDB query. */ + unsigned int length = track_ofs[num_tracks+1] - track_ofs[num_tracks]; + QCString q; + q.sprintf("cddb query %08x %d", id, num_tracks); + QCString num; + for (int i = 0; i < num_tracks; i++) + q += " " + num.setNum(track_ofs[i]); + q += " " + num.setNum(length / 75); + if (!writeLine(q)) + return false; + QCString r; + if (!readLine(r)) + return false; + r = r.stripWhiteSpace(); + int code = get_code(r); + if (code == 200) + { + QCString catg, d_id, title; + QDir dir; + QCString s, pid; + + emit cddbMessage(i18n("Found exact match cddb entry ...")); + qApp->processEvents(); + + /* an exact match */ + r.remove(0, 3); + parse_query_resp(r, catg, d_id, title); + //kdDebug(7101) << "CDDB: found exact CD: category=" << catg << " DiscId=" << d_id << " Title=`" << title << "'" << endl; + q = "cddb read " + catg + " " + d_id; + if (!writeLine(q)) + return false; + if (!readLine(r)) + return false; + r = r.stripWhiteSpace(); + code = get_code(r); + if (code != 210) + return false; + + pid.setNum(::getpid()); + s = cddb_dirs[0].latin1(); + //s = s + "/" +catg; // xine seems to not search in local subdirs + dir.setPath( s ); + if ( !dir.exists() ) dir.mkdir( s ); + s = s+"/"+ d_id; + file.setName( s ); + + if (save_local && file.open(IO_WriteOnly)) + { + //kdDebug(7101) << "CDDB: file name to save =" << file.name() << endl; + QTextStream stream(&file); + if (!parse_read_resp(0, &stream)) + { + file.remove(); + return false; + } + file.close(); + /*QString newname (file.name()); + newname.truncate(newname.findRev('.')); + if (QDir::current().rename(file.name(), newname)) { + //kdDebug(7101) << "CDDB: rename failed" << endl; + file.remove(); + } */ + } + else if (!parse_read_resp(0, 0)) + return false; + } + else if (code == 211) + { + // Found some close matches. We'll read the query response and ask the user + // which one should be fetched from the server. + QCString end = "."; + QCString catg, d_id, title; + QDir dir; + QCString s, pid, first_match; + QStringList disc_ids; + + /* some close matches */ + //XXX may be try to find marker based on r + emit cddbMessage(i18n("Found close cddb entry ...")); + qApp->processEvents(); + + int i=0; + while (1) + { + if (!readLine(r)) + return false; + r = r.stripWhiteSpace(); + if (r == end) + break; + disc_ids.append(r); + if (i == 0) + first_match = r; + i++; + } + + bool ok = false; + + // We don't want to be thinking too much, do we? +// QApplication::restoreOverrideCursor(); + + // Oh, mylord, which match should I serve you? + QString _answer = KInputDialog::getItem(i18n("CDDB Matches"), i18n("Several close CDDB entries found. Choose one:"), + disc_ids, 0, false, &ok ); + QCString answer = _answer.utf8(); + + if (ok){ // Get user selected match + parse_query_resp(answer, catg, d_id, title); + } + else{ // Get first match + parse_query_resp(first_match, catg, d_id, title); + } + + // Now we can continue thinking... +// QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) ); + + /*kdDebug(7101) << "CDDB: found close CD: category=" << catg << " DiscId=" + << d_id << " Title=`" << title << "'" << endl;*/ + + // ... and forth we go as usual + + q = "cddb read " + catg + " " + d_id; + if (!writeLine(q)) + return false; + if (!readLine(r)) + return false; + r = r.stripWhiteSpace(); + code = get_code(r); + if (code != 210) + return false; + + pid.setNum(::getpid()); + s = cddb_dirs[0].latin1(); + dir.setPath( s ); + if ( !dir.exists() ) dir.mkdir( s ); + s = s+"/"+ d_id; + file.setName( s ); + + if (save_local && file.open(IO_WriteOnly)) + { + //kdDebug(7101) << "CDDB: file name to save =" << file.name() << endl; + QTextStream stream(&file); + if (!parse_read_resp(0, &stream)) + { + file.remove(); + return false; + } + file.close(); + } + else if (!parse_read_resp(0, 0)) + return false; + + } + else + { + /* 202 - no match found + 403 - Database entry corrupt + 409 - no handshake */ + //kdDebug(7101) << "CDDB: query returned code " << code << endl; + return false; + } + + return true; +} diff --git a/src/cddb.h b/src/cddb.h new file mode 100755 index 0000000..62c38a7 --- /dev/null +++ b/src/cddb.h @@ -0,0 +1,79 @@ +/* + Copyright (C) 2000 Michael Matz + Modified 2006 Daniel Faust , thx Michael + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef CDDB_H +#define CDDB_H + +#include +#include +#include +#include + +class QFile; +class QTextStream; +class KExtendedSocket; + +class CDDB : public QObject +{ + Q_OBJECT +public: + CDDB(); + ~CDDB(); + bool set_server(const char *hostname = 0, unsigned short int port = 0); + void add_cddb_dirs(const QStringList& list); + void save_cddb (bool save) { save_local = save; } + unsigned int get_discid(QValueList& track_ofs); + bool queryCD(QValueList& track_ofs); + QString title() const { return m_title.utf8(); } + QString artist(int i) const; + int trackCount() const { return m_tracks; } + QString track(int i) const; + int disc() const { return m_disc; } + QString genre() const { return m_genre.utf8(); } + int year() const { return m_year; } + +private: + bool readLine(QCString& s); + bool writeLine(const QCString& s); + bool deinit(); + bool parse_read_resp(QTextStream*, QTextStream*); + bool searchLocal(unsigned int id, QFile *ret_file); + KExtendedSocket *ks; + QCString h_name; + unsigned short int port; + bool remote; + bool save_local; + QStringList cddb_dirs; + QCString buf; + unsigned int m_discid; + + int m_tracks; + int m_disc; + int m_year; + QString m_genre; + QString m_title; + QString m_artist; + QStringList m_artists; + QStringList m_names; + +signals: + void cddbMessage( QString ); +}; + +#endif // CDDB_H diff --git a/src/cdmanager.cpp b/src/cdmanager.cpp new file mode 100755 index 0000000..cd9dd27 --- /dev/null +++ b/src/cdmanager.cpp @@ -0,0 +1,190 @@ + +#include "cdmanager.h" +#include "paranoia.h" +#include "cddb.h" +#include "conversionoptions.h" + +#include +#include + +#include +#include +#include +#include + + +// ### soundkonverter 0.4 implement reading of milliseconds/frames + +// TODO implement reading of cd data + +CDDevice::CDDevice( const QString& _device ) +{ + QStringList s; + bool init = false; + QValueList qvl; + int i; + QStringList dcopList, devList; + bool ok = false; + + tags.clear(); + + if( !_device.isEmpty() ) + s.append( _device ); + else { + DCOPRef mediamanager( "kded", "mediamanager" ); + DCOPReply reply = mediamanager.call( "fullList()" ); + if( reply.isValid() ) { + dcopList = reply; + i = 0; + while( i < (int)dcopList.count() ) { + if( dcopList[i+10] == "media/audiocd" ) { + devList.append( dcopList[i+5] ); + } + i += 13; + } + if( devList.count() > 1 ) { + QString choice = KInputDialog::getItem( i18n("Audio CD"), i18n("Several audio CDs found. Choose one:"), devList, 0, false, &ok ); + if( ok ) s.append( choice ); + else s.append( 0 ); // TODO if canceled, the cd opener should close, not use the first item + } + else if( devList.count()==1 ) { + s.append( devList[0] ); + } + else { + s.append( "/dev/cdrom" ); + s.append( "/dev/dvd" ); + } + } + else { + s.append( "/dev/cdrom" ); + s.append( "/dev/dvd" ); + } + } + + para = new Paranoia(); + for( i = 0; i < (int)s.count(); i++ ) { + if( init = para->init(s[i]) ) { + device = s[i]; + break; + } + } + if( init ) { + trackCount = para->getTracks(); + timeCount = para->trackTime( -1 ); + for( i = 0; i < para->getTracks(); i++) { + qvl.append( para->trackFirstSector(i+1) + 150 ); + } + qvl.append( para->discFirstSector() ); + qvl.append( para->discLastSector() ); + CDDB* cddb = new CDDB(); + cddb->save_cddb( true ); + if( cddb->queryCD(qvl) ) { + for( i = 0; i < para->getTracks(); i++ ) { + tags += new TagData( cddb->artist(i), "", cddb->title(), cddb->track(i), cddb->genre(), "", + i+1, cddb->disc(), cddb->year(), para->trackTime(i) ); + } + } + else { + cddb->set_server( "freedb.freedb.org", 8880 ); + if( cddb->queryCD(qvl) ) { + for( i = 0; i < para->getTracks(); i++ ) { + tags += new TagData( cddb->artist(i), "", cddb->title(), cddb->track(i), cddb->genre(), "", + i+1, cddb->disc(), cddb->year(), para->trackTime(i) ); + } + } + else { + for( i = 0; i < para->getTracks(); i++ ) { + tags += new TagData( i18n("Unknown"), "", i18n("Unknown"), i18n("Unknown"), "", "", i+1, 1, 0, para->trackTime(i) ); + } + } + } + delete cddb; + } + else { + KMessageBox::information( 0, i18n("No audio CD found."), i18n("Warning") ); + device = ""; + delete para; + para = 0; + } +} + +CDDevice::~CDDevice() +{} + + +CDManager::CDManager() +{} + +CDManager::~CDManager() +{ + while( cdDevices.count() > 0 ) delete cdDevices.first(); +} + +QString CDManager::newCDDevice( const QString& device ) +{ + CDDevice* cdDevice = new CDDevice( device ); + + for( QValueList::Iterator it = cdDevices.begin(); it != cdDevices.end(); ++it ) { + if( (*it)->device = cdDevice->device ) { + cdDevices.remove( *it ); + delete (*it); + break; + } + } + + cdDevices += cdDevice; + return cdDevice->device; +} + +QValueList CDManager::getTrackList( const QString& device ) +{ + for( QValueList::Iterator it = cdDevices.begin(); it != cdDevices.end(); ++it ) { + if( (*it)->device = device ) return (*it)->tags; + } + + QValueList list; + return list; +} + +TagData* CDManager::getTags( const QString& device, int track ) +{ + for( QValueList::Iterator it = cdDevices.begin(); it != cdDevices.end(); ++it ) { + if( (*it)->device = device ) { + if( track > 0 ) { + QValueList::Iterator tag = (*it)->tags.at( track - 1 ); + return (*tag); + } + else { + return (*it)->discTags; + } + } + } + + return 0; +} + +int CDManager::getTrackCount( const QString& device ) +{ + for( QValueList::Iterator it = cdDevices.begin(); it != cdDevices.end(); ++it ) { + if( (*it)->device = device ) return (*it)->trackCount; + } + + return 0; +} + +int CDManager::getTimeCount( const QString& device ) +{ + for( QValueList::Iterator it = cdDevices.begin(); it != cdDevices.end(); ++it ) { + if( (*it)->device = device ) return (*it)->timeCount; + } + + return 0; +} + +void CDManager::setDiscTags( const QString& device, TagData* tags ) +{ + for( QValueList::Iterator it = cdDevices.begin(); it != cdDevices.end(); ++it ) { + if( (*it)->device = device ) (*it)->discTags = tags; + } +} + diff --git a/src/cdmanager.h b/src/cdmanager.h new file mode 100755 index 0000000..9af80c8 --- /dev/null +++ b/src/cdmanager.h @@ -0,0 +1,95 @@ + + +#ifndef CDMANAGER_H +#define CDMANAGER_H + +#include "tagengine.h" + +#include + +class ConversionOptions; +class Paranoia; + +/** + * @short All data needed for a cd device + * @author Daniel Faust + * @version 0.3 + */ +class CDDevice +{ +public: + /** + * Constructor + */ + CDDevice( const QString& _device="" ); + + /** + * Destructor + */ + virtual ~CDDevice(); + + QString device; + Paranoia* para; + QValueList tags; + TagData* discTags; + int trackCount; + int timeCount; +}; + +/** + * @short The CD manager + * @author Daniel Faust + * @version 0.3 + */ +class CDManager : public QObject +{ + Q_OBJECT +public: + /** + * Constructor + */ + CDManager(); + + /** + * Destructor + */ + virtual ~CDManager(); + + /** + * Create a new CDDevice entry in cdDevices. Use @param device or auto search for an audio cd + * Return the used device (usefull, if auto searching was used) + */ + QString newCDDevice( const QString& device="" ); + + /** + * Return a list of all tracks on the cd in drive @param device + */ + QValueList getTrackList( const QString& device ); + + /** + * Return the tags of the track @param track on the cd in drive @param device + */ + TagData* getTags( const QString& device, int track ); + + /** + * Set the tags of the cd in drive @param device + */ + void setDiscTags( const QString& device, TagData* tags ); + + /** + * Return the sum of all tracks of the cd in drive @param device + */ + int getTrackCount( const QString& device ); + + /** + * Return the complete length of the cd in drive @param device + */ + int getTimeCount( const QString& device ); + +private: + /** a list of all devices */ + QValueList cdDevices; + +}; + +#endif // CDMANAGER_H diff --git a/src/cdopener.cpp b/src/cdopener.cpp new file mode 100755 index 0000000..acabbc8 --- /dev/null +++ b/src/cdopener.cpp @@ -0,0 +1,781 @@ + +#include "cdopener.h" +#include "cdmanager.h" +#include "tagengine.h" +#include "config.h" +#include "ripperpluginloader.h" +#include "combobutton.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +// ### soundkonverter 0.4: implement cd info text + +CDOpener::CDOpener( Config* _config, CDManager* _cdManager, TagEngine* _tagEngine, const QString& _device, QWidget* parent, const char* name, /*Mode default_mode, const QString& default_text,*/ bool modal, WFlags f ) + : KDialog( parent, name, modal, f ) +{ + cdManager = _cdManager; + tagEngine = _tagEngine; + config = _config; + + // create an icon loader object for loading icons + KIconLoader* iconLoader = new KIconLoader(); + + // let the dialog look nice + setCaption( i18n("Add CD tracks") ); + setIcon( iconLoader->loadIcon("cdaudio_unmount",KIcon::Small) ); + + // the grid for all widgets in the dialog + QGridLayout* gridLayout = new QGridLayout( this, 1, 1, 11, 6, "gridLayout" ); + + // the grid for the artist and album input + QGridLayout* topGridLayout = new QGridLayout( this, 1, 1, 0, 6, "topGridLayout" ); + gridLayout->addLayout( topGridLayout, 0, 0 ); + + // set up the first row at the top + QLabel* lArtistLabel = new QLabel( i18n("Artist:"), this, "lArtistLabel" ); + topGridLayout->addWidget( lArtistLabel, 0, 0 ); + cArtist = new KComboBox( true, this, "cArtist" ); + topGridLayout->addWidget( cArtist, 0, 1 ); + cArtist->setMinimumWidth( 200 ); + cArtist->insertItem( i18n("Various Artists") ); + cArtist->setCurrentText( "" ); + connect( cArtist, SIGNAL(textChanged(const QString&)), + this, SLOT(artistChanged(const QString&)) + ); + // add a horizontal box layout for the composer + QHBoxLayout* artistBox = new QHBoxLayout( -1, "artistBox" ); + topGridLayout->addLayout( artistBox, 0, 3 ); + // and fill it up + QLabel* lComposerLabel = new QLabel( i18n("Composer:"), this, "lComposerLabel" ); + lComposerLabel->setAlignment( Qt::AlignRight | Qt::AlignVCenter ); + topGridLayout->addWidget( lComposerLabel, 0, 2 ); + cComposer = new KComboBox( true, this, "cComposer" ); + artistBox->addWidget( cComposer ); + cComposer->insertItem( i18n("Various Composer") ); + cComposer->setCurrentText( "" ); + //cComposer->setSizePolicy( QSizePolicy::Maximum ); + connect( cComposer, SIGNAL(textChanged(const QString&)), + this, SLOT(composerChanged(const QString&)) + ); + //artistBox->addStretch(); + artistBox->addSpacing( 130 ); +// pCDDB = new KPushButton( iconLoader->loadIcon("cdaudio_unmount",KIcon::Small), i18n("Request CDDB"), this, "pCDDB" ); +// topGridLayout->addWidget( pCDDB, 0, 8 ); + + // set up the second row at the top + QLabel* lAlbumLabel = new QLabel( i18n("Album:"), this, "lAlbumLabel" ); + topGridLayout->addWidget( lAlbumLabel, 1, 0 ); + lAlbum = new KLineEdit( this, "lAlbum" ); + topGridLayout->addWidget( lAlbum, 1, 1 ); + // add a horizontal box layout for the disc number, year and genre + QHBoxLayout* albumBox = new QHBoxLayout( -1, "albumBox" ); + topGridLayout->addLayout( albumBox, 1, 3 ); + // and fill it up + QLabel* lDiscLabel = new QLabel( i18n("Disc No.:"), this, "lDiscLabel" ); + lDiscLabel->setAlignment( Qt::AlignRight | Qt::AlignVCenter ); + topGridLayout->addWidget( lDiscLabel, 1, 2 ); + iDisc = new KIntSpinBox( 1, 99, 1, 1, 10, this, "iDisc" ); + albumBox->addWidget( iDisc ); + QLabel* lYearLabel = new QLabel( i18n("Year:"), this, "lYearLabel" ); + albumBox->addWidget( lYearLabel ); + iYear = new KIntSpinBox( 0, 99999, 1, QDate::currentDate().year(), 10, this, "iYear" ); + albumBox->addWidget( iYear ); + QLabel* lGenreLabel = new QLabel( i18n("Genre:"), this, "lGenreLabel" ); + albumBox->addWidget( lGenreLabel ); + cGenre = new KComboBox( true, this, "cGenre" ); + cGenre->insertStringList( tagEngine->genreList ); + cGenre->setCurrentText( "" ); + KCompletion* cGenreCompletion = cGenre->completionObject(); + cGenreCompletion->insertItems( tagEngine->genreList ); + cGenreCompletion->setIgnoreCase( true ); + albumBox->addWidget( cGenre ); + + // generate the list view for the tracks + trackList = new KListView( this, "trackList" ); + gridLayout->addWidget( trackList, 1, 0 ); + // and fill in the headers + trackList->addColumn( i18n("Track") ); + trackList->addColumn( i18n("Artist"), 0 ); + trackList->addColumn( i18n("Composer"), 0 ); + trackList->addColumn( i18n("Title") ); + trackList->addColumn( i18n("Time") ); + trackList->setSelectionMode( QListView::Extended ); + trackList->setAllColumnsShowFocus( true ); + trackList->setResizeMode( QListView::LastColumn ); + connect( trackList, SIGNAL(selectionChanged()), + this, SLOT(trackChanged()) + ); + connect( trackList, SIGNAL(doubleClicked(QListViewItem*,const QPoint&,int)), + this, SLOT(addClicked()) + ); + gridLayout->setRowStretch( 1, 1 ); + + // create the box at the bottom for editing the tags + tagGroupBox = new QGroupBox( i18n("No track selected"), this, "tagGroupBox" ); + gridLayout->addWidget( tagGroupBox, 2, 0 ); + tagGroupBox->setColumnLayout( 0, Qt::Vertical ); + tagGroupBox->layout()->setSpacing( 6 ); + tagGroupBox->layout()->setMargin( 6 ); + QGridLayout* tagGridLayout = new QGridLayout( tagGroupBox->layout(), 1, 1, -1, "tagGridLayout" ); + + // add the up and down buttons + pTrackUp = new KPushButton( " ", tagGroupBox, "pTrackUp" ); + pTrackUp->setPixmap( iconLoader->loadIcon("up",KIcon::Toolbar) ); + pTrackUp->setAutoRepeat( true ); + connect( pTrackUp, SIGNAL(clicked()), + this, SLOT(trackUpPressed()) + ); + tagGridLayout->addWidget( pTrackUp, 0, 0 ); + pTrackDown = new KPushButton( " ", tagGroupBox, "pTrackDown" ); + pTrackDown->setPixmap( iconLoader->loadIcon("down",KIcon::Toolbar) ); + pTrackDown->setAutoRepeat( true ); + connect( pTrackDown, SIGNAL(clicked()), + this, SLOT(trackDownPressed()) + ); + tagGridLayout->addWidget( pTrackDown, 1, 0 ); + + // add the inputs + // add a horizontal box layout for the title + QHBoxLayout* trackTitleBox = new QHBoxLayout( -1, "trackTitleBox" ); + tagGridLayout->addLayout( trackTitleBox, 0, 2 ); + // and fill it up + QLabel *lTrackTitleLabel = new QLabel( i18n("Title:"), tagGroupBox, "lTrackTitleLabel" ); + tagGridLayout->addWidget( lTrackTitleLabel, 0, 1 ); + lTrackTitle = new KLineEdit( tagGroupBox, "lTrackTitle" ); + trackTitleBox->addWidget( lTrackTitle ); + connect( lTrackTitle, SIGNAL(textChanged(const QString&)), + this, SLOT(trackTitleChanged(const QString&)) + ); + pTrackTitleEdit = new KPushButton( " ", tagGroupBox, "pTrackTitleEdit" ); + pTrackTitleEdit->setPixmap( iconLoader->loadIcon("kwrite",KIcon::Small) ); + pTrackTitleEdit->setFixedSize( lTrackTitle->sizeHint().height(), lTrackTitle->sizeHint().height() ); + pTrackTitleEdit->hide(); + trackTitleBox->addWidget( pTrackTitleEdit ); + connect( pTrackTitleEdit, SIGNAL(clicked()), + this, SLOT(editTrackTitleClicked()) + ); + // add a horizontal box layout for the composer + QHBoxLayout* trackArtistBox = new QHBoxLayout( -1, "trackArtistBox" ); + tagGridLayout->addLayout( trackArtistBox, 1, 2 ); + // and fill it up + QLabel* lTrackArtistLabel = new QLabel( i18n("Artist:"), tagGroupBox, "lTrackArtistLabel" ); + tagGridLayout->addWidget( lTrackArtistLabel, 1, 1 ); + lTrackArtist = new KLineEdit( tagGroupBox, "lTrackArtist" ); + trackArtistBox->addWidget( lTrackArtist ); + connect( lTrackArtist, SIGNAL(textChanged(const QString&)), + this, SLOT(trackArtistChanged(const QString&)) + ); + pTrackArtistEdit = new KPushButton( " ", tagGroupBox, "pTrackArtistEdit" ); + pTrackArtistEdit->setPixmap( iconLoader->loadIcon("kwrite",KIcon::Small) ); + pTrackArtistEdit->setFixedSize( lTrackArtist->sizeHint().height(), lTrackArtist->sizeHint().height() ); + pTrackArtistEdit->hide(); + trackArtistBox->addWidget( pTrackArtistEdit ); + connect( pTrackArtistEdit, SIGNAL(clicked()), + this, SLOT(editTrackArtistClicked()) + ); + QLabel* lTrackComposerLabel = new QLabel( i18n("Composer:"), tagGroupBox, "lTrackComposerLabel" ); + trackArtistBox->addWidget( lTrackComposerLabel ); + lTrackComposer = new KLineEdit( tagGroupBox, "lTrackComposer" ); + trackArtistBox->addWidget( lTrackComposer ); + connect( lTrackComposer, SIGNAL(textChanged(const QString&)), + this, SLOT(trackComposerChanged(const QString&)) + ); + pTrackComposerEdit = new KPushButton( " ", tagGroupBox, "pTrackComposerEdit" ); + pTrackComposerEdit->setPixmap( iconLoader->loadIcon("kwrite",KIcon::Small) ); + pTrackComposerEdit->setFixedSize( lTrackComposer->sizeHint().height(), lTrackComposer->sizeHint().height() ); + pTrackComposerEdit->hide(); + trackArtistBox->addWidget( pTrackComposerEdit ); + connect( pTrackComposerEdit, SIGNAL(clicked()), + this, SLOT(editTrackComposerClicked()) + ); + // add a horizontal box layout for the comment + QHBoxLayout* trackCommentBox = new QHBoxLayout( -1, "trackCommentBox" ); + tagGridLayout->addLayout( trackCommentBox, 2, 2 ); + // and fill it up + QLabel* lTrackCommentLabel = new QLabel( i18n("Comment:"), tagGroupBox, "lTrackCommentLabel" ); + tagGridLayout->addWidget( lTrackCommentLabel, 2, 1 ); + tTrackComment = new KTextEdit( tagGroupBox, "tTrackComment" ); + trackCommentBox->addWidget( tTrackComment ); + tTrackComment->setFixedHeight( 65 ); + connect( tTrackComment, SIGNAL(textChanged()), + this, SLOT(trackCommentChanged()) + ); + pTrackCommentEdit = new KPushButton( " ", tagGroupBox, "pTrackCommentEdit" ); + pTrackCommentEdit->setPixmap( iconLoader->loadIcon("kwrite",KIcon::Small) ); + pTrackCommentEdit->setFixedSize( lTrackTitle->sizeHint().height(), lTrackTitle->sizeHint().height() ); + pTrackCommentEdit->hide(); + trackCommentBox->addWidget( pTrackCommentEdit ); + connect( pTrackCommentEdit, SIGNAL(clicked()), + this, SLOT(editTrackCommentClicked()) + ); + + // draw a horizontal line + QFrame* lineFrame = new QFrame( this, "lineFrame" ); + lineFrame->setFrameShape( QFrame::HLine ); + lineFrame->setFrameShadow( QFrame::Sunken ); + lineFrame->setFrameShape( QFrame::HLine ); + gridLayout->addWidget( lineFrame, 3, 0 ); + gridLayout->setRowSpacing( 3, 16 ); + + // add a horizontal box layout for the control elements + QHBoxLayout* controlBox = new QHBoxLayout( -1, "controlBox" ); + gridLayout->addLayout( controlBox, 4, 0 ); + + // add the control elements + pSaveCue = new KPushButton( iconLoader->loadIcon("filesave",KIcon::Small), i18n("Save cuesheet ..."), this, "pSaveCue" ); + controlBox->addWidget( pSaveCue ); + connect( pSaveCue, SIGNAL(clicked()), + this, SLOT(saveCuesheetClicked()) + ); + controlBox->addStretch(); + + cAdd = new ComboButton( this, "cAdd" ); + cAdd->insertItem( iconLoader->loadIcon("fileopen",KIcon::Small),i18n("Add all tracks") ); + cAdd->insertItem( iconLoader->loadIcon("fileopen",KIcon::Small),i18n("Add selected tracks") ); + RipperPlugin* plugin = config->getCurrentRipper(); + if( plugin != 0 && plugin->rip.full_disc.enabled ) cAdd->insertItem( iconLoader->loadIcon("cdaudio_unmount",KIcon::Small),i18n("Add full CD as one file") ); + //cAdd->setSizeMode( ComboButton::Min ); + controlBox->addWidget( cAdd ); + connect( cAdd, SIGNAL(clicked(int)), + this, SLOT(addClicked(int)) + ); + pCancel = new KPushButton( iconLoader->loadIcon("cancel",KIcon::Small), i18n("Cancel"), this, "pCancel" ); + controlBox->addWidget( pCancel ); + connect( pCancel, SIGNAL(clicked()), + this, SLOT(reject()) + ); + + // delete the icon loader object + delete iconLoader; + + bool various_artists = false; + bool various_composer = false; + QString artist = ""; + QString composer = ""; + QString album = ""; + int disc = 0; + int year = 0; + QString genre = ""; + + device = cdManager->newCDDevice( _device ); + // don't execute the dialog, if no audio cd was found + noCD = device.isEmpty(); + + QValueList tags = cdManager->getTrackList( device ); + for( QValueList::Iterator it = tags.begin(); it != tags.end(); ++it ) { + if( artist == "" ) artist = (*it)->artist; + else if( artist != (*it)->artist ) various_artists = true; + + if( composer == "" ) composer = (*it)->composer; + else if( composer != (*it)->composer ) various_composer = true; + + if( album == "" ) album = (*it)->album; + if( disc == 0 ) disc = (*it)->disc; + if( year == 0 ) year = (*it)->year; + if( genre == "" ) genre = (*it)->genre; + + new KListViewItem( trackList, QString().sprintf("%02i",(*it)->track), (*it)->artist, (*it)->composer, (*it)->title, QString().sprintf("%i:%02i",(*it)->length/60,(*it)->length%60) ); + } + trackList->setSorting( -1 ); + + // fill in the cd information + if( various_artists ) cArtist->setCurrentItem( 0 ); + else cArtist->setCurrentText( artist ); + artistChanged( cArtist->currentText() ); + + if( various_composer ) cComposer->setCurrentItem( 0 ); + else cComposer->setCurrentText( composer ); + composerChanged( cComposer->currentText() ); + + lAlbum->setText( album ); + if( disc != 0 ) iDisc->setValue( disc ); + if( year != 0 ) iYear->setValue( year ); + cGenre->setCurrentText( genre ); + + //trackList->setCurrentItem( trackList->firstChild() ); + trackList->setSelected( trackList->firstChild(), true ); + + pTrackUp->setEnabled( false ); + if( trackList->firstChild() != 0 ) { + if( trackList->firstChild()->itemBelow() != 0 ) { + pTrackDown->setEnabled( true ); + } + else { + pTrackDown->setEnabled( false ); + } + } + else { + pTrackDown->setEnabled( false ); + } +} + +CDOpener::~CDOpener() +{} + +int CDOpener::columnByName( const QString& name ) +{ + for( int i = 0; i < trackList->columns(); ++i ) { + if( trackList->columnText( i ) == name ) return i; + } + return -1; +} + +void CDOpener::trackUpPressed() +{ + QListViewItem* item = selectedItems.first()->itemAbove(); + + if( item != 0 ) { + item->setSelected( true ); + trackList->repaintItem( item ); + trackList->ensureItemVisible( item ); + } + else { + return; // NULL pointer (cannot be) + } + + for( QValueList::Iterator it = selectedItems.begin(); it != selectedItems.end(); ++it ) { + (*it)->setSelected( false ); + trackList->repaintItem( *it ); + } + + if( item->itemAbove() == 0 ) { + pTrackUp->setEnabled( false ); + } + + pTrackDown->setEnabled( true ); + + trackChanged(); +} + +void CDOpener::trackDownPressed() +{ + QListViewItem* item = selectedItems.last()->itemBelow(); + + if( item != 0 ) { + item->setSelected( true ); + trackList->repaintItem( item ); + trackList->ensureItemVisible( item ); + } + else { + return; // NULL pointer (cannot be) + } + + for( QValueList::Iterator it = selectedItems.begin(); it != selectedItems.end(); ++it ) { + (*it)->setSelected( false ); + trackList->repaintItem( *it ); + } + + pTrackUp->setEnabled( true ); + + if( item->itemBelow() == 0 ) { + pTrackDown->setEnabled( false ); + } + + trackChanged(); +} + +void CDOpener::trackChanged() +{ + // NOTE if no track is selected soundkonverter could use the current item as default item (like qlistview does) + int i = 0; + + // rebuild the list of the selected tracks + selectedTracks.clear(); + selectedItems.clear(); + for( QListViewItem *item = trackList->firstChild(); item != NULL; item = item->nextSibling() ) { + i++; + if( item->isSelected() ) { + selectedTracks.append( i ); + selectedItems.append( item ); + } + } + + // insert the new values + if( selectedTracks.count() < 1 ) { + pTrackUp->setEnabled( false ); + pTrackDown->setEnabled( false ); + + lTrackTitle->setEnabled( false ); + lTrackTitle->setText( "" ); + pTrackTitleEdit->hide(); + lTrackArtist->setEnabled( false ); + lTrackArtist->setText( "" ); + pTrackArtistEdit->hide(); + lTrackComposer->setEnabled( false ); + lTrackComposer->setText( "" ); + pTrackComposerEdit->hide(); + tTrackComment->setEnabled( false ); + tTrackComment->setReadOnly( true ); + tTrackComment->setText( "" ); + pTrackCommentEdit->hide(); + + return; + } + else if( selectedTracks.count() > 1 ) { + if( selectedItems.first()->itemAbove() != 0 ) pTrackUp->setEnabled( true ); + else pTrackUp->setEnabled( false ); + + if( selectedItems.last()->itemBelow() != 0 ) pTrackDown->setEnabled( true ); + else pTrackDown->setEnabled( false ); + + QString trackListString = ""; + if( selectedTracks.count() == trackList->childCount() ) { + trackListString = i18n("All tracks"); + } + else { + trackListString = i18n("Tracks") + QString().sprintf(" %02i",selectedTracks.first()); + QValueList::Iterator track = selectedTracks.begin(); + track++; + for( ; track != selectedTracks.end(); ++track ) { + trackListString += QString().sprintf(", %02i",*track); + } + } + tagGroupBox->setTitle( trackListString ); + + QString title = cdManager->getTags( device, selectedTracks.first() )->title; + bool equalTitles = true; + QString artist = cdManager->getTags( device, selectedTracks.first() )->artist; + bool equalArtists = true; + QString composer = cdManager->getTags( device, selectedTracks.first() )->composer; + bool equalComposers = true; + QString comment = cdManager->getTags( device, selectedTracks.first() )->comment; + bool equalComments = true; + for( QValueList::Iterator track = selectedTracks.begin(); track != selectedTracks.end(); ++track ) { + TagData* tags = cdManager->getTags( device, *track ); + + if( title != tags->title ) equalTitles = false; + if( artist != tags->artist ) equalArtists = false; + if( composer != tags->composer ) equalComposers = false; + if( comment != tags->comment ) equalComments = false; + } + + if( equalTitles ) { + lTrackTitle->setEnabled( true ); + lTrackTitle->setText( title ); + pTrackTitleEdit->hide(); + } + else { + lTrackTitle->setEnabled( false ); + lTrackTitle->setText( "" ); + pTrackTitleEdit->show(); + } + + if( cArtist->currentText() == i18n("Various Artists") && equalArtists ) { + lTrackArtist->setEnabled( true ); + lTrackArtist->setText( artist ); + pTrackArtistEdit->hide(); + } + else if( cArtist->currentText() == i18n("Various Artists") ) { + lTrackArtist->setEnabled( false ); + lTrackArtist->setText( "" ); + pTrackArtistEdit->show(); + } + else { + lTrackArtist->setEnabled( false ); + lTrackArtist->setText( cArtist->currentText() ); + pTrackArtistEdit->hide(); + } + + if( cComposer->currentText() == i18n("Various Composer") && equalComposers ) { + lTrackComposer->setEnabled( true ); + lTrackComposer->setText( composer ); + pTrackComposerEdit->hide(); + } + else if( cComposer->currentText() == i18n("Various Composer") ) { + lTrackComposer->setEnabled( false ); + lTrackComposer->setText( "" ); + pTrackComposerEdit->show(); + } + else { + lTrackComposer->setEnabled( false ); + lTrackComposer->setText( cComposer->currentText() ); + pTrackComposerEdit->hide(); + } + + if( equalComments ) { + tTrackComment->setEnabled( true ); + tTrackComment->setReadOnly( false ); + tTrackComment->setText( comment ); + pTrackCommentEdit->hide(); + } + else { + tTrackComment->setEnabled( false ); + tTrackComment->setReadOnly( true ); + tTrackComment->setText( "" ); + pTrackCommentEdit->show(); + } + } + else { + if( selectedItems.first()->itemAbove() != 0 ) pTrackUp->setEnabled( true ); + else pTrackUp->setEnabled( false ); + + if( selectedItems.first()->itemBelow() != 0 ) pTrackDown->setEnabled( true ); + else pTrackDown->setEnabled( false ); + + tagGroupBox->setTitle( i18n("Track") + QString().sprintf(" %02i",selectedTracks.first()) ); + + TagData* tags = cdManager->getTags( device, selectedTracks.first() ); + lTrackTitle->setEnabled( true ); + lTrackTitle->setText( tags->title ); + pTrackTitleEdit->hide(); + if( cArtist->currentText() == i18n("Various Artists") ) { + lTrackArtist->setEnabled( true ); + lTrackArtist->setText( tags->artist ); + pTrackArtistEdit->hide(); + } + else { + lTrackArtist->setEnabled( false ); + lTrackArtist->setText( cArtist->currentText() ); + pTrackArtistEdit->hide(); + } + if( cComposer->currentText() == i18n("Various Composer") ) { + lTrackComposer->setEnabled( true ); + lTrackComposer->setText( tags->composer ); + pTrackComposerEdit->hide(); + } + else { + lTrackComposer->setEnabled( false ); + lTrackComposer->setText( cComposer->currentText() ); + pTrackComposerEdit->hide(); + } + tTrackComment->setEnabled( true ); + tTrackComment->setReadOnly( false ); + tTrackComment->setText( tags->comment ); + pTrackCommentEdit->hide(); + } +} + +void CDOpener::artistChanged( const QString& text ) +{ + if( text == i18n("Various Artists") ) { + trackList->adjustColumn( columnByName( i18n("Artist") ) ); + } + else { + trackList->setColumnWidth( columnByName( i18n("Artist") ), 0 ); + } + + trackChanged(); +} + +void CDOpener::composerChanged( const QString& text ) +{ + if( text == i18n("Various Composer") ) { + trackList->adjustColumn( columnByName( i18n("Composer") ) ); + } + else { + trackList->setColumnWidth( columnByName( i18n("Composer") ), 0 ); + } + + trackChanged(); +} + +void CDOpener::trackTitleChanged( const QString& text ) +{ + if( !lTrackTitle->isEnabled() ) return; + + for( QValueList::Iterator it = selectedItems.begin(); it != selectedItems.end(); ++it ) { + (*it)->setText( columnByName( i18n("Title") ), text ); + } + for( QValueList::Iterator it = selectedTracks.begin(); it != selectedTracks.end(); ++it ) { + TagData* tags = cdManager->getTags( device, *it ); + tags->title = text; + } +} + +void CDOpener::trackArtistChanged( const QString& text ) +{ + if( !lTrackArtist->isEnabled() ) return; + + for( QValueList::Iterator it = selectedItems.begin(); it != selectedItems.end(); ++it ) { + (*it)->setText( columnByName( i18n("Artist") ), text ); + } + for( QValueList::Iterator it = selectedTracks.begin(); it != selectedTracks.end(); ++it ) { + TagData* tags = cdManager->getTags( device, *it ); + tags->artist = text; + } +} + +void CDOpener::trackComposerChanged( const QString& text ) +{ + if( !lTrackComposer->isEnabled() ) return; + + for( QValueList::Iterator it = selectedItems.begin(); it != selectedItems.end(); ++it ) { + (*it)->setText( columnByName( i18n("Composer") ), text ); + } + for( QValueList::Iterator it = selectedTracks.begin(); it != selectedTracks.end(); ++it ) { + TagData* tags = cdManager->getTags( device, *it ); + tags->composer = text; + } +} + +void CDOpener::trackCommentChanged() +{ + QString text = tTrackComment->text(); + + if( !tTrackComment->isEnabled() ) return; + + for( QValueList::Iterator it = selectedTracks.begin(); it != selectedTracks.end(); ++it ) { + TagData* tags = cdManager->getTags( device, *it ); + tags->comment = text; + } +} + +void CDOpener::editTrackTitleClicked() +{ + lTrackTitle->setEnabled( true ); + lTrackTitle->setFocus(); + pTrackTitleEdit->hide(); + trackTitleChanged( lTrackTitle->text() ); +} + +void CDOpener::editTrackArtistClicked() +{ + lTrackArtist->setEnabled( true ); + lTrackArtist->setFocus(); + pTrackArtistEdit->hide(); + trackArtistChanged( lTrackArtist->text() ); +} + +void CDOpener::editTrackComposerClicked() +{ + lTrackComposer->setEnabled( true ); + lTrackComposer->setFocus(); + pTrackComposerEdit->hide(); + trackComposerChanged( lTrackComposer->text() ); +} + +void CDOpener::editTrackCommentClicked() +{ + tTrackComment->setEnabled( true ); + tTrackComment->setReadOnly( false ); + tTrackComment->setFocus(); + pTrackCommentEdit->hide(); + trackCommentChanged(); +} + +void CDOpener::addClicked( int index ) +{ + if( index == 0 ) + { + QValueList allTracks; + + // TODO save all options (album artist, disc, genre, etc.) + for( int it = 1; it <= cdManager->getTrackCount(device); ++it ) { + TagData* tags = cdManager->getTags( device, it ); + if( cArtist->currentText() != i18n("Various Artists") ) tags->artist = cArtist->currentText(); + if( cComposer->currentText() != i18n("Various Composer") ) tags->composer = cComposer->currentText(); + tags->album = lAlbum->text(); + tags->disc = iDisc->value(); + tags->year = iYear->value(); + tags->genre = cGenre->currentText(); + allTracks += it; + } + emit addTracks( device, allTracks ); + } + else if( index == 1 ) + { + // TODO save all options (album artist, disc, genre, etc.) + for( QValueList::Iterator it = selectedTracks.begin(); it != selectedTracks.end(); ++it ) { + TagData* tags = cdManager->getTags( device, *it ); + if( cArtist->currentText() != i18n("Various Artists") ) tags->artist = cArtist->currentText(); + if( cComposer->currentText() != i18n("Various Composer") ) tags->composer = cComposer->currentText(); + tags->album = lAlbum->text(); + tags->disc = iDisc->value(); + tags->year = iYear->value(); + tags->genre = cGenre->currentText(); + } + emit addTracks( device, selectedTracks ); + } + else + { + // TODO save all options (album artist, disc, genre, etc.) + cdManager->setDiscTags( device, + new TagData( cArtist->currentText(), cComposer->currentText(), + lAlbum->text(), /*cArtist->currentText() + " - " + */lAlbum->text(), + cGenre->currentText(), "", + 1, iDisc->value(), iYear->value(), + cdManager->getTimeCount(device) ) ); + emit addDisc( device ); + } + accept(); +} + +// void CDOpener::addAsOneTrackClicked() +// { +// // TODO save all options (album artist, disc, genre, etc.) +// cdManager->setDiscTags( device, +// new TagData( cArtist->currentText(), cComposer->currentText(), +// lAlbum->text(), /*cArtist->currentText() + " - " + */lAlbum->text(), +// cGenre->currentText(), "", +// 1, iDisc->value(), iYear->value(), +// cdManager->getTimeCount(device) ) ); +// +// emit addDisc( device ); +// accept(); +// } + +void CDOpener::saveCuesheetClicked() +{ + QString filename = KFileDialog::getSaveFileName( QDir::homeDirPath(), "*.cue" ); + if( filename.isEmpty() ) return; + + QFile cueFile( filename ); + if( cueFile.exists() ) { + int ret = KMessageBox::questionYesNo( this, + i18n("A file with this name already exists.\n\nDo you want to overwrite the existing one?"), + i18n("File already exists") ); + if( ret == KMessageBox::No ) return; + } + if( !cueFile.open( IO_WriteOnly ) ) return; + + QString content; + + content.append( "TITLE \"" + lAlbum->text() + "\"\n" ); + content.append( "PERFORMER \"" + cArtist->currentText() + "\"\n" ); + content.append( "FILE \"\" MP3\n" ); + + int INDEX = 0; + bool addFrames = false; + QValueList tags = cdManager->getTrackList( device ); + for( QValueList::Iterator it = tags.begin(); it != tags.end(); ++it ) { + content.append( QString().sprintf(" TRACK %02i AUDIO\n",(*it)->track ) ); + content.append( " TITLE \"" + (*it)->title + "\"\n" ); + content.append( " PERFORMER \"" + (*it)->artist + "\"\n" ); + if( addFrames ) { + content.append( QString().sprintf(" INDEX 01 %02i:%02i:37\n",INDEX/60,INDEX%60) ); + INDEX++; + addFrames = false; + } + else { + content.append( QString().sprintf(" INDEX 01 %02i:%02i:00\n",INDEX/60,INDEX%60) ); + addFrames = true; + } + + INDEX += (*it)->length; + } + + QTextStream ts( &cueFile ); + ts << content; + + cueFile.close(); +} + + + diff --git a/src/cdopener.h b/src/cdopener.h new file mode 100755 index 0000000..09e941a --- /dev/null +++ b/src/cdopener.h @@ -0,0 +1,139 @@ + + +#ifndef CDOPENER_H +#define CDOPENER_H + +#include + +class CDManager; +class TagEngine; +class Config; +class ComboButton; +class KListView; +class KPushButton; +class KLineEdit; +class KComboBox; +class KIntSpinBox; +class KTextEdit; +class QGroupBox; +class QListViewItem; + +/** + * @short Shows a dialog for selecting files from a CD + * @author Daniel Faust + * @version 0.3 + */ +class CDOpener : public KDialog +{ + Q_OBJECT +public: +// enum Mode { +// all_tracks, +// selected_tracks, +// full_cd +// }; + + /** + * Constructor + * @param parent The parent widget + * @param name The name of the file list + * @p modal Sets whether the dialog is modal or not + * @p f Some flags + */ + CDOpener( Config*, CDManager*, TagEngine*, const QString &device, QWidget *parent = 0, const char *name = 0, /*Mode default_mode = all_tracks, const QString& default_text = "",*/ bool modal = true, WFlags f = 0 ); + + /** + * Destructor + */ + virtual ~CDOpener(); + + /** true if no CD was found (don't execute the dialog) */ + bool noCD; + +private: + /** A list of all tracks on the CD */ + KListView *trackList; + + /** A combobox for entering the artist or selecting VA of the whole CD */ + KComboBox *cArtist; + /** A combobox for entering the composer or selecting VC of the whole CD */ + KComboBox *cComposer; + /** A lineedit for entering the album name */ + KLineEdit *lAlbum; + /** A spinbox for entering or selecting the disc number */ + KIntSpinBox *iDisc; + /** A spinbox for entering or selecting the year of the album */ + KIntSpinBox *iYear; + /** A combobox for entering or selecting the genre of the album */ + KComboBox *cGenre; + + /** Request CDDB information */ +// KPushButton *pCDDB; + + /** The groupbox shows the selected track numbers */ + QGroupBox *tagGroupBox; + + /** Set the focus of the tag editor to the track over it */ + KPushButton *pTrackUp; + /** Set the focus of the tag editor to the track under it */ + KPushButton *pTrackDown; + + /** A lineedit for entering the title of track */ + KLineEdit *lTrackTitle; + KPushButton *pTrackTitleEdit; + /** A lineedit for entering the artist of a track */ + KLineEdit *lTrackArtist; + KPushButton *pTrackArtistEdit; + /** A lineedit for entering the composer of a track */ + KLineEdit *lTrackComposer; + KPushButton *pTrackComposerEdit; + /** A textedit for entering a comment for a track */ + KTextEdit *tTrackComment; + KPushButton *pTrackCommentEdit; + + /** Save the tag information to a cue file */ + KPushButton *pSaveCue; + //** Add whole CD as one track and quit the dialog */ + //KPushButton *pAddAsOneTrack; + //** Add selected tracks to the file list and quit the dialog */ + //KPushButton *pAdd; + ComboButton* cAdd; + /** Quit the dialog */ + KPushButton *pCancel; + + CDManager* cdManager; + TagEngine* tagEngine; + Config* config; + + QString device; + + QValueList selectedTracks; + QValueList selectedItems; + + int columnByName( const QString& name ); + +private slots: + void trackChanged(); + void trackUpPressed(); + void trackDownPressed(); + void artistChanged( const QString& text ); + void composerChanged( const QString& text ); + void trackTitleChanged( const QString& text ); + void trackArtistChanged( const QString& text ); + void trackComposerChanged( const QString& text ); + void trackCommentChanged(); + void editTrackTitleClicked(); + void editTrackArtistClicked(); + void editTrackComposerClicked(); + void editTrackCommentClicked(); + void addClicked( int index = 1 ); +// void addAsOneTrackClicked(); + void saveCuesheetClicked(); + +signals: + void addTracks( const QString& device, QValueList ); + void addDisc( const QString& device ); + //void openCuesheetEditor( const QString& content ); +}; + +#endif // CDOPENER_H diff --git a/src/combobutton.cpp b/src/combobutton.cpp new file mode 100755 index 0000000..ff5d758 --- /dev/null +++ b/src/combobutton.cpp @@ -0,0 +1,114 @@ + +#include "combobutton.h" + +#include +#include +#include +#include +#include +#include + +ComboButton::ComboButton( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + m_increaseHeight = 0; + + QGridLayout *grid = new QGridLayout( this, 1, 1 ); + + m_box = new KComboBox(this); + grid->addWidget(m_box,0,0); + + connect( m_box, SIGNAL(activated(int)), + this, SLOT(boxActivated(int)) + ); + + m_button = new KPushButton( QString::null, this, "pushbutton" ); + grid->addWidget( m_button, 0, 0 ); + + connect( m_button, SIGNAL(clicked()), + this, SLOT(buttonClicked()) + ); + + m_sizeMode = Max; + + balanceSize(); +} + +ComboButton::~ComboButton() +{ +} + +void ComboButton::balanceSize() +{ + int width; + + if( m_sizeMode == Max ) + width = m_box->sizeHint().width()-17; + else + width = m_button->sizeHint().width(); + + int height = ( m_box->sizeHint().height() > m_button->sizeHint().height() ) ? m_box->sizeHint().height() : m_button->sizeHint().height(); + + m_box->setFixedSize( width+17, height+m_increaseHeight ); + m_button->setFixedSize( width, height+m_increaseHeight ); +} + +void ComboButton::repaintButton() +{ + m_button->setText( m_box->currentText() ); + if(m_box->pixmap( m_box->currentItem()) ) + m_button->setIconSet( *m_box->pixmap(m_box->currentItem()) ); + balanceSize(); +} + +void ComboButton::insertItem( const QString &text, int index ) +{ + m_box->insertItem( text, index ); + repaintButton(); +} + +void ComboButton::insertItem( const QPixmap &pixmap, const QString &text, int index ) +{ + m_box->insertItem( pixmap, text, index ); + repaintButton(); +} + +void ComboButton::increaseHeight( int height ) +{ + m_increaseHeight = height; + balanceSize(); +} + +void ComboButton::boxActivated( int index ) +{ + repaintButton(); + emit clicked( index ); +} + +void ComboButton::buttonClicked() +{ + emit clicked( m_box->currentItem() ); +} + +void ComboButton::setSizeMode( int mode ) +{ + m_sizeMode = mode; + balanceSize(); +} + +int ComboButton::sizeMode() +{ + return m_sizeMode; +} + +void ComboButton::setFont( const QFont& font ) +{ + m_button->setFont( font ); + m_box->setFont( font ); +} + +QFont ComboButton::font() +{ + return m_button->font(); +} + diff --git a/src/combobutton.h b/src/combobutton.h new file mode 100755 index 0000000..3f07199 --- /dev/null +++ b/src/combobutton.h @@ -0,0 +1,110 @@ + + +#ifndef COMBOBUTTON_H +#define COMBOBUTTON_H + +#include + +class QString; +class QPixmap; +class KPushButton; +class KComboBox; + +/** + * @short ComboButton + * @author Daniel Faust + * @version 0.3 + */ +class ComboButton : public QWidget +{ + Q_OBJECT +public: + enum SizeMode { + Min, Max + }; + + /** + * Constructor + * @param parent The parent widget + * @param name The name of the file list + */ + ComboButton( QWidget *parent, const char *name = 0 ); + + /** + * Destructor + */ + virtual ~ComboButton(); + + /** + * Insert a new item with @p text at position @p index + */ + void insertItem( const QString &text, int index = -1 ); + /** + * Insert a new item with an icon @p pixmap and @p text at position @p index + */ + void insertItem( const QPixmap &pixmap, const QString &text, int index = -1 ); + + /** + * Increase the combobutton's height by @p height + */ + void increaseHeight( int height ); + + /** + * Sets m_sizeMode to @p mode + */ + void setSizeMode( int mode ); + + /** + * Returns the m_sizeMode + */ + int sizeMode(); + + /** + * Sets the font of the combobutton + */ + void setFont( const QFont& font ); + + /** + * Returns the font of the button + */ + QFont font(); + +private: + /** A pointer to the button */ + KPushButton *m_button; + /** A pointer to the combobox */ + KComboBox *m_box; + + int m_increaseHeight; + + /** The actual size mode */ + int m_sizeMode; + + /** Recalculate the size of the combobutton */ + void balanceSize(); + /** The button gets a new label, etc. */ + void repaintButton(); + +//public slots: + //void setCurrentItem(const QString &item, bool insert=false, int index=-1); + //void setCurrentItem(int index); + +private slots: + /** + * Is called when the user selects an item from the popdown menu of the combobox + */ + void boxActivated( int index ); + /** + * Is called when the user clicks the button + */ + void buttonClicked(); + +signals: + /** + * The signal clicked is emitted, when the user selects an item + */ + void clicked( int index ); + +}; + +#endif // COMBOBUTTON_H diff --git a/src/config.cpp b/src/config.cpp new file mode 100755 index 0000000..b8b1904 --- /dev/null +++ b/src/config.cpp @@ -0,0 +1,1516 @@ + +#include "config.h" +#include "logger.h" +#include "convertpluginloader.h" +#include "replaygainpluginloader.h" +#include "ripperpluginloader.h" +#include "options.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +// NOTE currently only the possibilities of a file format are respected, +// the possibilities of the current encoder are ignored +// - seems to be fixed + +FormatItem::FormatItem() +{ + // reset everything + mime_types.clear(); + size = 0; + compressionType = FormatInfo::lossy; + compressionLevel = 0; + internalReplayGain = false; + encoders.clear(); + decoders.clear(); + replaygains.clear(); + //repairers.clear(); + encoder = 0; + decoder = 0; + replaygain = 0; + //repairer = 0; +} + +FormatItem::~FormatItem() +{} + + +Config::Config( Logger* _logger ) +{ + logger = _logger; + + currentRipper = 0; // this seems to be unnecessary +} + +Config::~Config() +{} + +void Config::read() +{ + loadPlugins(); + readProfiles(); + + KConfig *conf = kapp->config(); + QStringList listDefaults; + int intDefault; + bool boolDefault; + QString ripper; + QString encoder; + QString decoder; + QString replaygain; + int rank; + + conf->setGroup( "General" ) ; + data.app.configVersion = conf->readNumEntry( "configVersion", 0 ); + +/* if( configVersion == 0 ) { + conf->setGroup( "Interface" ); + data.general.updateDelay = conf->readNumEntry( "pauseMS", 500 ); + data.general.startTab = conf->readNumEntry( "startTab", 0 ); + data.general.showToolBar = conf->readBoolEntry( "showToolBar", false ); + + conf->setGroup( "Backends" ); + listDefaults.clear(); + QString datadir = locateLocal( "data", "soundkonverter/bin/" ); + datadir.remove( datadir.length() - 1, 1 ); + listDefaults.append( datadir ); + listDefaults.append( QDir::homeDirPath() + "/bin" ); + listDefaults.append( "/usr/local/bin" ); + listDefaults.append( "/usr/bin" ); + data.environment.directories = conf->readListEntry( "directories", listDefaults ); + listDefaults.clear(); + data.environment.foundPrograms = conf->readListEntry( "programs", listDefaults ); + + conf->setGroup( "Misc" ); + //configVersion = conf->readNumEntry( "configVersion", 0 ); + data.general.askForNewOptions = conf->readBoolEntry( "askForNewOptions", true ); + + return; + }*/ + + conf->setGroup( "General" ) ; + //configVersion = conf->readNumEntry( "configVersion", 0 ); + data.general.startTab = conf->readNumEntry( "startTab", 0 ); + data.general.lastTab = conf->readNumEntry( "lastTab", 0 ); + data.general.defaultProfile = conf->readEntry( "defaultProfile", i18n("Last used") ); + data.general.defaultFormat = conf->readEntry( "defaultFormat", i18n("Last used") ); +// data.general.defaultOutputDirectory = conf->readEntry( "defaultOutputDirectory", QDir::homeDirPath() + "/soundKonverter/%b/%d - %n - %a - %t" ); + data.general.specifyOutputDirectory = conf->readEntry( "specifyOutputDirectory", QDir::homeDirPath() + "/soundKonverter" ); + data.general.metaDataOutputDirectory = conf->readEntry( "metaDataOutputDirectory", QDir::homeDirPath() + "/soundKonverter/%b/%d - %n - %a - %t" ); + data.general.copyStructureOutputDirectory = conf->readEntry( "copyStructureOutputDirectory", QDir::homeDirPath() + "/soundKonverter" ); + data.general.useVFATNames = conf->readBoolEntry( "useVFATNames", true ); + data.general.conflictHandling = conf->readNumEntry( "conflictHandling", 0 ); + data.general.priority = conf->readNumEntry( "priority", 10 ); + data.general.numFiles = conf->readNumEntry( "numFiles", 3 ); + data.general.updateDelay = conf->readNumEntry( "updateDelay", 500 ); + data.general.askForNewOptions = conf->readBoolEntry( "askForNewOptions", true ); + data.general.executeUserScript = conf->readBoolEntry( "executeUserScript", false ); + data.general.showToolBar = conf->readBoolEntry( "showToolBar", false ); + + conf->setGroup( "Plugins" ); + data.plugins.checkForUpdates = conf->readBoolEntry( "checkForUpdates", false ); + + conf->setGroup( "Environment" ); + listDefaults.clear(); + QString datadir = locateLocal( "data", "soundkonverter/bin/" ); + datadir.remove( datadir.length() - 1, 1 ); + listDefaults.append( datadir ); + listDefaults.append( QDir::homeDirPath() + "/bin" ); + listDefaults.append( "/usr/local/bin" ); + listDefaults.append( "/usr/bin" ); + data.environment.directories = conf->readListEntry( "directories", listDefaults ); + listDefaults.clear(); + data.environment.foundPrograms = conf->readListEntry( "foundPrograms", listDefaults ); + + conf->setGroup( "Ripper" ); + ripper = conf->readEntry( "ripper", "kio_audiocd" ); + + if( ripper == "kio_audiocd" ) rank = 10000; + else rank = 60; // kio_audiocd ranking + currentRipper = 0; // this is a valid ripper (kio_audiocd) + for( QValueList::Iterator b = rippers.begin(); b != rippers.end(); ++b ) { + binaries[ (*b)->rip.bin ] = ""; + if( (*b)->rip.rank > rank ) { + rank = (*b)->rip.rank; + currentRipper = (*b); + } + if( (*b)->rip.bin == ripper ) { + rank = 10000; // should be high enough to overbid the other plugins + currentRipper = (*b); + } + } + + for( QValueList::Iterator it = formats.begin(); it != formats.end(); ++it ) + { + for( QValueList::Iterator b = (*it).encoders.begin(); b != (*it).encoders.end(); ++b ) { + binaries[ (*b)->enc.bin ] = ""; + } + + for( QValueList::Iterator b = (*it).decoders.begin(); b != (*it).decoders.end(); ++b ) { + binaries[ (*b)->dec.bin ] = ""; + } + + for( QValueList::Iterator b = (*it).replaygains.begin(); b != (*it).replaygains.end(); ++b ) { + binaries[ (*b)->replaygain.bin ] = ""; + } + + for( QMap::Iterator b = binaries.begin(); b != binaries.end(); ++b ) { + for( QStringList::Iterator c = data.environment.directories.begin(); c != data.environment.directories.end(); ++c ) + { + if( b.data() == "" && QFile::exists((*c) + "/" + b.key()) ) { + b.data() = (*c) + "/" + b.key(); + } + } + } + QStringList foundPrograms; + for( QMap::Iterator b = binaries.begin(); b != binaries.end(); ++b ) { + if( b.data() != "" ) { + foundPrograms.append( b.data() ); + } + } + if( foundPrograms != data.environment.foundPrograms ) { + backendsChanged = true; + } + else { + backendsChanged = false; + } + } + + for( QValueList::Iterator it = formats.begin(); it != formats.end(); ++it ) + { + conf->setGroup( (*it).mime_types.first() ); + encoder = conf->readEntry( "encoder" ); + decoder = conf->readEntry( "decoder" ); + replaygain = conf->readEntry( "replaygain" ); + + (*it).encoder = 0; + (*it).decoder = 0; + (*it).replaygain = 0; + + rank = 0; + for( QValueList::Iterator b = (*it).encoders.begin(); b != (*it).encoders.end(); ++b ) { + if( (*b)->enc.rank > rank && binaries[(*b)->enc.bin] != "" ) { + rank = (*b)->enc.rank; + (*it).encoder = (*b); + } + if( (*b)->enc.bin == encoder && binaries[(*b)->enc.bin] != "" ) { + rank = 10000; // should be high enougth to overbid the other plugins + (*it).encoder = (*b); + } + } + + rank = 0; + for( QValueList::Iterator b = (*it).decoders.begin(); b != (*it).decoders.end(); ++b ) { + if( (*b)->dec.rank > rank && binaries[(*b)->dec.bin] != "" ) { + rank = (*b)->dec.rank; + (*it).decoder = (*b); + } + if( (*b)->dec.bin == decoder && binaries[(*b)->dec.bin] != "" ) { + rank = 10000; // should be high enougth to overbid the other plugins + (*it).decoder = (*b); + } + } + + rank = 0; + for( QValueList::Iterator b = (*it).replaygains.begin(); b != (*it).replaygains.end(); ++b ) { + if( (*b)->replaygain.rank > rank && binaries[(*b)->replaygain.bin] != "" ) { + rank = (*b)->replaygain.rank; + (*it).replaygain = (*b); + } + if( (*b)->replaygain.bin == replaygain && binaries[(*b)->replaygain.bin] != "" ) { + rank = 10000; // should be high enougth to overbid the other plugins + (*it).replaygain = (*b); + } + } + + if( (*it).encoder != 0 && (*it).encoder->enc.strength.enabled ) { + if( (*it).encoder->enc.strength.range_max >= (*it).encoder->enc.strength.range_min ) + intDefault = (*it).encoder->enc.strength.default_value / (*it).encoder->enc.strength.step; + else + intDefault = ( (*it).encoder->enc.strength.range_min - (*it).encoder->enc.strength.default_value ) / (*it).encoder->enc.strength.step; + } + else { + intDefault = 0; + } + (*it).compressionLevel = conf->readNumEntry( "compressionLevel", intDefault ); + + if( (*it).encoder != 0 && (*it).encoder->enc.replaygain.enabled ) { + if( (*it).replaygain != 0 && (*it).replaygain->replaygain.rank > (*it).encoder->enc.replaygain.rank ) { + boolDefault = false; + } + else { + boolDefault = true; + } + } + else { + boolDefault = false; + } + (*it).internalReplayGain = conf->readBoolEntry( "internalReplayGain", boolDefault ); + } +} + +void Config::write( bool sync ) +{ + QTime time; + time.start(); + + writeProfiles(); + writeServiceMenu(); + writeAmarokScript(); + + KConfig *conf = kapp->config(); + + conf->setGroup( "Ripper" ); + conf->writeEntry( "ripper", (currentRipper)?currentRipper->rip.bin:"kio_audiocd" ); + + for( QValueList::Iterator it = formats.begin(); it != formats.end(); ++it ) + { + conf->setGroup( (*it).mime_types.first() ); + if( (*it).encoder ) conf->writeEntry( "encoder", (*it).encoder->enc.bin ); + if( (*it).decoder ) conf->writeEntry( "decoder", (*it).decoder->dec.bin ); + if( (*it).replaygain ) conf->writeEntry( "replaygain", (*it).replaygain->replaygain.bin ); + conf->writeEntry( "compressionLevel", (*it).compressionLevel ); + conf->writeEntry( "internalReplayGain", (*it).internalReplayGain ); + } + + conf->setGroup( "General" ) ; + conf->writeEntry( "configVersion", 300 ); + conf->writeEntry( "startTab", data.general.startTab ); + conf->writeEntry( "lastTab", data.general.lastTab ); + conf->writeEntry( "defaultProfile", data.general.defaultProfile ); + conf->writeEntry( "defaultFormat", data.general.defaultFormat ); +// conf->writeEntry( "defaultOutputDirectory", data.general.defaultOutputDirectory ); + conf->writeEntry( "specifyOutputDirectory", data.general.specifyOutputDirectory ); + conf->writeEntry( "metaDataOutputDirectory", data.general.metaDataOutputDirectory ); + conf->writeEntry( "copyStructureOutputDirectory", data.general.copyStructureOutputDirectory ); + conf->writeEntry( "useVFATNames", data.general.useVFATNames ); + conf->writeEntry( "conflictHandling", data.general.conflictHandling ); + conf->writeEntry( "priority", data.general.priority ); + conf->writeEntry( "numFiles", data.general.numFiles ); + conf->writeEntry( "updateDelay", data.general.updateDelay ); + conf->writeEntry( "askForNewOptions", data.general.askForNewOptions ); + conf->writeEntry( "executeUserScript", data.general.executeUserScript ); + conf->writeEntry( "showToolBar", data.general.showToolBar ); + + conf->setGroup( "Plugins" ); + conf->writeEntry( "checkForUpdates", data.plugins.checkForUpdates ); + + conf->setGroup( "Environment" ); + conf->writeEntry( "directories", data.environment.directories ); + data.environment.foundPrograms.clear(); + for( QMap::Iterator b = binaries.begin(); b != binaries.end(); ++b ) { + if( b.data() != "" ) { + data.environment.foundPrograms.append( b.data() ); + } + } + conf->writeEntry( "foundPrograms", data.environment.foundPrograms ); + + if( sync ) conf->sync(); + + emit configChanged(); + + logger->log( 1000, "wrote preferences: " + QString::number(time.elapsed()) ); +} + +void Config::readProfiles() +{ + int version; + QString name; + ConversionOptions options; + + QDomDocument domTree; + QFile opmlFile( locateLocal("data","soundkonverter/profiles.xml") ); + if( !opmlFile.open( IO_ReadOnly ) ) return; + if( !domTree.setContent( &opmlFile ) ) return; + opmlFile.close(); + + QDomElement root = domTree.documentElement(); + if( root.attribute("type") != "profiles" ) return; + QDomNode node, sub1Node, sub2Node; + node = root.firstChild(); + + while( !node.isNull() ) { + if( node.isElement() && node.nodeName() == "info" ) { + + version = node.toElement().attribute("version").toInt(); + + } + else if( node.isElement() && node.nodeName() == "profile" ) { + + name = node.toElement().attribute("name"); + + sub1Node = node.toElement().firstChild(); + while( !sub1Node.isNull() ) { + if( sub1Node.isElement() && sub1Node.nodeName() == "encodingOptions" ) { +// TODO clean up + options.encodingOptions.sFormat = sub1Node.toElement().attribute("sFormat"); + options.encodingOptions.sQualityMode = sub1Node.toElement().attribute("sQualityMode"); + options.encodingOptions.iQuality = sub1Node.toElement().attribute("iQuality").toInt(); + options.encodingOptions.sBitrateMode = sub1Node.toElement().attribute("sBitrateMode"); + options.encodingOptions.bBitrateRange = sub1Node.toElement().attribute("bBitrateRange").toInt(); + options.encodingOptions.iMinBitrate = sub1Node.toElement().attribute("iMinBitrate").toInt(); + options.encodingOptions.iMaxBitrate = sub1Node.toElement().attribute("iMaxBitrate").toInt(); + + sub2Node = sub1Node.toElement().firstChild(); + while( !sub2Node.isNull() ) { + if( sub2Node.isElement() && sub2Node.nodeName() == "samplingRate" ) { + + options.encodingOptions.samplingRate.bEnabled = sub2Node.toElement().attribute("bEnabled").toInt(); + options.encodingOptions.samplingRate.iSamplingRate = sub2Node.toElement().attribute("iSamplingRate").toInt(); + + } + else if( sub2Node.isElement() && sub2Node.nodeName() == "channels" ) { + + options.encodingOptions.channels.bEnabled = sub2Node.toElement().attribute("bEnabled").toInt(); + options.encodingOptions.channels.sChannels = sub2Node.toElement().attribute("sChannels"); + + } + else if( sub2Node.isElement() && sub2Node.nodeName() == "replaygain" ) { + + options.encodingOptions.replaygain.bEnabled = sub2Node.toElement().attribute("bEnabled").toInt(); + + } + sub2Node = sub2Node.nextSibling(); + } + + options.encodingOptions.sInOutFiles = sub1Node.toElement().attribute("sInOutFiles"); + + } + else if( sub1Node.isElement() && sub1Node.nodeName() == "outputOptions" ) { + + options.outputOptions.mode = (OutputDirectory::Mode)sub1Node.toElement().attribute("mode").toInt(); + options.outputOptions.directory = sub1Node.toElement().attribute("directory"); + + } + sub1Node = sub1Node.nextSibling(); + } + ProfileData profileData; + profileData.name = name; + profileData.options = options; + profiles += profileData; + } + node = node.nextSibling(); + } +} + +void Config::writeProfiles() +{ + QDomDocument domTree; + QDomElement root = domTree.createElement( "soundkonverter" ); + root.setAttribute( "type", "profiles" ); + domTree.appendChild( root ); + + QDomElement info = domTree.createElement( "info" ); + info.setAttribute( "version", "300" ); + root.appendChild( info ); + + for( QValueList::Iterator it = profiles.begin(); it != profiles.end(); ++it ) { + QDomElement profile = domTree.createElement( "profile" ); + profile.setAttribute( "name", (*it).name ); + + QDomElement encodingOptions = domTree.createElement( "encodingOptions" ); + + encodingOptions.setAttribute( "sFormat", (*it).options.encodingOptions.sFormat ); + encodingOptions.setAttribute( "sQualityMode", (*it).options.encodingOptions.sQualityMode ); + encodingOptions.setAttribute( "iQuality", (*it).options.encodingOptions.iQuality ); + encodingOptions.setAttribute( "sBitrateMode", (*it).options.encodingOptions.sBitrateMode ); + encodingOptions.setAttribute( "bBitrateRange", (*it).options.encodingOptions.bBitrateRange ); + encodingOptions.setAttribute( "iMinBitrate", (*it).options.encodingOptions.iMinBitrate ); + encodingOptions.setAttribute( "iMaxBitrate", (*it).options.encodingOptions.iMaxBitrate ); + + QDomElement samplingRate = domTree.createElement( "samplingRate" ); + + samplingRate.setAttribute( "bEnabled", (*it).options.encodingOptions.samplingRate.bEnabled ); + samplingRate.setAttribute( "iSamplingRate", (*it).options.encodingOptions.samplingRate.iSamplingRate ); + + encodingOptions.appendChild( samplingRate ); + + QDomElement channels = domTree.createElement( "channels" ); + + channels.setAttribute( "bEnabled", (*it).options.encodingOptions.channels.bEnabled ); + channels.setAttribute( "sChannels", (*it).options.encodingOptions.channels.sChannels ); + + encodingOptions.appendChild( channels ); + + QDomElement replaygain = domTree.createElement( "replaygain" ); + + replaygain.setAttribute( "bEnabled", (*it).options.encodingOptions.replaygain.bEnabled ); + + encodingOptions.appendChild( replaygain ); + + encodingOptions.setAttribute( "sInOutFiles", (*it).options.encodingOptions.sInOutFiles ); + + profile.appendChild( encodingOptions ); + + QDomElement outputOptions = domTree.createElement( "outputOptions" ); + + outputOptions.setAttribute( "mode", int((*it).options.outputOptions.mode) ); + outputOptions.setAttribute( "directory", (*it).options.outputOptions.directory ); + + profile.appendChild( outputOptions ); + + root.appendChild( profile ); + } + + QFile opmlFile( locateLocal("data","soundkonverter/profiles.xml") ); + if( !opmlFile.open( IO_WriteOnly ) ) return; + + QTextStream ts( &opmlFile ); + ts << domTree.toString(); + + opmlFile.close(); +} + +void Config::writeServiceMenu() +{ + int num; + QString content; + QFile file; + + num = 0; + content = ""; + content += "[Desktop Entry]\n"; + content += "ServiceTypes="; + + for( QValueList::Iterator it = formats.begin(); it != formats.end(); ++it ) { +// if( (*it).encoder != 0 && binaries[(*it).encoder->enc.bin] != "" && (*it).mime_types.first() != "application/octet-stream" ) { +// if( !(*it).encoder->enc.lossy.enabled && !(*it).encoder->enc.lossless.enabled && !(*it).encoder->enc.hybrid.enabled ) continue; +// for( QStringList::Iterator b = (*it).mime_types.begin(); b != (*it).mime_types.end(); ++b ) { +// content += (*b) + ","; +// num++; +// } +// } + if( (*it).decoder != 0 && binaries[(*it).decoder->dec.bin] != "" && (*it).mime_types.first() != "application/octet-stream" ) { + for( QStringList::Iterator b = (*it).mime_types.begin(); b != (*it).mime_types.end(); ++b ) { + content += (*b) + ","; + num++; + } + } + } + + if( num != 0 ) + { + content += "audio/x-wav"; + + content += "\n"; + content += "Icon=soundkonverter\n"; + content += "Actions=ConvertWithSoundkonverter\n\n"; + + content += "[Desktop Action ConvertWithSoundkonverter]\n"; + content += "Name="+i18n("Convert with soundKonverter ...")+"\n"; + content += "Icon=soundkonverter\n"; + content += "Exec=soundkonverter %F\n"; + + file.setName( locateLocal("data","konqueror/servicemenus/")+"convert_with_soundkonverter.desktop" ); + if ( file.open( IO_WriteOnly ) ) { + QTextStream stream( &file ); + stream << content; + file.close(); + } + } + + num = 0; + content = ""; + content += "[Desktop Entry]\n"; + content += "ServiceTypes="; + + for( QValueList::Iterator it = formats.begin(); it != formats.end(); ++it ) { + if( (*it).replaygain != 0 && binaries[(*it).replaygain->replaygain.bin] != "" && (*it).mime_types.first() != "application/octet-stream" ) { + for( QStringList::Iterator b = (*it).mime_types.begin(); b != (*it).mime_types.end(); ++b ) { + content += (*b) + ","; + num++; + } + } + } + + if( num != 0 ) + { + content = content.left(content.length()-1); + + content += "\n"; + content += "Icon=soundkonverter_replaygain\n"; + content += "Actions=AddReplayGainWithSoundkonverter\n\n"; + + content += "[Desktop Action AddReplayGainWithSoundkonverter]\n"; + content += "Name="+i18n("Add Replay Gain with soundKonverter ...")+"\n"; + content += "Icon=soundkonverter_replaygain\n"; + content += "Exec=soundkonverter --replaygain %F\n"; + + file.setName( locateLocal("data","konqueror/servicemenus/")+"add_replaygain_with_soundkonverter.desktop" ); + if( file.open(IO_WriteOnly) ) { + QTextStream st( &file ); + st << content; + file.close(); + } + } +} + +void Config::writeAmarokScript() +{ + int num, num1, num2; + QString content, content1, content2; + QFile file; + + num = 0; + content = ""; + content += "name = soundKonverter\n"; + content += "type = transcode\n\n"; + content += "[Transcode]\n"; + content += "target_formats = "; + + for( QValueList::Iterator it = formats.begin(); it != formats.end(); ++it ) { + if( (*it).encoder != 0 && binaries[(*it).encoder->enc.bin] != "" && (*it).mime_types.first() != "application/octet-stream" ) { + if( !(*it).encoder->enc.lossy.enabled && !(*it).encoder->enc.lossless.enabled && !(*it).encoder->enc.hybrid.enabled ) continue; + for( QStringList::Iterator b = (*it).extensions.begin(); b != (*it).extensions.end(); ++b ) { + if( content.find(" "+(*b).lower()+" ") == -1 ) content += (*b).lower() + " "; + num++; + } + } + } + + if( num != 0 ) // TODO what is, if there are only decoders? + { + content += "wav"; + content += "\n"; + + file.setName( locateLocal("data","amarok/scripts/soundKonverter/")+"soundKonverter.spec" ); + if( file.open(IO_WriteOnly) ) { + QTextStream st( &file ); + st << content; + file.close(); + } + } + + num1 = num2 = 0; + content = content1 = content2 = ""; + + // NOTE duplicate entries won't be shown to the user at any time, so they aren't filtered + for( QValueList::Iterator it = formats.begin(); it != formats.end(); ++it ) { + if( (*it).encoder != 0 && binaries[(*it).encoder->enc.bin] != "" && (*it).mime_types.first() != "application/octet-stream" ) { + if( (*it).encoder->enc.lossless.enabled ) { + for( QStringList::Iterator b = (*it).extensions.begin(); b != (*it).extensions.end(); ++b ) { + if( content1.find(","+(*b).lower()+",") == -1 ) content1 += (*b).lower() + ","; // NOTE the first entry will be shown twice + num1++; + } + } + if( (*it).encoder->enc.hybrid.enabled ) { + for( QStringList::Iterator b = (*it).extensions.begin(); b != (*it).extensions.end(); ++b ) { + if( content2.find(","+(*b).lower()+",") == -1 ) content2 += (*b).lower() + ","; // NOTE the first entry will be shown twice + num2++; + } + } + } + } + + if( num1 != 0 ) + { + content1 = content1.left(content1.length()-1); + content += "Lossless"; + content += "\n"; + content += content1; + content += "\n"; + } + + if( num2 != 0 ) + { + content2 = content2.left(content2.length()-1); + content += "Hybrid"; + content += "\n"; + content += content2; + content += "\n"; + } + + if( num1 != 0 || num2 != 0 ) + { + file.setName( locateLocal("data","amarok/scripts/soundKonverter/")+"formats" ); + if( file.open(IO_WriteOnly) ) { + QTextStream st( &file ); + st << content; + file.close(); + } + } + + KStandardDirs* stdDirs = new KStandardDirs(); + if( !QFile::exists(locateLocal("data","amarok/scripts/soundKonverter/soundKonverter.rb")) ) { + KIO::NetAccess::file_copy( stdDirs->findResource("data","soundkonverter/amarokscript/soundKonverter.rb"), locateLocal("data","amarok/scripts/soundKonverter/soundKonverter.rb"), 0755, true ); + } + if( !QFile::exists(locateLocal("data","amarok/scripts/soundKonverter/README")) ) { + KIO::NetAccess::file_copy( stdDirs->findResource("data","soundkonverter/amarokscript/README"), locateLocal("data","amarok/scripts/soundKonverter/README"), -1, true ); + } + delete stdDirs; +} + +void Config::loadFileInfos() +{} + +void Config::loadPlugins() +{ + // NOTE can be speeded up + + //kdDebug() << "entering: `" << "Config::loadPlugins()" << "'" << endl; + logger->log( 1000, "entering: `Config::loadPlugins()'" ); + QStringList list; + QDir dir; + QString correction_file_mime_type; + + /** a map that holds the _identifier_ and the _version_ number of all plugins */ + QMap pluginMap; + + int version; + QString identifier; + int i; + + ConvertPluginLoader* convertPluginLoader = new ConvertPluginLoader(); + ReplayGainPluginLoader* replaygainPluginLoader = new ReplayGainPluginLoader(); + RipperPluginLoader* ripperPluginLoader = new RipperPluginLoader(); + + KStandardDirs stddir; + QStringList directories = stddir.findDirs( "data", "soundkonverter/plugins/" ); + for( QStringList::Iterator a = directories.begin(); a != directories.end(); ++a ) + { + //kdDebug() << " searching directory: `" << *a << "'" << endl; + logger->log( 1000, " searching directory: `" + *a + "'" ); + dir.setPath( *a ); + list = dir.entryList( "*", QDir::All, QDir::Name ); + for( QStringList::Iterator b = list.begin(); b != list.end(); ++b ) + { + if( *b != "." && *b != ".." && (*b).right(19) == ".soundkonverter.xml" ) + { + //kdDebug() << " found file: `" << *b << "'" << endl; + logger->log( 1000, " found file: `" + *b + "'" ); + if( convertPluginLoader->verifyFile( QString(*a).append(*b) ) != -1 ) + { + version = convertPluginLoader->verifyFile( QString(*a).append(*b) ); + identifier = *b; + identifier.remove( identifier.length() - 19, 19 ); + i = identifier.findRev( "-" ); + identifier.remove( i, identifier.length() - i ); +// i = identifier.find( "." ); +// identifier.remove( 0, i + 1 ); + if( !pluginMap.contains(identifier) ) { + PluginMapData data; + data.version = 0; + pluginMap.insert( identifier, data ); + } + if( pluginMap[identifier].version < version ) + { + pluginMap[identifier].version = version; + pluginMap[identifier].filename = QString(*a).append(*b); + pluginMap[identifier].type = "converter"; + logger->log( 1000, " updating version for: `" + identifier + "'" ); + } + } + else if( replaygainPluginLoader->verifyFile( QString(*a).append(*b) ) != -1 ) + { + version = replaygainPluginLoader->verifyFile( QString(*a).append(*b) ); + identifier = *b; + identifier.remove( identifier.length() - 19, 19 ); + i = identifier.findRev( "-" ); + identifier.remove( i, identifier.length() - i ); +// i = identifier.find( "." ); +// identifier.remove( 0, i + 1 ); + if( !pluginMap.contains(identifier) ) { + PluginMapData data; + data.version = 0; + pluginMap.insert( identifier, data ); + } + if( pluginMap[identifier].version < version ) + { + pluginMap[identifier].version = version; + pluginMap[identifier].filename = QString(*a).append(*b); + pluginMap[identifier].type = "replaygain"; + logger->log( 1000, " updating version for: `" + identifier + "'" ); + } + } + else if( ripperPluginLoader->verifyFile( QString(*a).append(*b) ) != -1 ) + { + version = ripperPluginLoader->verifyFile( QString(*a).append(*b) ); + identifier = *b; + identifier.remove( identifier.length() - 19, 19 ); + i = identifier.findRev( "-" ); + identifier.remove( i, identifier.length() - i ); +// i = identifier.find( "." ); +// identifier.remove( 0, i + 1 ); + if( !pluginMap.contains(identifier) ) { + PluginMapData data; + data.version = 0; + pluginMap.insert( identifier, data ); + } + if( pluginMap[identifier].version < version ) + { + pluginMap[identifier].version = version; + pluginMap[identifier].filename = QString(*a).append(*b); + pluginMap[identifier].type = "ripper"; + logger->log( 1000, " updating version for: `" + identifier + "'" ); + } + } + else + { + //kdDebug() << " file is invalid: `" << *b << "'" << endl; + logger->log( 1000, " file is invalid: `" + *b + "'" ); + } + } + } + } + + for( QMap::Iterator a = pluginMap.begin(); a != pluginMap.end(); ++a ) { + if( a.data().type == "converter" ) + { + ConvertPlugin* plugin = convertPluginLoader->loadFile( a.data().filename ); + if( plugin->info.version != -1 ) + { + if( plugin->enc.hybrid.enabled ) + { + correction_file_mime_type = plugin->enc.hybrid.correction_file_mime_type; + } + if( plugin->enc.enabled ) + { + for( QStringList::Iterator b = plugin->enc.mime_types.begin(); b != plugin->enc.mime_types.end(); ++b ) + { + //kdDebug() << " registering encoder for: `" << *b << "'" << endl; + logger->log( 1000, " registering encoder for: `" + *b + "'" ); + registerFormatFeatures( *b, plugin, 0, 0, correction_file_mime_type ); + } + } + if( plugin->dec.enabled ) + { + for( QStringList::Iterator b = plugin->dec.mime_types.begin(); b != plugin->dec.mime_types.end(); ++b ) + { + //kdDebug() << " registering decoder for: `" << *b << "'" << endl; + logger->log( 1000, " registering decoder for: `" + *b + "'" ); + registerFormatFeatures( *b, 0, plugin, 0, correction_file_mime_type ); + } + } + converters.append( plugin ); + //kdDebug() << " plugin sucessfully loaded: `" << a.key() << "'" << endl; + logger->log( 1000, " plugin sucessfully loaded: `" + a.key() + "'" ); + } + else + { + //kdError() << " failed to load Plugin: `" << a.key() << "'" << endl; + logger->log( 1000, " failed to load Plugin: `" + a.key() + "'" ); + } + } + else if( a.data().type == "replaygain" ) + { + ReplayGainPlugin* plugin = replaygainPluginLoader->loadFile( a.data().filename ); + if( plugin->info.version != -1 ) + { + for( QStringList::Iterator b = plugin->replaygain.mime_types.begin(); b != plugin->replaygain.mime_types.end(); ++b ) + { + //kdDebug() << " registering replaygain for: `" << *b << "'" << endl; + logger->log( 1000, " registering replaygain for: `" + *b + "'" ); + registerFormatFeatures( *b, 0, 0, plugin ); + } + replaygains.append( plugin ); + //kdDebug() << " plugin sucessfully loaded: `" << a.key() << "'" << endl; + logger->log( 1000, " plugin sucessfully loaded: `" + a.key() + "'" ); + } + else + { + //kdError() << " failed to load Plugin: `" << a.key() << "'" << endl; + logger->log( 1000, " failed to load Plugin: `" + a.key() + "'" ); + } + } + else if( a.data().type == "ripper" ) + { + RipperPlugin* plugin = ripperPluginLoader->loadFile( a.data().filename ); + if( plugin->info.version != -1 ) + { + rippers.append( plugin ); + //kdDebug() << " plugin sucessfully loaded: `" << a.key() << "'" << endl; + logger->log( 1000, " plugin sucessfully loaded: `" + a.key() + "'" ); + } + else + { + //kdError() << " failed to load Plugin: `" << a.key() << "'" << endl; + logger->log( 1000, " failed to load Plugin: `" + a.key() + "'" ); + } + } + } + + delete convertPluginLoader; + delete replaygainPluginLoader; + delete ripperPluginLoader; + + // NOTE in order to make a plugin working, there must be a format_infos file. + + // TODO remove duplicate extensions + + FormatInfoLoader* formatInfoLoader = new FormatInfoLoader(); + + //kdDebug() << " trying to open: `" << "soundkonverter/format_infos/"+language+"/" << "'" << endl; +// logger->log( 1000, " trying to open: `soundkonverter/format_infos/" + language + "/'" ); +// directories = stddir.findDirs( "data", "soundkonverter/format_infos/"+language+"/" ); +// if( directories.isEmpty() ) directories = stddir.findDirs( "data", "soundkonverter/format_infos/en/" ); + directories = stddir.findDirs( "data", "soundkonverter/format_infos/" ); + for( QStringList::Iterator a = directories.begin(); a != directories.end(); ++a ) + { + //kdDebug() << " searching directory: `" << *a << "'" << endl; + logger->log( 1000, " searching directory: `" + *a + "'" ); + dir.setPath( *a ); + list = dir.entryList( "*", QDir::All, QDir::Name ); + for( QStringList::Iterator b = list.begin(); b != list.end(); ++b ) + { + if( *b != "." && *b != ".." && (*b).right(4) == ".xml" ) + { + //kdDebug() << " found file: `" << *b << "'" << endl; + logger->log( 1000, " found file: `" + *b + "'" ); + if( formatInfoLoader->verifyFile( QString(*a).append(*b) ) ) + { + FormatInfo* formatInfo = formatInfoLoader->loadFile( QString(*a).append(*b) ); + + for( QValueList::Iterator c = formats.begin(); c != formats.end(); ++c ) { + for( QStringList::Iterator d = formatInfo->mime_types.begin(); d != formatInfo->mime_types.end(); ++d ) { + if( (*c).mime_types.findIndex(*d) != -1 ) { + (*c).description = "

" + formatInfo->description + "

"; + (*c).description.replace("\\n","

\n

"); + for( QStringList::Iterator d = formatInfo->urls.begin(); d != formatInfo->urls.end(); ++d ) { + (*c).description += "\n

" + (*d) + "

"; + } + (*c).compressionType = formatInfo->compressionType; + (*c).size = formatInfo->size; + // add extensions for mime types + logger->log( 1000, " found mime type: `" + *d + "'" ); + QStringList extensions = KMimeType::mimeType( *d )->patterns(); + for( QStringList::Iterator c = extensions.begin(); c != extensions.end(); ++c ) { + (*c).remove( 0, 2 ); + logger->log( 1000, " adding extension: `" + *c + "'" ); + } + (*c).extensions += extensions; + // add extensions (from format file) HACK + extensions = formatInfo->extensions; + if( !extensions.isEmpty() ) { + logger->log( 1000, " found extensions..." ); + for( QStringList::Iterator c = extensions.begin(); c != extensions.end(); ++c ) { + logger->log( 1000, " adding extension: `" + *c + "'" ); + } + (*c).extensions += extensions; + } + // add extensions for correction file mime types + for( QStringList::Iterator d = (*c).correction_file_mime_types.begin(); d != (*c).correction_file_mime_types.end(); ++d ) { + logger->log( 1000, " found correction mime type: `" + *d + "'" ); + QStringList extensions = KMimeType::mimeType( *d )->patterns(); + for( QStringList::Iterator e = extensions.begin(); e != extensions.end(); ++e ) { + (*e).remove( 0, 2 ); + logger->log( 1000, " adding correction extension: `" + *e + "'" ); + (*c).correction_file_extensions += (*e); + } + } + } + } + } + } + } + } + } + + delete formatInfoLoader; +} + +void Config::registerFormatFeatures( const QString &mime_type, + ConvertPlugin* encoder, ConvertPlugin* decoder, + ReplayGainPlugin* replaygain/*, RepairPlugin* repairer*/, + const QString &correction_file_mime_type ) +{ + //kdDebug() << " entering: `" << "Config::registerFormatFeatures( ... )" << "'" << endl; + logger->log( 1000, " entering: `Config::registerFormatFeatures( ... )'" ); + + // iterate through all file formats and search for an existing one + for( QValueList::Iterator it = formats.begin(); it != formats.end(); ++it ) { + if( (*it).mime_types.findIndex(mime_type) != -1 ) { // we found an existing entry for our file format + //kdDebug() << " found an existing entry: `" << mime_type << "'" << endl; + logger->log( 1000, " found an existing entry: `" + mime_type + "'" ); + + if( encoder != 0 ) (*it).encoders.append( encoder ); +// if( (*it).encoder == 0 && encoder != 0 ) (*it).encoder = encoder; +// if( (*it).encoder != 0 && binaries[(*it).encoder.enc.bin] == "" ) + if( decoder != 0 ) (*it).decoders.append( decoder ); +// if( (*it).decoder == 0 && decoder != 0 ) (*it).decoder = decoder; + if( replaygain != 0 ) (*it).replaygains.append( replaygain ); +// if( (*it).replaygain == 0 && replaygain != 0 ) (*it).replaygain = replaygain; + //if( repairer ) (*it).repairer.append( repairer );*/ + if( !correction_file_mime_type.isEmpty() ) (*it).correction_file_mime_types.append( correction_file_mime_type ); + + // everything done, we can return! + return; + } + } + //kdDebug() << " creating a new entry: `" << mime_type << "'" << endl; + logger->log( 1000, " creating a new entry: `" + mime_type + "'" ); + + // well it seems, we haven't found an entry. create a new! + QValueList::Iterator newItem = formats.append( FormatItem() ); + (*newItem).mime_types = mime_type; + if( encoder != 0 ) (*newItem).encoders.append( encoder ); +// if( encoder != 0 ) (*newItem).encoder = encoder; + if( decoder != 0 ) (*newItem).decoders.append( decoder ); +// if( decoder != 0 ) (*newItem).decoder = decoder; + if( replaygain != 0 ) (*newItem).replaygains.append( replaygain ); +// if( replaygain != 0 ) (*newItem).replaygain = replaygain; + //if( repairer ) (*newItem).repairer.append( repairer ); + if( !correction_file_mime_type.isEmpty() ) (*newItem).correction_file_mime_types.append( correction_file_mime_type ); + +} + +/*void Config::registerFileFormat( const QString &mime_type, const QString &option, const QString &value ) +{ + // iterate through all file formats and search for an existing one + for( QValueList::Iterator it = formats.begin(); it != formats.end(); ++it ) { + if( (*it).mime_types.findIndex(mime_type) != -1 ) { // we found an existing entry for our file format + if( option == "mime_type" ) (*it).mime_types.append( value ); + //else if( option == "description" ) // TODO implement a qmap ?! + else if( option == "size" ) (*it).size = value.toInt(); + else if( option == "compression_type" ) { + if( value == "lossy" ) (*it).compressionType = FormatInfo::lossy; + else if( value == "lossless" ) (*it).compressionType = FormatInfo::lossless; + else (*it).compressionType = FormatInfo::hybrid; + } + + // everything done, we can return! + return; + } + } + + // well it seems, we haven't found an entry. create a new! + QValueList::Iterator newItem = formats.append( FormatItem() ); + if( option == "mime_type" ) (*newItem).mime_types.append( value ); + //else if( option == "description" ) // TODO implement a qmap ?! + else if( option == "size" ) (*newItem).size = value.toInt(); + else if( option == "compression_type" ) { + if( value == "lossy" ) (*newItem).compressionType = FormatInfo::lossy; + else if( value == "lossless" ) (*newItem).compressionType = FormatInfo::lossless; + else (*newItem).compressionType = FormatInfo::hybrid; + } +}*/ + +ConvertPlugin* Config::encoderForFormat( const QString &format ) +{ + // iterate through all file formats and search for our format in mime_types and extensions + for( QValueList::Iterator it = formats.begin(); it != formats.end(); ++it ) { + if( (*it).mime_types.findIndex(format) != -1 || (*it).extensions.findIndex(format) != -1 ) { // we found it + return (*it).encoder; + } + } + + return 0; +} + +ConvertPlugin* Config::decoderForFormat( const QString &format ) +{ + // iterate through all file formats and search for our format in mime_types and extensions + for( QValueList::Iterator it = formats.begin(); it != formats.end(); ++it ) { + if( (*it).mime_types.findIndex(format) != -1 || (*it).extensions.findIndex(format) != -1 ) { // we found it + return (*it).decoder; + } + } + + return 0; +} + +ReplayGainPlugin* Config::replaygainForFormat( const QString &format ) +{ + // iterate through all file formats and search for our format in mime_types and extensions + for( QValueList::Iterator it = formats.begin(); it != formats.end(); ++it ) { + if( (*it).mime_types.findIndex(format) != -1 || (*it).extensions.findIndex(format) != -1 ) { // we found it + return (*it).replaygain; + } + } + + return 0; +} + +FormatItem* Config::getFormatItem( const QString &format ) +{ + // iterate through all file formats and search for our format in mime_types and extensions + for( QValueList::Iterator it = formats.begin(); it != formats.end(); ++it ) { + if( (*it).mime_types.findIndex(format) != -1 || (*it).extensions.findIndex(format) != -1 ) { // we found it + return &(*it); + } + } + + return 0; +} + +// NOTE speed up the following 3 functions (cache the data) (use the extensions variable in FormatItem) +// NOTE seems to be called too often ??? +QStringList Config::allFormats() +{ + QStringList list; + + //kdDebug() << "entering: `" << "Config::allFormats()" << "'" << endl; + logger->log( 1000, "entering: `Config::allFormats()'" ); + + for( QValueList::Iterator it = formats.begin(); it != formats.end(); ++it ) { + //kdDebug() << " mime type: `" << (*it).mime_types.first() << "'" << endl; + logger->log( 1000, " mime type: `" + (*it).mime_types.first() + "'" ); + if( (*it).mime_types.first() != "application/octet-stream" ) { +// QString extension = KMimeType::mimeType( (*it).mime_types.first() )->patterns().first().lower(); +// extension.remove( 0, 2 ); + QString extension = (*it).extensions.first().lower(); + //kdDebug() << " extension: `" << extension << "'" << endl; + logger->log( 1000, " extension: `" + extension + "'" ); + if( !extension.isEmpty() && !list.contains(extension) ) { + list.append( extension ); + //kdDebug() << " (added)" << endl; + logger->log( 1000, " (added)" ); + } + } + } + + return list; +} + +QStringList Config::allEncodableFormats() +{ + QStringList list; + + //kdDebug() << "entering: `" << "Config::allEncodableFormats()" << "'" << endl; + logger->log( 1000, "entering: `Config::allEncodableFormats()'" ); + + for( QValueList::Iterator it = formats.begin(); it != formats.end(); ++it ) { + //kdDebug() << " mime type: `" << (*it).mime_types.first() << "'" << endl; + logger->log( 1000, " mime type: `" + (*it).mime_types.first() + "'" ); + if( (*it).encoder != 0 && binaries[(*it).encoder->enc.bin] != "" && (*it).mime_types.first() != "application/octet-stream" ) { + if( !(*it).encoder->enc.lossy.enabled && !(*it).encoder->enc.lossless.enabled && !(*it).encoder->enc.hybrid.enabled ) continue; +// QString extension = KMimeType::mimeType( (*it).mime_types.first() )->patterns().first().lower(); +// extension.remove( 0, 2 ); + QString extension = (*it).extensions.first().lower(); + //kdDebug() << " extension: `" << extension << "'" << endl; + logger->log( 1000, " extension: `" + extension + "'" ); + if( !extension.isEmpty() && !list.contains(extension) ) { + list.append( extension ); + //kdDebug() << " (added)" << endl; + logger->log( 1000, " (added)" ); + } + } + } + + return list; +} + +QStringList Config::allLossyEncodableFormats() +{ + QStringList list; + + //kdDebug() << "entering: `" << "Config::allLossyEncodableFormats()" << "'" << endl; +// logger->log( 1000, "entering: `Config::allLossyEncodableFormats()'" ); + + for( QValueList::Iterator it = formats.begin(); it != formats.end(); ++it ) { + //kdDebug() << " mime type: `" << (*it).mime_types.first() << "'" << endl; +// logger->log( 1000, " mime type: `" + (*it).mime_types.first() + "'" ); + if( (*it).encoder != 0 && binaries[(*it).encoder->enc.bin] != "" && (*it).encoder->enc.lossy.enabled && (*it).compressionType & FormatInfo::lossy && (*it).mime_types.first() != "application/octet-stream" ) { +// QString extension = KMimeType::mimeType( (*it).mime_types.first() )->patterns().first().lower(); +// extension.remove( 0, 2 ); + QString extension = (*it).extensions.first().lower(); + //kdDebug() << " extension: `" << extension << "'" << endl; +// logger->log( 1000, " extension: `" + extension + "'" ); + if( !extension.isEmpty() && !list.contains(extension) ) { + list.append( extension ); + //kdDebug() << " (added)" << endl; +// logger->log( 1000, " (added)" ); + } + } + } + + return list; +} + +QStringList Config::allLosslessEncodableFormats() +{ + QStringList list; + + //kdDebug() << "entering: `" << "Config::allLosslessEncodableFormats()" << "'" << endl; + logger->log( 1000, "entering: `Config::allLosslessEncodableFormats()'" ); + + for( QValueList::Iterator it = formats.begin(); it != formats.end(); ++it ) { + //kdDebug() << " mime type: `" << (*it).mime_types.first() << "'" << endl; + logger->log( 1000, " mime type: `" + (*it).mime_types.first() + "'" ); + if( (*it).encoder != 0 && binaries[(*it).encoder->enc.bin] != "" && (*it).encoder->enc.lossless.enabled && (*it).compressionType & FormatInfo::lossless && (*it).mime_types.first() != "application/octet-stream" ) { +// QString extension = KMimeType::mimeType( (*it).mime_types.first() )->patterns().first().lower(); +// extension.remove( 0, 2 ); + QString extension = (*it).extensions.first().lower(); + //kdDebug() << " extension: `" << extension << "'" << endl; + logger->log( 1000, " extension: `" + extension + "'" ); + if( !extension.isEmpty() && !list.contains(extension) ) { + list.append( extension ); + //kdDebug() << " (added)" << endl; + logger->log( 1000, " (added)" ); + } + } + } + + return list; +} + +QStringList Config::allHybridEncodableFormats() +{ + QStringList list; + + //kdDebug() << "entering: `" << "Config::allHybridEncodableFormats()" << "'" << endl; + logger->log( 1000, "entering: `Config::allHybridEncodableFormats()'" ); + + for( QValueList::Iterator it = formats.begin(); it != formats.end(); ++it ) { + //kdDebug() << " mime type: `" << (*it).mime_types.first() << "'" << endl; + logger->log( 1000, " mime type: `" + (*it).mime_types.first() + "'" ); + if( (*it).encoder != 0 && binaries[(*it).encoder->enc.bin] != "" && (*it).encoder->enc.hybrid.enabled && (*it).compressionType & FormatInfo::hybrid && (*it).mime_types.first() != "application/octet-stream" ) { +// QString extension = KMimeType::mimeType( (*it).mime_types.first() )->patterns().first().lower(); +// extension.remove( 0, 2 ); + QString extension = (*it).extensions.first().lower(); + //kdDebug() << " extension: `" << extension << "'" << endl; + logger->log( 1000, " extension: `" + extension + "'" ); + if( !extension.isEmpty() && !list.contains(extension) ) { + list.append( extension ); + //kdDebug() << " (added)" << endl; + logger->log( 1000, " (added)" ); + } + } + } + + return list; +} + +QString Config::getCorrectionExtension( const QString &format ) +{ + // iterate through all file formats and search for our format + for( QValueList::Iterator it = formats.begin(); it != formats.end(); ++it ) { + if( (*it).mime_types.findIndex(format) != -1 || (*it).extensions.findIndex(format) != -1 ) { // we found it + return (*it).correction_file_extensions.first(); + } + } + + return ""; +} + +QString Config::getFormatDescription( const QString &format ) // NOTE could be removed +{ + // iterate through all file formats and search for our format + for( QValueList::Iterator it = formats.begin(); it != formats.end(); ++it ) { + if( (*it).mime_types.findIndex(format) != -1 || (*it).extensions.findIndex(format) != -1 ) { // we found it + return (*it).description; + } + } + + return ""; +} + +void Config::addProfile( const QString &name, const ConversionOptions& profile ) +{ + ProfileData profileData; + profileData.name = name; + profileData.options = profile; + profiles += profileData; + if( name != i18n("Last used") && name != "Last used" ) writeProfiles(); // will only be saved at app exit, when saving everything anyway + emit configChanged(); +} + +void Config::removeProfile( const QString &name ) +{ + for( QValueList::Iterator it = profiles.begin(); it != profiles.end(); ++it ) { + if( (*it).name == name ) { + profiles.remove( it ); + if( name != i18n("Last used") && name != "Last used" ) writeProfiles(); // will only be saved at app exit, when saving everything anyway + return; + } + } + emit configChanged(); +} + +ConversionOptions Config::getProfile( const QString &name ) +{ + for( QValueList::Iterator it = profiles.begin(); it != profiles.end(); ++it ) { + if( /*(*it).name != i18n("Last used") &&*/ (*it).name == name ) { + return (*it).options; + } + } + + ConversionOptions options; + options.encodingOptions.sFormat = ""; + return options; +} + +QString Config::getProfileName( const ConversionOptions& options ) +{ + if( options.encodingOptions.sQualityMode == i18n("Lossless") ) { + return i18n("Lossless"); + } + + if( options.encodingOptions.sQualityMode == i18n("Hybrid") ) { + return i18n("Hybrid"); + } + + for( QValueList::Iterator it = profiles.begin(); it != profiles.end(); ++it ) { + if( (*it).name != i18n("Last used") && (*it).options.nearlyEqual( options ) ) { + return (*it).name; + } + } + + ConvertPlugin* plugin = encoderForFormat( options.encodingOptions.sFormat ); + if( plugin != 0 ) { + if( plugin->enc.lossy.quality.enabled ) { + if( options.encodingOptions.sQualityMode == i18n("Quality") && options.encodingOptions.iQuality == 20 && + options.encodingOptions.bBitrateRange == false && + options.encodingOptions.samplingRate.bEnabled == true && options.encodingOptions.samplingRate.iSamplingRate == 22050 && + options.encodingOptions.channels.bEnabled == true && options.encodingOptions.channels.sChannels == i18n("Mono") && + options.encodingOptions.sInOutFiles == binaries[plugin->enc.bin] + " " + plugin->enc.in_out_files ) { + return i18n("Very low"); + } + if( options.encodingOptions.sQualityMode == i18n("Quality") && options.encodingOptions.iQuality == 30 && + options.encodingOptions.bBitrateRange == false && + options.encodingOptions.samplingRate.bEnabled == true && options.encodingOptions.samplingRate.iSamplingRate == 22050 && + options.encodingOptions.channels.bEnabled == false && + options.encodingOptions.sInOutFiles == binaries[plugin->enc.bin] + " " + plugin->enc.in_out_files ) { + return i18n("Low"); + } + if( options.encodingOptions.sQualityMode == i18n("Quality") && options.encodingOptions.iQuality == 40 && + options.encodingOptions.bBitrateRange == false && + options.encodingOptions.samplingRate.bEnabled == false && + options.encodingOptions.channels.bEnabled == false && + options.encodingOptions.sInOutFiles == binaries[plugin->enc.bin] + " " + plugin->enc.in_out_files ) { + return i18n("Medium"); + } + if( options.encodingOptions.sQualityMode == i18n("Quality") && options.encodingOptions.iQuality == 50 && + options.encodingOptions.bBitrateRange == false && + options.encodingOptions.samplingRate.bEnabled == false && + options.encodingOptions.channels.bEnabled == false && + options.encodingOptions.sInOutFiles == binaries[plugin->enc.bin] + " " + plugin->enc.in_out_files ) { + return i18n("High"); + } + if( options.encodingOptions.sQualityMode == i18n("Quality") && options.encodingOptions.iQuality == 60 && + options.encodingOptions.bBitrateRange == false && + options.encodingOptions.samplingRate.bEnabled == false && + options.encodingOptions.channels.bEnabled == false && + options.encodingOptions.sInOutFiles == binaries[plugin->enc.bin] + " " + plugin->enc.in_out_files ) { + return i18n("Very high"); + } + } + if( plugin->enc.lossy.bitrate.abr.enabled || plugin->enc.lossy.bitrate.cbr.enabled ) { + if( options.encodingOptions.sQualityMode == i18n("Bitrate") && options.encodingOptions.iQuality == 64 && + options.encodingOptions.bBitrateRange == false && + options.encodingOptions.samplingRate.bEnabled == true && options.encodingOptions.samplingRate.iSamplingRate == 22050 && + options.encodingOptions.channels.bEnabled == true && options.encodingOptions.channels.sChannels == i18n("Mono") && + options.encodingOptions.sInOutFiles == binaries[plugin->enc.bin] + " " + plugin->enc.in_out_files ) { + return i18n("Very low"); + } + if( options.encodingOptions.sQualityMode == i18n("Bitrate") && options.encodingOptions.iQuality == 96 && + options.encodingOptions.bBitrateRange == false && + options.encodingOptions.samplingRate.bEnabled == true && options.encodingOptions.samplingRate.iSamplingRate == 22050 && + options.encodingOptions.channels.bEnabled == false && + options.encodingOptions.sInOutFiles == binaries[plugin->enc.bin] + " " + plugin->enc.in_out_files ) { + return i18n("Low"); + } + if( options.encodingOptions.sQualityMode == i18n("Bitrate") && options.encodingOptions.iQuality == 192 && + options.encodingOptions.bBitrateRange == false && + options.encodingOptions.samplingRate.bEnabled == false && + options.encodingOptions.channels.bEnabled == false && + options.encodingOptions.sInOutFiles == binaries[plugin->enc.bin] + " " + plugin->enc.in_out_files ) { + return i18n("Medium"); + } + if( options.encodingOptions.sQualityMode == i18n("Bitrate") && options.encodingOptions.iQuality == 240 && + options.encodingOptions.bBitrateRange == false && + options.encodingOptions.samplingRate.bEnabled == false && + options.encodingOptions.channels.bEnabled == false && + options.encodingOptions.sInOutFiles == binaries[plugin->enc.bin] + " " + plugin->enc.in_out_files ) { + return i18n("High"); + } + if( options.encodingOptions.sQualityMode == i18n("Bitrate") && options.encodingOptions.iQuality == 320 && + options.encodingOptions.bBitrateRange == false && + options.encodingOptions.samplingRate.bEnabled == false && + options.encodingOptions.channels.bEnabled == false && + options.encodingOptions.sInOutFiles == binaries[plugin->enc.bin] + " " + plugin->enc.in_out_files ) { + return i18n("Very high"); + } + } + /*{ + if( options.encodingOptions.bBitrateRange == false && + options.encodingOptions.samplingRate.bEnabled == true && options.encodingOptions.samplingRate.iSamplingRate == 22050 && + options.encodingOptions.channels.bEnabled == true && options.encodingOptions.channels.sChannels == i18n("Mono") && + options.encodingOptions.sInOutFiles == binaries[plugin->enc.bin] + " " + plugin->enc.in_out_files ) { + return i18n("Very low"); + } + if( options.encodingOptions.bBitrateRange == false && + options.encodingOptions.samplingRate.bEnabled == true && options.encodingOptions.samplingRate.iSamplingRate == 22050 && + options.encodingOptions.channels.bEnabled == false && + options.encodingOptions.sInOutFiles == binaries[plugin->enc.bin] + " " + plugin->enc.in_out_files ) { + return i18n("Low"); + } + if( options.encodingOptions.bBitrateRange == false && + options.encodingOptions.samplingRate.bEnabled == false && + options.encodingOptions.channels.bEnabled == false && + options.encodingOptions.sInOutFiles == binaries[plugin->enc.bin] + " " + plugin->enc.in_out_files ) { + return i18n("Medium"); + } + if( options.encodingOptions.bBitrateRange == false && + options.encodingOptions.samplingRate.bEnabled == false && + options.encodingOptions.channels.bEnabled == false && + options.encodingOptions.sInOutFiles == binaries[plugin->enc.bin] + " " + plugin->enc.in_out_files ) { + return i18n("High"); + } + if( options.encodingOptions.bBitrateRange == false && + options.encodingOptions.samplingRate.bEnabled == false && + options.encodingOptions.channels.bEnabled == false && + options.encodingOptions.sInOutFiles == binaries[plugin->enc.bin] + " " + plugin->enc.in_out_files ) { + return i18n("Very high"); + } + }*/ + } + return i18n("User defined"); +} + +QStringList Config::getAllProfiles() +{ + QStringList list; + + for( QValueList::Iterator it = profiles.begin(); it != profiles.end(); ++it ) { + /*if( (*it).name != i18n("Last used") )*/ list += (*it).name; + } + + return list; +} + +bool Config::acceptFile( const QString& format ) +{ + if( format == "audio/x-wav" || format == "wav" ) return true; + + for( QValueList::Iterator it = formats.begin(); it != formats.end(); ++it ) { + if( (*it).mime_types.findIndex(format) != -1 || (*it).extensions.findIndex(format) != -1 ) { // we found it + if( (*it).decoder != 0 ) return true; + } + } + + return false; +} + +bool Config::acceptReplayGainFile( const QString& format ) +{ + for( QValueList::Iterator it = formats.begin(); it != formats.end(); ++it ) { + if( (*it).mime_types.findIndex(format) != -1 || (*it).extensions.findIndex(format) != -1 ) { // we found it + if( (*it).replaygain != 0 ) return true; + } + } + + return false; +} + +QString Config::fileFilter( bool wav ) +{ + QString filter1; + if( wav ) filter1 += "*.wav *.WAV *.Wav"; + QString filter2; + if( wav ) filter2 += "\n*.wav *.WAV *.Wav|wav " + i18n("files") + " (*.wav)"; + QString temp; + + for( QValueList::Iterator a = formats.begin(); a != formats.end(); ++a ) { + if( (*a).decoder != 0 ) { + temp = ""; + for( QStringList::Iterator b = (*a).extensions.begin(); b != (*a).extensions.end(); ++b ) { + filter1 += " *." + (*b); + if( !temp.contains(*b,false) ) temp += " *." + (*b).lower(); + } + //temp.stripWhiteSpace(); // NOTE doesn't work + if( temp != "" && temp.length() < 80 ) { + temp.remove( 0, 1 ); + temp = "\n" + temp + "|" + (*a).extensions.first() + " " + i18n("files") + " (" + temp + ")"; + if( !filter2.contains(temp) ) { // HACK when unsing multiple mime types, there were too much entries + filter2 += temp; + } + } + else if( temp != "" ) { + temp.remove( 0, 1 ); + temp = "\n" + temp + "|" + (*a).extensions.first() + " " + i18n("files"); + if( !filter2.contains(temp) ) { // HACK when unsing multiple mime types, there were too much entries + filter2 += temp; + } + } + } + } + + filter1.stripWhiteSpace(); + filter2.stripWhiteSpace(); + + return filter1 + "|" + i18n("all supported formats") + "\n*.*|" + i18n("all formats") + filter2; +} + +QStringList Config::fileTypes( bool wav ) +{ + QStringList types; + if( wav ) types.append( "wav" ); + QString temp; + + for( QValueList::Iterator a = formats.begin(); a != formats.end(); ++a ) { + if( (*a).decoder != 0 ) { + temp = ""; + for( QStringList::Iterator b = (*a).extensions.begin(); b != (*a).extensions.end(); ++b ) { + if( !temp.contains(*b,false) ) temp.append( (*b).lower() + ", " ); + } + if( temp != "" ) { + temp = temp.left( temp.length() - 2 ); + if( types.findIndex(temp) == -1 ) types.append( temp ); + } + } + } + + return types; +} + +QString Config::replayGainFilter() +{ + QString filter1; + QString filter2; + QString temp; + + for( QValueList::Iterator a = formats.begin(); a != formats.end(); ++a ) { + if( (*a).replaygain != 0 ) { + temp = ""; + for( QStringList::Iterator b = (*a).extensions.begin(); b != (*a).extensions.end(); ++b ) { + filter1 += " *." + (*b); + if( !temp.contains(*b,false) ) temp += " *." + (*b).lower(); + } + //temp.stripWhiteSpace(); // NOTE doesn't work + if( temp != "" && temp.length() < 80 ) { + temp.remove( 0, 1 ); + filter2 += "\n" + temp + "|" + (*a).extensions.first() + " " + i18n("files") + " (" + temp + ")"; + } + else if( temp != "" ) { + temp.remove( 0, 1 ); + filter2 += "\n" + temp + "|" + (*a).extensions.first() + " " + i18n("files"); + } + } + } + + filter1.stripWhiteSpace(); + filter2.stripWhiteSpace(); + + return filter1 + "|" + i18n("all supported formats") + "\n*.*|" + i18n("all formats") + filter2; +} + +QStringList Config::replayGainFileTypes() +{ + QStringList types; + QString temp; + + for( QValueList::Iterator a = formats.begin(); a != formats.end(); ++a ) { + if( (*a).replaygain != 0 ) { + temp = ""; + for( QStringList::Iterator b = (*a).extensions.begin(); b != (*a).extensions.end(); ++b ) { + if( !temp.contains(*b,false) ) temp.append( (*b).lower() + ", " ); + } + if( temp != "" ) { + temp = temp.left( temp.length() - 2 ); + if( types.findIndex(temp) == -1 ) types.append( temp ); + } + } + } + + return types; +} + + diff --git a/src/config.h b/src/config.h new file mode 100755 index 0000000..130ddf9 --- /dev/null +++ b/src/config.h @@ -0,0 +1,354 @@ + + +#ifndef CONFIG_H +#define CONFIG_H + +#include "formatinfoloader.h" +#include "conversionoptions.h" + +#include +#include +#include +#include + +class Logger; +class ConvertPlugin; +//class ConvertPluginLoader; +class ReplayGainPlugin; +//class ReplayGainPluginLoader; +class RipperPlugin; +struct ProfileData; + + +/** + * @short Format items for the format list + * @author Daniel Faust + * @version 0.3 + */ +class FormatItem +{ +public: + /** + * Constructor + */ + FormatItem(); + + /** + * Destructor + */ + virtual ~FormatItem(); + + QStringList mime_types; + QStringList extensions; // for easy use + QStringList correction_file_mime_types; + QStringList correction_file_extensions; // for easy use + QString description; + FormatInfo::CompressionType compressionType; + int compressionLevel; // the value from the config dialog + bool internalReplayGain; + int size; + QValueList encoders; + QValueList decoders; + QValueList replaygains; + //QValueList repairers; + ConvertPlugin* encoder; + ConvertPlugin* decoder; + ReplayGainPlugin* replaygain; + //RepairerPlugin* repairer; +}; + + +/** + * @short Configuration class + * @author Daniel Faust + * @version 0.3 + */ +class Config : public QObject +{ + Q_OBJECT +public: + /** + * Constructor + */ + Config( Logger* ); + + /** + * Destructor + */ + virtual ~Config(); + + /** + * Read the preferences from the configuration file + */ + void read(); + + /** + * Write the preferences to the configuration file + */ + void write( bool sync = true ); + + /** + * Read the profiles from the profiles file + */ + void readProfiles(); + + /** + * Write the profiles to the profiles file + */ + void writeProfiles(); + + /** + * Get the encoder for a given file format (mime type or extension) + */ + ConvertPlugin* encoderForFormat( const QString &format ); + + /** + * Get the decoder for a given file format (mime type or extension) + */ + ConvertPlugin* decoderForFormat( const QString &format ); + + /** + * Get the decoder for a given file format (mime type or extension) + */ + ReplayGainPlugin* replaygainForFormat( const QString &format ); + + /** + * Get the format information for a given file format (mime type or extension) + */ + FormatItem* getFormatItem( const QString &format ); + + /** + * Get the current ripper + */ + RipperPlugin* getCurrentRipper() { return currentRipper; } + + /** + * Set the current ripper + */ + void setCurrentRipper( RipperPlugin* ripper ) { currentRipper = ripper; } + + /** + * Returns a list of all loaded rippers + */ + QValueList allRippers() { return rippers; } + + /** + * Returns a list of all loaded converters + */ + QValueList allConverters() { return converters; } + + /** + * Returns a list of all loaded replaygains + */ + QValueList allReplayGains() { return replaygains; } + + /** + * Returns a list of all known file formats + */ + QStringList allFormats(); + + /** + * Returns a list of all known encodeable file formats + */ + QStringList allEncodableFormats(); + + /** + * Returns a list of all known lossy encodeable file formats + */ + QStringList allLossyEncodableFormats(); + + /** + * Returns a list of all known lossless encodeable file formats + */ + QStringList allLosslessEncodableFormats(); + + /** + * Returns a list of all known hybrid encodeable file formats + */ + QStringList allHybridEncodableFormats(); + + /** + * Returns the extension of the correction file format for the given format + * If there is nor correction file format, the returned string is empty + */ + QString getCorrectionExtension( const QString &format ); + + /** + * Returns a localized description for the given format + */ + QString getFormatDescription( const QString &format ); + + /** + * Add a new profile + */ + void addProfile( const QString &name, const ConversionOptions& profile ); + + /** + * Remove a new profile + */ + void removeProfile( const QString &name ); + + /** + * Returns the conversion options for a profile + */ + ConversionOptions getProfile( const QString &name ); + + /** + * Returns the name of the profile with conversion options @p options + */ + QString getProfileName( const ConversionOptions& options ); + + /** + * Returns a list of all user defined profiles + */ + QStringList getAllProfiles(); + + /** + * Returns true if the @p file can be added to the conversion list (can be decoded) + */ + bool acceptFile( const QString& format ); + + /** + * Returns true if the @p file can be added to the replay gain tool + */ + bool acceptReplayGainFile( const QString& format ); + + /** + * Returns a file filter suitable for the file open dialog + */ + QString fileFilter( bool wav = true ); + + /** + * Returns a string list of supported file formats + */ + QStringList fileTypes( bool wav = true ); + + /** + * Returns a file filter suitable for the file open dialog for the replay gain scanner + */ + QString replayGainFilter(); + + /** + * Returns a string list of Replay Gain supported file formats + */ + QStringList replayGainFileTypes(); + + struct Data { + struct General { + int startTab; + int lastTab; + QString defaultProfile; + QString defaultFormat; +// QString defaultOutputDirectory; + QString specifyOutputDirectory; + QString metaDataOutputDirectory; + QString copyStructureOutputDirectory; + int priority; + bool useVFATNames; + int conflictHandling; + int numFiles; + int updateDelay; + bool askForNewOptions; + bool executeUserScript; + bool showToolBar; + } general; + struct Plugins { + bool checkForUpdates; + } plugins; + struct Environment { + QStringList directories; + QStringList foundPrograms; + } environment; + struct App { + int configVersion; + } app; + } data; + + bool onlinePluginsChanged; + bool backendsChanged; + + QMap binaries; + +private: + struct PluginMapData { + int version; + QString filename; + QString type; + }; + + Logger* logger; + + /** holds all known formats */ + QValueList formats; + + /** holds all known rippers */ + QValueList rippers; + RipperPlugin* currentRipper; + + /** holds all known converters */ + QValueList converters; + /** holds all known replaygain apps */ + QValueList replaygains; + /* holds all known file repairing apps */ +// QValueList repairer; + + //ConvertPluginLoader* convertPluginLoader; + //ReplayGainPluginLoader* replaygainPluginLoader; + + /** holds all user defined profiles */ + QValueList profiles; + + /** + * Load the files with the file infos (format descriptions, file size, etc.) + */ + void loadFileInfos(); + + /** + * Load all plugins that can be found + */ + void loadPlugins(); + + /** + * A plugin wants to register it's features for a file format + * @p binary The binary name of the app that wants to register it's features + * @p extension The file name extension for that is wants to register + * @p features The features of the app for that extension + */ + void registerFormatFeatures( const QString &mime_type, + ConvertPlugin* encoder = 0, ConvertPlugin* decoder = 0, + ReplayGainPlugin* replaygain = 0/*, RepairPlugin* repairer = 0*/, + const QString &correction_file_mime_type = QString::null ); + + /** + * Generate the service menu + */ + void writeServiceMenu(); + + /** + * Copy the amarok script + */ + void writeAmarokScript(); + + /* + * We have new inforamtion for a file format + * @p extension The file name extension for that is wants to register + * @p newSynonym Register a new synonym for this file format? + * @p newMimeType Register a new mime type for this file format? + * @p newDescription Register a new description for this file format? + * @p newSize Register a new size for this file format for calculating the progress? + */ + /*void registerFileFormat( const QString &extension, const QString &newSynonym = QString::null, + const QString &newMimeType = QString::null, + const QString &newDescription = QString::null, + int newSize = 0, FormatInfo::CompressionType newCompressionType = FormatInfo::lossy );*/ + //void registerFileFormat( const QString &mime_type, const QString &option, const QString &value ); + // NOTE this function is obsolete. + // after loading all plugins and creating all neccessary file format items, + // sk will search for format info files and update the items. + +signals: + void configChanged(); + +}; + +#endif // CONFIG_H diff --git a/src/configbackendspage.cpp b/src/configbackendspage.cpp new file mode 100755 index 0000000..d7b1589 --- /dev/null +++ b/src/configbackendspage.cpp @@ -0,0 +1,493 @@ + +#include "configbackendspage.h" +#include "convertpluginloader.h" +#include "replaygainpluginloader.h" +#include "ripperpluginloader.h" +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +ConfigBackendsPage::ConfigBackendsPage( Config* _config, QMap* _binaries, QWidget* parent, const char *name ) + : ConfigPageBase( parent, name ) +{ + config = _config; + binaries = _binaries; + + grid = new QGridLayout( parent ); + scrollView = new KScrollView( parent, "scrollView" ); + scrollView->setResizePolicy( QScrollView::AutoOneFit ); + grid->addWidget( scrollView, 0, 0 ); + box = new QVBox( scrollView->viewport() ); + box->setMargin( 11 ); + box->setSpacing( 6 ); + scrollView->addChild( box ); + + QHBox* legendBox = new QHBox( box ); + legendBox->setMargin( 0 ); + legendBox->setSpacing( 6 ); + KStandardDirs* stdDirs = new KStandardDirs(); + QLabel* lLegendLabel = new QLabel( i18n("Legend")+":", legendBox, "lLegendLabel" ); + QLabel* lLegendGreen = new QLabel( "", legendBox, "lLegendGreen" ); + lLegendGreen->setPixmap( QPixmap(stdDirs->findResource("data","soundkonverter/pics/ledgreen_legend.png")) ); + QLabel* lLegendFull = new QLabel( i18n("Full support"), legendBox, "lLegendFull" ); + QLabel* lLegendYellow = new QLabel("",legendBox,"lLegendYellow"); + lLegendYellow->setPixmap( QPixmap(stdDirs->findResource("data","soundkonverter/pics/ledyellow_legend.png")) ); + QLabel* lLegendMost = new QLabel( i18n("Most supported"), legendBox, "lLegendMost" ); + QLabel* lLegendRed = new QLabel( "", legendBox, "lLegendRed" ); + lLegendRed->setPixmap( QPixmap(stdDirs->findResource("data","soundkonverter/pics/ledred_legend.png")) ); + QLabel* lLegendBasic = new QLabel( i18n("Basic support"), legendBox, "lLegendBasic" ); + legendBox->setStretchFactor( lLegendLabel, 1 ); + + QGroupBox* ripperGroup = new QGroupBox( 1, Qt::Vertical, box, "ripperGroup" ); + ripperGroup->layout()->setSpacing( 6 ); + ripperGroup->layout()->setMargin( 6 ); + QLabel* lRipper = new QLabel( i18n("CD Ripper")+":", ripperGroup, "lRipper" ); + cRipper = new KComboBox( ripperGroup, "cRipper" ); + connect( cRipper, SIGNAL(activated(int)), + this, SLOT(cfgChanged()) + ); + + delete stdDirs; + + rebuild(); +} + +ConfigBackendsPage::~ConfigBackendsPage() +{} + +void ConfigBackendsPage::resetDefaults() +{ + int i; + int item; + int rank; + + i = 1; + rank = 60; + item = 0; + QValueList rippers = config->allRippers(); + for( QValueList::Iterator it = rippers.begin(); it != rippers.end(); ++it ) + { + if( (*it)->rip.rank > rank ) { + rank = (*it)->rip.rank; + item = i; + } + i++; + } + cRipper->setCurrentItem( item ); + + for( QValueList::Iterator a = formatOptions.begin(); a != formatOptions.end(); ++a ) + { + FormatItem* formatItem = config->getFormatItem( (*a).format ); + if( formatItem == 0 ) continue; + + i = item = rank = 0; + for( QValueList::Iterator b = formatItem->encoders.begin(); b != formatItem->encoders.end(); ++b ) { + if( (*b)->enc.rank > rank ) { + rank = (*b)->enc.rank; + item = i; + } + i++; + } + (*a).cEncoder->setCurrentItem( item ); + + i = item = rank = 0; + for( QValueList::Iterator b = formatItem->decoders.begin(); b != formatItem->decoders.end(); ++b ) { + if( (*b)->dec.rank > rank ) { + rank = (*b)->dec.rank; + item = i; + } + i++; + } + (*a).cDecoder->setCurrentItem( item ); + + i = item = rank = 0; + for( QValueList::Iterator b = formatItem->replaygains.begin(); b != formatItem->replaygains.end(); ++b ) { + if( (*b)->replaygain.rank > rank ) { + rank = (*b)->replaygain.rank; + item = i; + } + i++; + } + (*a).cReplayGain->setCurrentItem( item ); + } + + encoderChanged(); + + for( QValueList::Iterator a = formatOptions.begin(); a != formatOptions.end(); ++a ) + { + FormatItem* formatItem = config->getFormatItem( (*a).format ); + if( formatItem == 0 ) continue; + + QString encoder = (*a).cEncoder->currentText(); + + (*a).cInternalReplayGain->setChecked( false ); + + for( QValueList::Iterator b = formatItem->encoders.begin(); b != formatItem->encoders.end(); ++b ) { + if( (*b)->enc.bin == encoder && (*b)->enc.strength.enabled ) { + if( (*b)->enc.strength.range_max >= (*b)->enc.strength.range_min ) + (*a).sStrength->setValue( (*b)->enc.strength.default_value / (*b)->enc.strength.step ); + else + (*a).sStrength->setValue( ( (*b)->enc.strength.range_min - (*b)->enc.strength.default_value ) / (*b)->enc.strength.step ); + } + if( (*b)->enc.bin == encoder && (*b)->enc.replaygain.enabled ) { + if( formatItem->replaygain != 0 && formatItem->replaygain->replaygain.rank > (*b)->enc.replaygain.rank ) { + (*a).cInternalReplayGain->setChecked( false ); + } + else { + (*a).cInternalReplayGain->setChecked( true ); + } + } + } + } + + strengthChanged(); + cfgChanged(); +} + +void ConfigBackendsPage::saveSettings() +{ + config->setCurrentRipper( 0 ); + QValueList rippers = config->allRippers(); + for( QValueList::Iterator it = rippers.begin(); it != rippers.end(); ++it ) + { + if( (*it)->rip.bin == cRipper->currentText() ) { + config->setCurrentRipper( *it ); + } + } + + for( QValueList::Iterator a = formatOptions.begin(); a != formatOptions.end(); ++a ) + { + FormatItem* formatItem = config->getFormatItem( (*a).format ); + if( formatItem == 0 ) continue; + + for( QValueList::Iterator b = formatItem->encoders.begin(); b != formatItem->encoders.end(); ++b ) { + if( (*b)->enc.bin == (*a).cEncoder->currentText() ) { + formatItem->encoder = (*b); + if( (*b)->enc.strength.enabled ) { + formatItem->compressionLevel = (*a).sStrength->value(); + } + if( (*b)->enc.replaygain.enabled ) { + formatItem->internalReplayGain = (*a).cInternalReplayGain->isChecked(); + } + } + } + + for( QValueList::Iterator b = formatItem->decoders.begin(); b != formatItem->decoders.end(); ++b ) { + if( (*b)->dec.bin == (*a).cDecoder->currentText() ) { + formatItem->decoder = (*b); + } + } + + for( QValueList::Iterator b = formatItem->replaygains.begin(); b != formatItem->replaygains.end(); ++b ) { + if( (*b)->replaygain.bin == (*a).cReplayGain->currentText() ) { + formatItem->replaygain = (*b); + } + } + } +} + +void ConfigBackendsPage::rebuild() +{ + for( QValueList::Iterator it = formatOptions.begin(); it != formatOptions.end(); ++it ) + { + delete (*it).lEncoder; + disconnect( (*it).cEncoder, SIGNAL(activated(int)), 0, 0 ); + delete (*it).cEncoder; + delete (*it).lStrength; + disconnect( (*it).sStrength,SIGNAL(valueChanged(int)), 0, 0 ); + delete (*it).sStrength; + delete (*it).lStrengthDisplay; + delete (*it).lDecoder; + disconnect( (*it).cDecoder, SIGNAL(activated(int)), 0, 0 ); + delete (*it).cDecoder; + delete (*it).lReplayGain; + disconnect( (*it).cReplayGain, SIGNAL(activated(int)), 0, 0 ); + delete (*it).cReplayGain; + disconnect( (*it).cInternalReplayGain, SIGNAL(toggled(bool)), 0, 0 ); + delete (*it).cInternalReplayGain; + delete (*it).grid; + delete (*it).group; + } + + formatOptions.clear(); + + // TODO show all extensions + + QStringList formats = config->allFormats(); + + for( QStringList::Iterator it = formats.begin(); it != formats.end(); ++it ) + { + FormatOptions options; + options.format = *it; + + FormatItem *formatItem = config->getFormatItem( options.format ); + QString title; + if( formatItem ) { + for( QStringList::Iterator at = formatItem->extensions.begin(); at != formatItem->extensions.end(); ++at ) { + if( !title.contains((*at).lower()) ) title += (*at).lower() + ", "; + } + title = title.left( title.length() - 2 ); +/* title += " ["; + for( QStringList::Iterator bt = formatItem->mime_types.begin(); bt != formatItem->mime_types.end(); ++bt ) { + if( !title.contains((*bt).lower()) ) title += (*bt).lower() + ", "; + } + title = title.left( title.length() - 2 ) + "]";*/ + } + else { + title = options.format; + } + + options.group = new QGroupBox( title, box, options.format ); + options.group->setColumnLayout( 0, Qt::Vertical ); + options.group->layout()->setSpacing( 6 ); + options.group->layout()->setMargin( 6 ); + options.group->show(); + options.grid = new QGridLayout( options.group->layout() ); + + options.lEncoder = new QLabel( i18n("Encoder")+":", options.group, options.format ); + options.lEncoder->show(); + options.grid->addWidget( options.lEncoder, 0, 0 ); + options.cEncoder = new KComboBox( options.group, options.format ); + options.cEncoder->show(); + connect( options.cEncoder, SIGNAL(activated(int)), + this, SLOT(cfgChanged()) + ); + connect( options.cEncoder, SIGNAL(activated(int)), + this, SLOT(encoderChanged()) + ); + options.grid->addWidget( options.cEncoder, 0, 1 ); + + options.lStrength = new QLabel( i18n("Strength")+":", options.group, options.format ); + options.lStrength->setAlignment( Qt::AlignRight | Qt::AlignVCenter ); + options.lStrength->show(); + options.grid->addWidget( options.lStrength, 0, 2 ); + options.sStrength = new QSlider( Qt::Horizontal, options.group, options.format ); + options.sStrength->setTickmarks( QSlider::Below ); + options.sStrength->show(); + QToolTip::add( options.sStrength, i18n("Set the compression strength:\n\nLeft = fast conversion\nRight = good resultant file") ); + options.grid->addWidget( options.sStrength, 0, 3 ); + connect( options.sStrength, SIGNAL(valueChanged(int)), + this, SLOT(cfgChanged()) + ); + connect( options.sStrength, SIGNAL(valueChanged(int)), + this, SLOT(strengthChanged()) + ); + + options.lDecoder = new QLabel( i18n("Decoder")+":", options.group, options.format ); + options.lDecoder->show(); + options.grid->addWidget( options.lDecoder, 1, 0 ); + options.cDecoder = new KComboBox( options.group, options.format ); + options.cDecoder->show(); + options.grid->addWidget( options.cDecoder, 1, 1 ); + connect( options.cDecoder, SIGNAL(activated(int)), + this, SLOT(cfgChanged()) + ); + options.lStrengthDisplay = new QLabel( "", options.group, options.format ); + options.lStrengthDisplay->setAlignment( Qt::AlignRight | Qt::AlignVCenter ); + options.lStrengthDisplay->setEnabled( false ); + options.grid->addWidget( options.lStrengthDisplay, 1, 3 ); + + options.lReplayGain = new QLabel( i18n("Replay Gain")+":", options.group, options.format ); + options.lReplayGain->show(); + options.grid->addWidget( options.lReplayGain, 2, 0 ); + options.cReplayGain = new KComboBox( options.group, options.format ); + options.cReplayGain->show(); + options.grid->addWidget( options.cReplayGain, 2, 1 ); + connect( options.cReplayGain, SIGNAL(activated(int)), + this, SLOT(cfgChanged()) + ); + options.cInternalReplayGain = new QCheckBox( i18n("Use internal Replay Gain"), options.group, options.format ); + QToolTip::add( options.cInternalReplayGain, i18n("Use the internal Replay Gain calculator of the encoder") ); + options.grid->addWidget( options.cInternalReplayGain, 2, 3 ); + connect( options.cInternalReplayGain, SIGNAL(toggled(bool)), + this, SLOT(cfgChanged()) + ); + + options.grid->setColStretch( 0, 0 ); + options.grid->setColStretch( 1, 1 ); + options.grid->setColStretch( 2, 1 ); + options.grid->setColStretch( 3, 1 ); + + formatOptions.append( options ); + } + + refill(); +} + +void ConfigBackendsPage::refill() +{ + KStandardDirs* stdDirs = new KStandardDirs(); + int i, item; + + cRipper->clear(); + i = item = 0; + cRipper->insertItem( QPixmap(stdDirs->findResource("data","soundkonverter/pics/ledyellow.png")), i18n("KDE audio CD protocol") ); + i++; + QValueList rippers = config->allRippers(); + for( QValueList::Iterator it = rippers.begin(); it != rippers.end(); ++it ) + { + if( (*binaries)[(*it)->rip.bin] == "" ) continue; + + if( (*it)->rip.rank >= 70 ) cRipper->insertItem( QPixmap(stdDirs->findResource("data","soundkonverter/pics/ledgreen.png")), (*it)->rip.bin ); + else if( (*it)->rip.rank >= 40 ) cRipper->insertItem( QPixmap(stdDirs->findResource("data","soundkonverter/pics/ledyellow.png")), (*it)->rip.bin ); + else cRipper->insertItem( QPixmap(stdDirs->findResource("data","soundkonverter/pics/ledred.png")), (*it)->rip.bin ); + if( (*it) == config->getCurrentRipper() ) item = i; + i++; + } + cRipper->setCurrentItem( item ); + + for( QValueList::Iterator a = formatOptions.begin(); a != formatOptions.end(); ++a ) + { + FormatItem* formatItem = config->getFormatItem( (*a).format ); + (*a).cEncoder->clear(); + (*a).cDecoder->clear(); + (*a).cReplayGain->clear(); + if( formatItem == 0 ) continue; + + i = item = 0; + for( QValueList::Iterator b = formatItem->encoders.begin(); b != formatItem->encoders.end(); ++b ) { + if( (*binaries)[(*b)->enc.bin] == "" ) continue; + + if( (*b)->enc.rank >= 70 ) (*a).cEncoder->insertItem( QPixmap(stdDirs->findResource("data","soundkonverter/pics/ledgreen.png")), (*b)->enc.bin ); + else if( (*b)->enc.rank >= 40 ) (*a).cEncoder->insertItem( QPixmap(stdDirs->findResource("data","soundkonverter/pics/ledyellow.png")), (*b)->enc.bin ); + else (*a).cEncoder->insertItem( QPixmap(stdDirs->findResource("data","soundkonverter/pics/ledred.png")), (*b)->enc.bin ); + if( (*b) == formatItem->encoder ) item = i; + i++; + } + (*a).cEncoder->setCurrentItem( item ); + + i = item = 0; + for( QValueList::Iterator b = formatItem->decoders.begin(); b != formatItem->decoders.end(); ++b ) { + if( (*binaries)[(*b)->dec.bin] == "" ) continue; + + if( (*b)->dec.rank >= 70 ) (*a).cDecoder->insertItem( QPixmap(stdDirs->findResource("data","soundkonverter/pics/ledgreen.png")), (*b)->dec.bin ); + else if( (*b)->dec.rank >= 40 ) (*a).cDecoder->insertItem( QPixmap(stdDirs->findResource("data","soundkonverter/pics/ledyellow.png")), (*b)->dec.bin ); + else (*a).cDecoder->insertItem( QPixmap(stdDirs->findResource("data","soundkonverter/pics/ledred.png")), (*b)->dec.bin ); + if( (*b) == formatItem->decoder ) item = i; + i++; + } + (*a).cDecoder->setCurrentItem( item ); + + i = item = 0; + for( QValueList::Iterator b = formatItem->replaygains.begin(); b != formatItem->replaygains.end(); ++b ) { + if( (*binaries)[(*b)->replaygain.bin] == "" ) continue; + + if( (*b)->replaygain.rank >= 70 ) (*a).cReplayGain->insertItem( QPixmap(stdDirs->findResource("data","soundkonverter/pics/ledgreen.png")), (*b)->replaygain.bin ); + else if( (*b)->replaygain.rank >= 40 ) (*a).cReplayGain->insertItem( QPixmap(stdDirs->findResource("data","soundkonverter/pics/ledyellow.png")), (*b)->replaygain.bin ); + else (*a).cReplayGain->insertItem( QPixmap(stdDirs->findResource("data","soundkonverter/pics/ledred.png")), (*b)->replaygain.bin ); + if( (*b) == formatItem->replaygain ) item = i; + i++; + } + (*a).cReplayGain->setCurrentItem( item ); + } + + delete stdDirs; + + encoderChanged(); +} + +void ConfigBackendsPage::encoderChanged() +{ + bool recalc; + + for( QValueList::Iterator a = formatOptions.begin(); a != formatOptions.end(); ++a ) + { + FormatItem* formatItem = config->getFormatItem( (*a).format ); + (*a).lStrength->hide(); + (*a).sStrength->hide(); + (*a).lStrengthDisplay->hide(); + (*a).cInternalReplayGain->hide(); + if( formatItem == 0 ) continue; + + QString encoder = (*a).cEncoder->currentText(); + + for( QValueList::Iterator b = formatItem->encoders.begin(); b != formatItem->encoders.end(); ++b ) { + if( QObject::sender() && (*a).format == QObject::sender()->name() ) recalc = true; + else if( !QObject::sender() ) recalc = true; + else recalc = false; + if( (*b)->enc.bin == encoder && (*b)->enc.strength.enabled ) { + (*a).lStrength->show(); + if( (*b)->enc.strength.range_max >= (*b)->enc.strength.range_min ) { + (*a).sStrength->setMinValue( (int)((*b)->enc.strength.range_min/(*b)->enc.strength.step) ); + (*a).sStrength->setMaxValue( (int)((*b)->enc.strength.range_max/(*b)->enc.strength.step) ); + } + else { + (*a).sStrength->setMinValue( (int)((*b)->enc.strength.range_max/(*b)->enc.strength.step) ); + (*a).sStrength->setMaxValue( (int)((*b)->enc.strength.range_min/(*b)->enc.strength.step) ); + } + (*a).sStrength->setPageStep( 1 ); + if( QObject::sender() && (*a).format == QObject::sender()->name() ) { + if( (*b)->enc.strength.range_max >= (*b)->enc.strength.range_min ) + (*a).sStrength->setValue( (*b)->enc.strength.default_value / (*b)->enc.strength.step ); + else + (*a).sStrength->setValue( ( (*b)->enc.strength.range_min - (*b)->enc.strength.default_value ) / (*b)->enc.strength.step ); + } + else if( !QObject::sender() ) { + (*a).sStrength->setValue( formatItem->compressionLevel ); + } + (*a).sStrength->show(); + (*a).lStrengthDisplay->show(); + } + if( (*b)->enc.bin == encoder && (*b)->enc.replaygain.enabled ) { + (*a).cInternalReplayGain->show(); + if( recalc ) (*a).cInternalReplayGain->setChecked( formatItem->internalReplayGain ); + } + } + } + + strengthChanged(); +} + +void ConfigBackendsPage::strengthChanged() +{ + for( QValueList::Iterator a = formatOptions.begin(); a != formatOptions.end(); ++a ) + { + FormatItem* formatItem = config->getFormatItem( (*a).format ); + if( formatItem == 0 ) continue; + + QString encoder = (*a).cEncoder->currentText(); + + for( QValueList::Iterator b = formatItem->encoders.begin(); b != formatItem->encoders.end(); ++b ) { + if( (*b)->enc.bin == encoder && (*b)->enc.strength.enabled ) { + QString strength = (*b)->enc.strength.param; + int compressionLevel = (*a).sStrength->value(); + if( (*b)->enc.strength.profiles.empty() ) { + if( (*b)->enc.strength.step < 1 ) { + if( (*b)->enc.strength.range_max >= (*b)->enc.strength.range_min ) + strength.replace( "%c", QString::number( compressionLevel * (*b)->enc.strength.step ) ); + else + strength.replace( "%c", QString::number( (*b)->enc.strength.range_min - compressionLevel * (*b)->enc.strength.step ) ); + } + else { + if( (*b)->enc.strength.range_max >= (*b)->enc.strength.range_min ) + strength.replace( "%c", QString::number( (int)(compressionLevel * (*b)->enc.strength.step) ) ); + else + strength.replace( "%c", QString::number( (int)((*b)->enc.strength.range_min - compressionLevel * (*b)->enc.strength.step) ) ); + } + if( (*b)->enc.strength.separator != '.' ) strength.replace( QChar('.'), (*b)->enc.strength.separator ); + } + else { + QStringList::Iterator it = (*b)->enc.strength.profiles.at( (int)compressionLevel ); + strength.replace( "%c", *it ); + } + (*a).lStrengthDisplay->setText( "( \"" + strength + "\" )" ); + } + } + } +} + + + diff --git a/src/configbackendspage.h b/src/configbackendspage.h new file mode 100755 index 0000000..27071f2 --- /dev/null +++ b/src/configbackendspage.h @@ -0,0 +1,81 @@ + + +#ifndef CONFIGBACKENDSPAGE_H +#define CONFIGBACKENDSPAGE_H + +#include + +#include + +class Config; +class KComboBox; +class KScrollView; +class QGroupBox; +class QGridLayout; +class QLabel; +class QSlider; +class QCheckBox; +class QVBox; + +/** +* @short The page for configuring the environment + * @author Daniel Faust + * @version 0.3 + */ +class ConfigBackendsPage : public ConfigPageBase +{ + Q_OBJECT +public: + /** + * Default Constructor + */ + ConfigBackendsPage( Config*, QMap*, QWidget *parent=0, const char *name=0 ); + + /** + * Default Destructor + */ + virtual ~ConfigBackendsPage(); + +private: + struct FormatOptions + { + // TODO remove the string lists + QString format; + QGroupBox* group; + QGridLayout* grid; + QLabel* lEncoder; + KComboBox* cEncoder; + QLabel* lStrength; + QSlider* sStrength; + QLabel* lStrengthDisplay; + QLabel* lDecoder; + KComboBox* cDecoder; + QLabel* lReplayGain; + KComboBox* cReplayGain; + QCheckBox* cInternalReplayGain; + }; + + QValueList formatOptions; + + QGridLayout* grid; + KScrollView* scrollView; + QVBox* box; + + KComboBox* cRipper; + + Config* config; + + QMap* binaries; + +public slots: + void resetDefaults(); + void saveSettings(); + void rebuild(); + void refill(); + void encoderChanged(); + void strengthChanged(); + +}; + +#endif // CONFIGBACKENDSPAGE_H + diff --git a/src/configdialog.cpp b/src/configdialog.cpp new file mode 100755 index 0000000..3e58007 --- /dev/null +++ b/src/configdialog.cpp @@ -0,0 +1,174 @@ + + +#include "configdialog.h" + +#include "config.h" +#include "configgeneralpage.h" +#include "configpluginspage.h" +#include "configenvironmentpage.h" +#include "configbackendspage.h" + +/*#include "config_dialogue_interface.h" +#include "config_dialogue_backend_plugins.h" +#include "config_dialogue_backends.h" +#include "config_dialogue_en_decoder.h" +#include "config_dialogue_en_decoder_options.h" + +#include "tools.h" +#include "backend_plugins.h" +#include "replaygain_plugins.h" + +#include +*/ +//#include +#include +#include +#include + +ConfigDialog::ConfigDialog( Config* _config, QWidget *parent, const char *name, Page startPage ) + : KDialogBase( + IconList, + i18n("Settings"), + Apply | Cancel | Default | Help | Ok, + Ok, // default button + parent, + name, + true, // modal + true // separator + ) +{ + config = _config; + + //resize( 600, 400 ); + + binaries = config->binaries; + + connect( this, SIGNAL(applyClicked()), + this,SLOT(applyClickedSlot()) + ); + connect( this, SIGNAL(okClicked()), + this,SLOT(okClickedSlot()) + ); + connect( this, SIGNAL(defaultClicked()), + this,SLOT(defaultClickedSlot()) + ); + + generalPage = addPage( i18n("General"), "misc" ); + configGeneralPage = new ConfigGeneralPage( config, generalPage, "configGeneralPage" ); + connect( configGeneralPage, SIGNAL(configChanged()), + this, SLOT(configChanged()) + ); + connect( this, SIGNAL(saveGeneral()), + configGeneralPage, SLOT(saveSettings()) + ); + connect( this, SIGNAL(resetGeneral()), + configGeneralPage, SLOT(resetDefaults()) + ); + + pluginsPage = addPage( i18n("Plugins"), "connect_creating" ); + configPluginsPage = new ConfigPluginsPage( config, pluginsPage, "configPluginsPage" ); + connect( configPluginsPage, SIGNAL(configChanged()), + this, SLOT(configChanged()) + ); + connect( this, SIGNAL(savePlugins()), + configPluginsPage, SLOT(saveSettings()) + ); + connect( this, SIGNAL(resetPlugins()), + configPluginsPage, SLOT(resetDefaults()) + ); + + environmentPage = addPage( i18n("Environment"), "filefind" ); + configEnvironmentPage = new ConfigEnvironmentPage( config, &binaries, environmentPage, "configEnvironmentPage" ); + connect( configEnvironmentPage, SIGNAL(configChanged()), + this, SLOT(configChanged()) + ); + connect( this, SIGNAL(saveEnvironment()), + configEnvironmentPage, SLOT(saveSettings()) + ); + connect( this, SIGNAL(resetEnvironment()), + configEnvironmentPage, SLOT(resetDefaults()) + ); + + backendsPage = addPage( i18n("Backends"), "kcmsystem" ); + configBackendsPage = new ConfigBackendsPage( config, &binaries, backendsPage, "configBackendsPage" ); + connect( configBackendsPage, SIGNAL(configChanged()), + this, SLOT(configChanged()) + ); + connect( this, SIGNAL(saveBackends()), + configBackendsPage, SLOT(saveSettings()) + ); + connect( this, SIGNAL(resetBackends()), + configBackendsPage, SLOT(resetDefaults()) + ); + connect( configEnvironmentPage, SIGNAL(rebuildBackendsPage()), + configBackendsPage, SLOT(rebuild()) + ); + + setConfigChanged( false ); + + showPage( startPage ); +} + +ConfigDialog::~ConfigDialog() +{ +} + +QFrame *ConfigDialog::addPage(const QString &itemName, const QString &iconName) +{ + return KDialogBase::addPage( itemName, QString::null, MainBarIcon(iconName,32) ); +} + +void ConfigDialog::setConfigChanged( const bool value ) +{ + actionButton( Apply )->setEnabled(value); +} + +void ConfigDialog::configChanged() +{ + setConfigChanged( true ); +} + +void ConfigDialog::applyClickedSlot() +{ + okClickedSlot(); + setConfigChanged( false ); +} + +void ConfigDialog::okClickedSlot() +{ + emit saveGeneral(); + emit savePlugins(); + emit saveEnvironment(); + emit saveBackends(); + config->write(); +} + +void ConfigDialog::defaultClickedSlot() +{ + int index = activePageIndex(); + QStringList listDefaults; + + if( index == -1 ) + return; + + if( index == pageIndex(generalPage) ) + { + emit resetGeneral(); + setConfigChanged( true ); + } + else if( index == pageIndex(pluginsPage) ) + { + emit resetPlugins(); + setConfigChanged( true ); + } + else if( index == pageIndex(environmentPage) ) + { + emit resetEnvironment(); + setConfigChanged( true ); + } + else if( index == pageIndex(backendsPage) ) + { + emit resetBackends(); + setConfigChanged( true ); + } +} diff --git a/src/configdialog.h b/src/configdialog.h new file mode 100755 index 0000000..19d3d12 --- /dev/null +++ b/src/configdialog.h @@ -0,0 +1,79 @@ + + +#ifndef CONFIGDIALOG_H +#define CONFIGDIALOG_H + +#include + +#include + + +class Config; +class ConfigGeneralPage; +class ConfigPluginsPage; +class ConfigEnvironmentPage; +class ConfigBackendsPage; + +/** + * @short Config dialog + * @author Daniel Faust + * @version 0.3 + */ +class ConfigDialog : public KDialogBase +{ + Q_OBJECT +public: + enum Page { + GeneralPage, + PluginsPage, + EnvironmentPage, + BackendsPage + }; + + /** + * Constructor + */ + ConfigDialog( Config*, QWidget *parent = 0, const char *name = 0, Page startPage = GeneralPage ); + + /** + * Destructor + */ + virtual ~ConfigDialog(); + +private: + QFrame* addPage( const QString &itemName, const QString &iconName ); + + QFrame* generalPage; + ConfigGeneralPage* configGeneralPage; + QFrame* pluginsPage; + ConfigPluginsPage* configPluginsPage; + QFrame* environmentPage; + ConfigEnvironmentPage* configEnvironmentPage; + QFrame* backendsPage; + ConfigBackendsPage* configBackendsPage; + + void setConfigChanged( const bool ); + + Config* config; + + QMap binaries; + +private slots: + void configChanged(); + void okClickedSlot(); + void applyClickedSlot(); + void defaultClickedSlot(); + +signals: + void saveGeneral(); + void savePlugins(); + void saveEnvironment(); + void saveBackends(); + + void resetGeneral(); + void resetPlugins(); + void resetEnvironment(); + void resetBackends(); +}; + +#endif // CONFIGDIALOG_H diff --git a/src/configenvironmentpage.cpp b/src/configenvironmentpage.cpp new file mode 100755 index 0000000..26dbd5b --- /dev/null +++ b/src/configenvironmentpage.cpp @@ -0,0 +1,223 @@ + +#include "configenvironmentpage.h" + +#include "config.h" + +#include +#include +#include +#include +//#include +//#include +#include +#include + +#include +#include +#include +#include + + +ConfigEnvironmentPage::ConfigEnvironmentPage( Config* _config, QMap* _binaries, QWidget *parent, const char *name ) + : ConfigPageBase( parent, name ) +{ + config = _config; + binaries = _binaries; + + // create an icon loader object for loading icons + KIconLoader* iconLoader = new KIconLoader(); + + QVBoxLayout* box = new QVBoxLayout( parent, 0, 6 ); + + QLabel* lDirectoriesLabel = new QLabel( i18n("Directories to be scanned")+":", parent, "lDirectoriesLabel" ); + box->addWidget( lDirectoriesLabel ); + +// KEditListBox* eDirectories = new KEditListBox( parent, "eDirectories" ); +// box->addWidget( eDirectories ); + + QHBoxLayout* directoriesBox = new QHBoxLayout( box ); + lDirectories = new KListBox( parent, "lDirectories" ); + lDirectories->insertStringList( config->data.environment.directories ); + directoriesBox->addWidget( lDirectories ); + connect( lDirectories, SIGNAL(highlighted(int)), + this, SLOT(directoriesSelectionChanged(int)) + ); + + QVBoxLayout* directoriesMiddleBox = new QVBoxLayout( directoriesBox ); + pDirUp = new KPushButton( "", parent, "pDirUp" ); + pDirUp->setPixmap( iconLoader->loadIcon("up",KIcon::Toolbar) ); + pDirUp->setEnabled( false ); + QToolTip::add( pDirUp, i18n("Move selected directory one position up.\nThis effects which backend will be chosen, if there are several versions.") ); + directoriesMiddleBox->addWidget( pDirUp ); + connect( pDirUp, SIGNAL(clicked()), + this, SLOT(dirUp()) + ); + + directoriesMiddleBox->addStretch(); + pDirDown = new KPushButton( "", parent, "pDirDown" ); + pDirDown->setPixmap( iconLoader->loadIcon("down",KIcon::Toolbar) ); + pDirDown->setEnabled( false ); + QToolTip::add( pDirDown, i18n("Move selected directory one position down.\nThis effects which backend will be chosen, if there are several versions.") ); + directoriesMiddleBox->addWidget( pDirDown ); + connect( pDirDown, SIGNAL(clicked()), + this, SLOT(dirDown()) + ); + + QVBoxLayout* directoriesRightBox = new QVBoxLayout( directoriesBox ); + pAddDirectory = new KPushButton( iconLoader->loadIcon("add",KIcon::Small), i18n("Add ..."), parent, "pAddDirectory" ); + directoriesRightBox->addWidget( pAddDirectory ); + connect( pAddDirectory, SIGNAL(clicked()), + this, SLOT(addDirectory()) + ); + + pRemoveDirectory = new KPushButton( iconLoader->loadIcon("remove",KIcon::Small), i18n("Remove"), parent, "pRemoveDirectory" ); + directoriesRightBox->addWidget( pRemoveDirectory ); + pRemoveDirectory->setEnabled( false ); + connect( pRemoveDirectory, SIGNAL(clicked()), + this, SLOT(removeDirectory()) + ); + + directoriesRightBox->addStretch(); + + box->addSpacing( 5 ); + + QHBoxLayout* programsBox = new QHBoxLayout( box ); + + QVBoxLayout* foundProgramsBox = new QVBoxLayout( programsBox ); + QLabel* lFoundProgramsLabel = new QLabel( i18n("Programs found")+":", parent, "lFoundProgramsLabel" ); + foundProgramsBox->addWidget( lFoundProgramsLabel ); + lFoundPrograms = new KListBox( parent, "lFoundPrograms" ); + lFoundPrograms->setSelectionMode( QListBox::NoSelection ); + foundProgramsBox->addWidget( lFoundPrograms ); + //connect(lPrograms,SIGNAL(highlighted(int)),this,SLOT(programsSelectionChanged(int))); + programsBox->setStretchFactor( foundProgramsBox, 3 ); + + QVBoxLayout* notFoundProgramsBox = new QVBoxLayout( programsBox ); + QLabel* lNotFoundProgramsLabel = new QLabel( i18n("Programs not found")+":", parent, "lNotFoundProgramsLabel" ); + notFoundProgramsBox->addWidget( lNotFoundProgramsLabel ); + lNotFoundPrograms = new KListBox( parent, "lNotFoundPrograms" ); + lNotFoundPrograms->setSelectionMode( QListBox::NoSelection ); + notFoundProgramsBox->addWidget( lNotFoundPrograms ); + //connect(lPrograms,SIGNAL(highlighted(int)),this,SLOT(programsSelectionChanged(int))); + programsBox->setStretchFactor( notFoundProgramsBox, 2 ); + + for( QMap::Iterator it = config->binaries.begin(); it != config->binaries.end(); ++it ) { + if( it.data() != "" ) { + lFoundPrograms->insertItem( it.data() ); + } + else { + lNotFoundPrograms->insertItem( it.key() ); + } + } + +// box->addStretch(); + + // delete the icon loader object + delete iconLoader; +} + +ConfigEnvironmentPage::~ConfigEnvironmentPage() +{} + +void ConfigEnvironmentPage::resetDefaults() +{ + lDirectories->clear(); + QString datadir = locateLocal( "data", "soundkonverter/bin/" ); + datadir.remove( datadir.length() - 1, 1 ); + lDirectories->insertItem( datadir ); + lDirectories->insertItem( QDir::homeDirPath() + "/bin" ); + lDirectories->insertItem( "/usr/local/bin" ); + lDirectories->insertItem( "/usr/bin" ); + + refill(); + cfgChanged(); +} + +void ConfigEnvironmentPage::saveSettings() +{ + config->data.environment.directories.clear(); + for( uint i = 0; i < lDirectories->count(); i++ ) { + config->data.environment.directories.append( lDirectories->text(i) ); + } + + config->binaries = *binaries; +} + +void ConfigEnvironmentPage::directoriesSelectionChanged( int index ) +{ + pRemoveDirectory->setEnabled( true ); + if( index != 0 ) pDirUp->setEnabled( true ); + else pDirUp->setEnabled( false ); + if( index != lDirectories->count() - 1 ) pDirDown->setEnabled( true ); + else pDirDown->setEnabled( false ); +} + +void ConfigEnvironmentPage::dirUp() +{ + int index = lDirectories->currentItem(); + if( index > 0 ) { + QString text = lDirectories->currentText(); + lDirectories->removeItem( index ); + lDirectories->insertItem( text, index - 1 ); + lDirectories->setSelected( index - 1, true ); + refill(); + cfgChanged(); + } +} + +void ConfigEnvironmentPage::dirDown() +{ + int index = lDirectories->currentItem(); + if( (uint)index < lDirectories->count() - 1 ) { + QString text = lDirectories->currentText(); + lDirectories->removeItem( index ); + lDirectories->insertItem( text, index + 1 ); + lDirectories->setSelected( index + 1, true ); + refill(); + cfgChanged(); + } +} + +void ConfigEnvironmentPage::addDirectory() +{ + QString dirname = KFileDialog::getExistingDirectory( "/", 0 ); + if( dirname != NULL ) { + lDirectories->insertItem( dirname ); + refill(); + cfgChanged(); + } +} + +void ConfigEnvironmentPage::removeDirectory() +{ + lDirectories->removeItem( lDirectories->currentItem() ); + refill(); + cfgChanged(); +} + +void ConfigEnvironmentPage::refill() +{ + for( QMap::Iterator it = binaries->begin(); it != binaries->end(); ++it ) { + it.data() = ""; + for( uint i = 0; i < lDirectories->count(); i++ ) { + if( it.data() == "" && QFile::exists(lDirectories->text(i) + "/" + it.key()) ) { + it.data() = lDirectories->text(i) + "/" + it.key(); + } + } + } + + lFoundPrograms->clear(); + lNotFoundPrograms->clear(); + for( QMap::Iterator it = binaries->begin(); it != binaries->end(); ++it ) { + if( it.data() != "" ) { + lFoundPrograms->insertItem( it.data() ); + } + else { + lNotFoundPrograms->insertItem( it.key() ); + } + } + + emit rebuildBackendsPage(); +} + + diff --git a/src/configenvironmentpage.h b/src/configenvironmentpage.h new file mode 100755 index 0000000..37b0c2e --- /dev/null +++ b/src/configenvironmentpage.h @@ -0,0 +1,62 @@ + + +#ifndef CONFIGENVIRONMENTPAGE_H +#define CONFIGENVIRONMENTPAGE_H + +#include + +class Config; +class KPushButton; +class KListBox; + +/** +* @short The page for configuring the environment + * @author Daniel Faust + * @version 0.3 + */ +class ConfigEnvironmentPage : public ConfigPageBase +{ + Q_OBJECT +public: + /** + * Default Constructor + */ + ConfigEnvironmentPage( Config*, QMap*, QWidget *parent=0, const char *name=0 ); + + /** + * Default Destructor + */ + virtual ~ConfigEnvironmentPage(); + +private: + KListBox* lDirectories; + KPushButton* pDirUp; + KPushButton* pDirDown; + KPushButton* pAddDirectory; + KPushButton* pRemoveDirectory; + KListBox* lFoundPrograms; + KListBox* lNotFoundPrograms; + + Config* config; + + QMap* binaries; + +public slots: + void resetDefaults(); + void saveSettings(); + +private slots: + void directoriesSelectionChanged( int ); + void dirUp(); + void dirDown(); + void addDirectory(); + void removeDirectory(); + void refill(); + +signals: + void rebuildBackendsPage(); + +}; + +#endif // CONFIGENVIRONMENTPAGE_H + diff --git a/src/configgeneralpage.cpp b/src/configgeneralpage.cpp new file mode 100755 index 0000000..9408ffd --- /dev/null +++ b/src/configgeneralpage.cpp @@ -0,0 +1,323 @@ + +#include "configgeneralpage.h" + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +// ### soundkonverter 0.4: add an option to use vfat save names when the output device is vfat + +ConfigGeneralPage::ConfigGeneralPage( Config* _config, QWidget *parent, const char *name ) + : ConfigPageBase( parent, name ) +{ + config = _config; + + // create an icon loader object for loading icons + KIconLoader* iconLoader = new KIconLoader(); + + QVBoxLayout* box = new QVBoxLayout( parent, 0, 6 ); + + QHBoxLayout* startTabBox = new QHBoxLayout( box, 6 ); + QLabel* lStartTab = new QLabel( i18n("Start in Mode")+":", parent, "lStartTab" ); + startTabBox->addWidget( lStartTab ); + cStartTab = new KComboBox( parent, "cStartTab" ); + cStartTab->insertItem( i18n("Last used") ); + cStartTab->insertItem( i18n("Simple") ); + cStartTab->insertItem( i18n("Detailed") ); + cStartTab->setCurrentItem( config->data.general.startTab ); + startTabBox->addWidget( cStartTab ); + connect( cStartTab, SIGNAL(activated(int)), + this, SLOT(cfgChanged()) + ); + + box->addSpacing( 5 ); + + QHBoxLayout* defaultProfileBox = new QHBoxLayout( box, 6 ); + QLabel* lDefaultProfile = new QLabel( i18n("Default profile")+":", parent, "lDefaultProfile" ); + defaultProfileBox->addWidget( lDefaultProfile ); + cDefaultProfile = new KComboBox( parent, "cDefaultProfile" ); + sDefaultProfile += i18n("Very low"); + sDefaultProfile += i18n("Low"); + sDefaultProfile += i18n("Medium"); + sDefaultProfile += i18n("High"); + sDefaultProfile += i18n("Very high"); + sDefaultProfile += i18n("Lossless"); + sDefaultProfile += i18n("Hybrid"); + sDefaultProfile += config->getAllProfiles(); + sDefaultProfile.remove( i18n("Last used") ); + sDefaultProfile.remove( "Last used" ); + sDefaultProfile.prepend( i18n("Last used") ); + cDefaultProfile->insertStringList( sDefaultProfile ); + cDefaultProfile->setCurrentItem( profileIndex(config->data.general.defaultProfile) ); + defaultProfileBox->addWidget( cDefaultProfile ); + connect( cDefaultProfile, SIGNAL(activated(int)), + this, SLOT(profileChanged()) + ); + connect( cDefaultProfile, SIGNAL(activated(int)), + this, SLOT(cfgChanged()) + ); + QLabel* lDefaultFormat = new QLabel( i18n("Default format")+":", parent, "lDefaultFormat" ); + defaultProfileBox->addWidget( lDefaultFormat ); + cDefaultFormat = new KComboBox( parent, "cDefaultFormat" ); + defaultProfileBox->addWidget( cDefaultFormat ); + connect( cDefaultFormat, SIGNAL(activated(int)), + this, SLOT(cfgChanged()) + ); + profileChanged(); + + box->addSpacing( 5 ); + +/* QHBoxLayout* defaultDirBox = new QHBoxLayout( box, 6 ); + QLabel* lDefaultDir = new QLabel( i18n("Default output directory")+":", parent, "lDefaultDir" ); + defaultDirBox->addWidget( lDefaultDir ); + lDir = new KLineEdit( parent, "lDir" ); + lDir->setText( config->data.general.defaultOutputDirectory ); + QToolTip::add( lDir, i18n("

The following strings are space holders, that will be replaced by the information in the meta data:

%a - Artist
%b - Album
%c - Comment
%d - Disc number
%g - Genre
%n - Track number
%p - Composer
%t - Title
%y - Year
%f - Original file name

") ); + defaultDirBox->addWidget( lDir ); + connect( lDir, SIGNAL(textChanged(const QString&)), + this, SLOT(cfgChanged()) + );*/ + /*pDirInfo = new KPushButton( iconLoader->loadIcon("messagebox_info",KIcon::Small), "", parent, "pDirInfo" ); + QToolTip::add( pDirInfo, i18n("Information about the wildcards.") ); + defaultDirBox->addWidget( pDirInfo ); + connect( pDirInfo, SIGNAL(clicked()), + this, SLOT(dirInfo()) + );*/ +// pDirSelect = new KPushButton( iconLoader->loadIcon("folder",KIcon::Small), "", parent, "pDirSelect" ); +// QToolTip::add( pDirSelect, i18n("Choose an output directory") ); +// defaultDirBox->addWidget( pDirSelect ); +// connect( pDirSelect, SIGNAL(clicked()), +// this, SLOT(selectDir()) +// ); + + QHBoxLayout* priorityBox = new QHBoxLayout( box, 6 ); + QLabel* lPriority = new QLabel( i18n("Process priority of the backends")+":", parent, "lPriority" ); + priorityBox->addWidget( lPriority ); + cPriority = new KComboBox( parent, "cPriority" ); + sPriority += i18n("Normal"); + sPriority += i18n("Low"); + cPriority->insertStringList( sPriority ); + cPriority->setCurrentItem( config->data.general.priority / 10 ); // NOTE that just works for 'normal' and 'low' + priorityBox->addWidget( cPriority ); + connect( cPriority, SIGNAL(activated(int)), + this, SLOT(cfgChanged()) + ); + + box->addSpacing( 5 ); + + QHBoxLayout* useVFATNamesBox = new QHBoxLayout( box, 6 ); + cUseVFATNames = new QCheckBox( i18n("Use FAT compatible output file names"), parent, "cUseVFATNames" ); + QToolTip::add( cUseVFATNames, i18n("Replaces some special characters like \'?\' by \'_\'.") ); + cUseVFATNames->setChecked( config->data.general.useVFATNames ); + useVFATNamesBox->addWidget( cUseVFATNames ); + connect( cUseVFATNames, SIGNAL(toggled(bool)), + this, SLOT(cfgChanged()) + ); + + box->addSpacing( 5 ); + + QHBoxLayout* conflictHandlingBox = new QHBoxLayout( box, 6 ); + QLabel* lConflictHandling = new QLabel( i18n("Conflict handling")+":", parent, "lConflictHandling" ); + conflictHandlingBox->addWidget( lConflictHandling ); + cConflictHandling = new KComboBox( parent, "cConflictHandling" ); + QToolTip::add( cConflictHandling, i18n("Do that if the output file already exists") ); + sConflictHandling += i18n("Generate new file name"); + sConflictHandling += i18n("Skip file"); + cConflictHandling->insertStringList( sConflictHandling ); + cConflictHandling->setCurrentItem( config->data.general.conflictHandling ); + conflictHandlingBox->addWidget( cConflictHandling ); + connect( cConflictHandling, SIGNAL(activated(int)), + this, SLOT(cfgChanged()) + ); + + box->addSpacing( 5 ); + + QHBoxLayout* numFilesBox = new QHBoxLayout( box, 6 ); + QLabel* lNumFiles = new QLabel( i18n("Number of files to convert at once")+":", parent, "lNumFiles" ); + numFilesBox->addWidget( lNumFiles ); + iNumFiles = new KIntSpinBox( 1, 100, 1, config->data.general.numFiles, 10, parent, "iNumFiles" ); + numFilesBox->addWidget( iNumFiles ); + connect( iNumFiles, SIGNAL(valueChanged(int)), + this, SLOT(cfgChanged()) + ); + + box->addSpacing( 5 ); + + QHBoxLayout* updateDelayBox = new QHBoxLayout( box, 6 ); + QLabel* lUpdateDelay = new QLabel( i18n("Status update delay (time in msec.)")+":", parent, "lUpdateDelay" ); + updateDelayBox->addWidget( lUpdateDelay ); + iUpdateDelay = new KIntSpinBox( 100, 5000, 100, config->data.general.updateDelay, 10, parent, "iUpdateDelay" ); + QToolTip::add( iUpdateDelay, i18n("Update the progress bar in this interval (time in milliseconds)") ); + updateDelayBox->addWidget( iUpdateDelay ); + connect( iUpdateDelay, SIGNAL(valueChanged(int)), + this, SLOT(cfgChanged()) + ); + + box->addSpacing( 5 ); + + QHBoxLayout* askForNewOptionsBox = new QHBoxLayout( box, 6 ); + cAskForNewOptions = new QCheckBox( i18n("Ask for new options, when adding files from external program"), parent, "cAskForNewOptions" ); + QToolTip::add( cAskForNewOptions, i18n("If you open a file with soundKonverter and soundKonverter is already running,\nyou can either be asked to define new converting options\nor the current settings from the soundKonverter main window are used.") ); + cAskForNewOptions->setChecked( config->data.general.askForNewOptions ); + askForNewOptionsBox->addWidget( cAskForNewOptions ); + connect( cAskForNewOptions, SIGNAL(toggled(bool)), + this, SLOT(cfgChanged()) + ); + + box->addSpacing( 5 ); + + QHBoxLayout* executeUserScriptBox = new QHBoxLayout( box, 6 ); + cExecuteUserScript = new QCheckBox( i18n("Execute user script (for advanced users)"), parent, "cAskForNewOptions" ); + QToolTip::add( cExecuteUserScript, i18n("Executes a script after every finished conversion. Have a look at $KDEDIR/soundkonverter/userscript.sh") ); + cExecuteUserScript->setChecked( config->data.general.executeUserScript ); + executeUserScriptBox->addWidget( cExecuteUserScript ); + connect( cExecuteUserScript, SIGNAL(toggled(bool)), + this, SLOT(cfgChanged()) + ); + + box->addStretch(); + + // delete the icon loader object + delete iconLoader; +} + +ConfigGeneralPage::~ConfigGeneralPage() +{} + +void ConfigGeneralPage::resetDefaults() +{ + cStartTab->setCurrentItem( 0 ); + cDefaultProfile->setCurrentItem( 0 ); + cDefaultFormat->setCurrentItem( 0 ); +// lDir->setText( QDir::homeDirPath() + "/soundKonverter/%b/%d - %n - %a - %t" ); + cPriority->setCurrentItem( 1 ); + cUseVFATNames->setChecked( true ); + cConflictHandling->setCurrentItem( 0 ); + iNumFiles->setValue( 3 ); + iUpdateDelay->setValue( 500 ); + cAskForNewOptions->setChecked( true ); + cExecuteUserScript->setChecked( false ); + + cfgChanged(); +} + +void ConfigGeneralPage::saveSettings() +{ + config->data.general.startTab = cStartTab->currentItem(); + config->data.general.defaultProfile = cDefaultProfile->currentText(); + config->data.general.defaultFormat = cDefaultFormat->currentText(); +// config->data.general.defaultOutputDirectory = lDir->text(); + config->data.general.priority = cPriority->currentItem() * 10; // NOTE that just works for 'normal' and 'low' + config->data.general.useVFATNames = cUseVFATNames->isChecked(); + config->data.general.conflictHandling = cConflictHandling->currentItem(); + config->data.general.numFiles = iNumFiles->value(); + config->data.general.updateDelay = iUpdateDelay->value(); + config->data.general.askForNewOptions = cAskForNewOptions->isChecked(); + config->data.general.executeUserScript = cExecuteUserScript->isChecked(); +} + +int ConfigGeneralPage::profileIndex( const QString &string ) +{ + return sDefaultProfile.findIndex( string ); +} + +int ConfigGeneralPage::formatIndex( const QString &string ) +{ + return sDefaultFormat.findIndex( string ); +} + +// void ConfigGeneralPage::selectDir() +// { +// QString startDir = lDir->text(); +// int i = startDir.find( QRegExp("%[aAbBcCdDgGnNpPtTyY]{1,1}") ); +// if( i != -1 ) { +// i = startDir.findRev( "/", i ); +// startDir = startDir.left( i ); +// } +// +// QString directory = KFileDialog::getExistingDirectory( startDir, 0, i18n("Choose an output directory") ); +// if( !directory.isEmpty() ) { +// QString dir = lDir->text(); +// i = dir.find( QRegExp("%[aAbBcCdDgGnNpPtTyY]{1,1}") ); +// if( i != -1 ) { +// i = dir.findRev( "/", i ); +// lDir->setText( directory + dir.mid(i) ); +// } +// else { +// lDir->setText( directory ); +// } +// } +// } + +void ConfigGeneralPage::profileChanged() +{ + QString last; + + if( cDefaultProfile->currentText() == i18n("Last used") ) { + last = cDefaultFormat->currentText(); + if( last.isEmpty() ) last = config->data.general.defaultFormat; + cDefaultFormat->clear(); + sDefaultFormat = i18n("Last used"); + cDefaultFormat->insertStringList( sDefaultFormat ); + cDefaultFormat->setCurrentItem( formatIndex(last) ); + return; + } + + ConversionOptions options = config->getProfile( cDefaultProfile->currentText() ); + if( !options.encodingOptions.sFormat.isEmpty() ) { + last = cDefaultFormat->currentText(); + cDefaultFormat->clear(); + sDefaultFormat = options.encodingOptions.sFormat; + cDefaultFormat->insertStringList( sDefaultFormat ); + cDefaultFormat->setCurrentItem( formatIndex(last) ); + return; + } + + if( cDefaultProfile->currentText() == i18n("Very low") || + cDefaultProfile->currentText() == i18n("Low") || + cDefaultProfile->currentText() == i18n("Medium") || + cDefaultProfile->currentText() == i18n("High") || + cDefaultProfile->currentText() == i18n("Very high") ) { + last = cDefaultFormat->currentText(); + if( last.isEmpty() ) last = config->data.general.defaultFormat; + cDefaultFormat->clear(); + sDefaultFormat = i18n("Last used"); + sDefaultFormat += config->allLossyEncodableFormats(); + cDefaultFormat->insertStringList( sDefaultFormat ); + cDefaultFormat->setCurrentItem( formatIndex(last) ); + } + else if( cDefaultProfile->currentText() == i18n("Lossless") ) { + last = cDefaultFormat->currentText(); + if( last.isEmpty() ) last = config->data.general.defaultFormat; + cDefaultFormat->clear(); + sDefaultFormat = i18n("Last used"); + sDefaultFormat += config->allLosslessEncodableFormats(); + sDefaultFormat += "wav"; + cDefaultFormat->insertStringList( sDefaultFormat ); + cDefaultFormat->setCurrentItem( formatIndex(last) ); + } + else if( cDefaultProfile->currentText() == i18n("Hybrid") ) { + last = cDefaultFormat->currentText(); + if( last.isEmpty() ) last = config->data.general.defaultFormat; + cDefaultFormat->clear(); + sDefaultFormat = i18n("Last used"); + sDefaultFormat += config->allHybridEncodableFormats(); + cDefaultFormat->insertStringList( sDefaultFormat ); + cDefaultFormat->setCurrentItem( formatIndex(last) ); + } +} + + diff --git a/src/configgeneralpage.h b/src/configgeneralpage.h new file mode 100755 index 0000000..270cb47 --- /dev/null +++ b/src/configgeneralpage.h @@ -0,0 +1,69 @@ + + +#ifndef CONFIGGENERALPAGE_H +#define CONFIGGENERALPAGE_H + +#include + +class Config; +class QCheckBox; +class KComboBox; +class KIntSpinBox; +class KLineEdit; +class KPushButton; + +/** + * @short The page for the general configuration + * @author Daniel Faust + * @version 0.3 + */ +class ConfigGeneralPage : public ConfigPageBase +{ + Q_OBJECT +public: + /** + * Default Constructor + */ + ConfigGeneralPage( Config*, QWidget *parent=0, const char *name=0 ); + + /** + * Default Destructor + */ + virtual ~ConfigGeneralPage(); + +private: + KComboBox* cStartTab; + KComboBox* cDefaultProfile; + QStringList sDefaultProfile; + KComboBox* cDefaultFormat; + QStringList sDefaultFormat; +// KLineEdit* lDir; + //KPushButton* pDirInfo; +// KPushButton* pDirSelect; + KComboBox* cPriority; + QStringList sPriority; + QCheckBox* cUseVFATNames; + QStringList sConflictHandling; + KComboBox* cConflictHandling; + KIntSpinBox* iNumFiles; + KIntSpinBox* iUpdateDelay; + QCheckBox* cAskForNewOptions; + QCheckBox* cExecuteUserScript; + + Config* config; + + int profileIndex( const QString& string ); + int formatIndex( const QString& string ); + +public slots: + void resetDefaults(); + void saveSettings(); + +private slots: +// void selectDir(); + void profileChanged(); + +}; + +#endif // CONFIGGENERALPAGE_H + diff --git a/src/configpagebase.cpp b/src/configpagebase.cpp new file mode 100755 index 0000000..1aedea5 --- /dev/null +++ b/src/configpagebase.cpp @@ -0,0 +1,20 @@ + +#include "configpagebase.h" + +ConfigPageBase::ConfigPageBase( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{} + +ConfigPageBase::~ConfigPageBase() +{} + +void ConfigPageBase::resetDefaults() +{} + +void ConfigPageBase::saveSettings() +{} + +void ConfigPageBase::cfgChanged() +{ + emit configChanged(); +} diff --git a/src/configpagebase.h b/src/configpagebase.h new file mode 100755 index 0000000..802bb2d --- /dev/null +++ b/src/configpagebase.h @@ -0,0 +1,38 @@ + + +#ifndef CONFIGPAGEBASE_H +#define CONFIGPAGEBASE_H + +#include + +/** + * @short The base for all pages of the config dialog + * @author Daniel Faust + * @version 0.3 + */ +class ConfigPageBase : public QWidget +{ + Q_OBJECT +public: + /** + * Constructor + */ + ConfigPageBase( QWidget *parent=0, const char *name=0 ); + + /** + * Destructor + */ + virtual ~ConfigPageBase(); + +public slots: + virtual void resetDefaults(); + virtual void saveSettings(); + void cfgChanged(); + +signals: + void configChanged(); + +}; + +#endif // CONFIGPAGEBASE_H + diff --git a/src/configpluginspage.cpp b/src/configpluginspage.cpp new file mode 100755 index 0000000..a6bc560 --- /dev/null +++ b/src/configpluginspage.cpp @@ -0,0 +1,639 @@ + +#include "configpluginspage.h" +#include "config.h" +#include "convertpluginloader.h" +#include "replaygainpluginloader.h" +#include "ripperpluginloader.h" + +#include +#include +#include +#include +#include +// #include +// #include +#include +#include +// #include + +#include +#include +#include +#include +#include +#include +#include +#include +//#include + +ConfigPluginsPage::ConfigPluginsPage( Config* _config, QWidget* parent, const char* name ) + : ConfigPageBase( parent, name ) +{ + config = _config; + + // create an icon loader object for loading icons + KIconLoader* iconLoader = new KIconLoader(); + + QVBoxLayout* box = new QVBoxLayout( parent, 0, 6 ); + + QLabel* lPluginsLabel = new QLabel( i18n("Installed plugins")+":", parent, "lPluginsLabel" ); + box->addWidget( lPluginsLabel ); + QHBoxLayout* pluginsBox = new QHBoxLayout( box ); + lPlugins = new KListBox( parent, "lPlugins" ); + pluginsBox->addWidget(lPlugins); + connect( lPlugins, SIGNAL(highlighted(int)), + this, SLOT(pluginsSelectionChanged(int)) + ); + refreshPlugins(); + + QVBoxLayout* pluginsRightBox = new QVBoxLayout( pluginsBox ); + pAddPlugin = new KPushButton( iconLoader->loadIcon("add",KIcon::Small), i18n("Add ..."), parent, "pAddPlugin" ); + pluginsRightBox->addWidget( pAddPlugin ); + connect( pAddPlugin, SIGNAL(clicked()), + this, SLOT(getPlugin()) + ); + pRemovePlugin = new KPushButton( iconLoader->loadIcon("remove",KIcon::Small), i18n("Remove"), parent, "pRemovePlugin" ); + pRemovePlugin->setEnabled( false ); + pluginsRightBox->addWidget( pRemovePlugin ); + connect( pRemovePlugin, SIGNAL(clicked()), + this, SLOT(removePlugin()) + ); + pluginsRightBox->addStretch(); + pAboutPlugin = new KPushButton( iconLoader->loadIcon("messagebox_info",KIcon::Small), i18n("About"), parent, "pAboutPlugin" ); + pAboutPlugin->setEnabled( false ); + pluginsRightBox->addWidget( pAboutPlugin ); + connect( pAboutPlugin, SIGNAL(clicked()), + this, SLOT(aboutPlugin()) + ); +/* NOTE kaligames.de is down + box->addSpacing( 5 ); + + QLabel* lOnlinePluginsLabel = new QLabel( i18n("Available plugins")+":", parent, "lOnlinePluginsLabel" ); + box->addWidget( lOnlinePluginsLabel ); + QHBoxLayout* onlinePluginsBox = new QHBoxLayout( box ); + lOnlinePlugins = new KListBox( parent, "lOnlinePlugins" ); + onlinePluginsBox->addWidget( lOnlinePlugins ); + connect( lOnlinePlugins, SIGNAL(highlighted(int)), + this, SLOT(onlinePluginsSelectionChanged(int)) + ); + QVBoxLayout* onlinePluginsRightBox = new QVBoxLayout( onlinePluginsBox ); + pRefreshOnlinePlugins = new KPushButton( iconLoader->loadIcon("reload",KIcon::Small), i18n("Refresh"), parent, "pRefreshOnlinePlugins" ); + QToolTip::add( pRefreshOnlinePlugins, i18n("Download the latest list of available plugins.") ); + onlinePluginsRightBox->addWidget( pRefreshOnlinePlugins ); + connect( pRefreshOnlinePlugins, SIGNAL(clicked()), + this, SLOT(refreshOnlinePlugins()) + ); + // TODO upgrade button +// pUpgradeOnlinePlugins = new KPushButton( iconLoader->loadIcon("filesave",KIcon::Small), i18n("Upgrade"), parent, "pUpgradeOnlinePlugins" ); +// pUpgradeOnlinePlugins->setEnabled( false ); +// QToolTip::add( pUpgradeOnlinePlugins, i18n("Download all plugins and install them into the soundKonverter directory.") ); +// onlinePluginsRightBox->addWidget( pUpgradeOnlinePlugins ); +// connect(pInstallAllOnlinePlugins,SIGNAL(clicked()),this,SLOT(upgradeOnlinePlugins())); + onlinePluginsRightBox->addStretch(); + pInstallOnlinePlugin = new KPushButton( iconLoader->loadIcon("filesave",KIcon::Small), i18n("Install"), parent, "pInstallOnlinePlugin" ); + pInstallOnlinePlugin->setEnabled( false ); + QToolTip::add( pInstallOnlinePlugin, i18n("Download the selected plugin and install it into the soundKonverter directory.") ); + onlinePluginsRightBox->addWidget( pInstallOnlinePlugin ); + connect( pInstallOnlinePlugin, SIGNAL(clicked()), + this, SLOT(getOnlinePlugin()) + ); + pAboutOnlinePlugin = new KPushButton( iconLoader->loadIcon("messagebox_info",KIcon::Small), i18n("About"), parent, "pAboutOnlinePlugin" ); + pAboutOnlinePlugin->setEnabled( false ); + onlinePluginsRightBox->addWidget( pAboutOnlinePlugin ); + connect( pAboutOnlinePlugin, SIGNAL(clicked()), + this, SLOT(aboutOnlinePlugin()) + ); + cCheckOnlinePlugins = new QCheckBox( i18n("Check for new plugins on every startup"), parent, "cCheckOnlinePlugins" ); + cCheckOnlinePlugins->setChecked( config->data.plugins.checkForUpdates ); + box->addWidget( cCheckOnlinePlugins ); + connect( cCheckOnlinePlugins, SIGNAL(toggled(bool)), + this, SLOT(cfgChanged()) + ); + +// box->addStretch(); + + // delete the icon loader object + delete iconLoader; + + if( config->data.plugins.checkForUpdates && config->onlinePluginsChanged ) { + // NOTE copied from below + QString line; + bool add; + QFile file( locateLocal("data","soundkonverter/pluginlist.txt") ); + if( file.open(IO_ReadOnly) ) { + QTextStream stream( &file ); + while( !stream.atEnd() ) { + line = stream.readLine(); // line of text excluding '\n' + line.replace( "&", "&" ); + line.replace( "ä", "ä" ); + line.replace( "Ä", "Ä" ); + line.replace( "ö", "ö" ); + line.replace( "Ö", "Ö" ); + line.replace( "ü", "ü" ); + line.replace( "Ü", "Ü" ); + line.replace( "ß", "ß" ); + + add = true; + for( uint i=0; icount(); i++ ) { + if( lPlugins->text(i) == line ) { + add = false; + break; + } + } + if( add ) lOnlinePlugins->insertItem( line ); + } + file.close(); + } + } +*/ +} + +ConfigPluginsPage::~ConfigPluginsPage() +{} + +void ConfigPluginsPage::resetDefaults() +{ +// cCheckOnlinePlugins->setChecked( false ); + +// cfgChanged(); +} + +void ConfigPluginsPage::saveSettings() +{ +// config->data.plugins.checkForUpdates = cCheckOnlinePlugins->isChecked(); +} + +void ConfigPluginsPage::pluginsSelectionChanged( int index ) +{ + QString name = lPlugins->text( index ); + + QValueList converters = config->allConverters(); + for( QValueList::Iterator it = converters.begin(); it != converters.end(); ++it ) { + if( name == (*it)->info.name + " v. " + QString::number((*it)->info.version) ) { + QFileInfo file( (*it)->filePathName ); + if( file.isWritable() ) pRemovePlugin->setEnabled( true ); + else pRemovePlugin->setEnabled( false ); + break; + } + } + + QValueList replaygains = config->allReplayGains(); + for( QValueList::Iterator it = replaygains.begin(); it != replaygains.end(); ++it ) { + if( name == (*it)->info.name + " v. " + QString::number((*it)->info.version) ) { + QFileInfo file( (*it)->filePathName ); + if( file.isWritable() ) pRemovePlugin->setEnabled( true ); + else pRemovePlugin->setEnabled( false ); + break; + } + } + + QValueList rippers = config->allRippers(); + for( QValueList::Iterator it = rippers.begin(); it != rippers.end(); ++it ) { + if( name == (*it)->info.name + " v. " + QString::number((*it)->info.version) ) { + QFileInfo file( (*it)->filePathName ); + if( file.isWritable() ) pRemovePlugin->setEnabled( true ); + else pRemovePlugin->setEnabled( false ); + break; + } + } + + pAboutPlugin->setEnabled( true ); +} + +void ConfigPluginsPage::refreshPlugins() +{ + lPlugins->clear(); + + QValueList converters = config->allConverters(); + for( QValueList::Iterator it = converters.begin(); it != converters.end(); ++it ) { + lPlugins->insertItem( (*it)->info.name + " v. " + QString::number((*it)->info.version) ); + //lPlugins->insertItem( i18n("%1, Version: %2").arg((*it)->info.name).arg((*it)->info.version) ); + } + + QValueList replaygains = config->allReplayGains(); + for( QValueList::Iterator it = replaygains.begin(); it != replaygains.end(); ++it ) { + lPlugins->insertItem( (*it)->info.name + " v. " + QString::number((*it)->info.version) ); + //lPlugins->insertItem( i18n("%1, Version: %2").arg((*it)->info.name).arg((*it)->info.version) ); + } + + QValueList rippers = config->allRippers(); + for( QValueList::Iterator it = rippers.begin(); it != rippers.end(); ++it ) { + lPlugins->insertItem( (*it)->info.name + " v. " + QString::number((*it)->info.version) ); + //lPlugins->insertItem( i18n("%1, Version: %2").arg((*it)->info.name).arg((*it)->info.version) ); + } +} + +void ConfigPluginsPage::getPlugin() +{ + QString url = KFileDialog::getOpenFileName( QDir::homeDirPath(), i18n("*.soundkonverter.xml|Plugins (*.soundkonverter.xml)"), this, i18n("Choose a plugin to add!") ); + if( !url.isEmpty() ) { + QString filePathName = KURL::decode_string( url ); + QString fileName = filePathName.right( filePathName.length() - filePathName.findRev("/") ); + getPluginFilePathName = locateLocal("data","soundkonverter/plugins/") + fileName; + getPluginJob = KIO::file_copy( url, getPluginFilePathName, -1, true, false, false ); + connect( getPluginJob, SIGNAL(result(KIO::Job*)), + this, SLOT(getPluginFinished(KIO::Job*)) + ); + } +} + +void ConfigPluginsPage::getPluginFinished( KIO::Job* job ) +{ + if( job->error() == 0 ) { + ConvertPluginLoader* convertPluginLoader = new ConvertPluginLoader(); + ReplayGainPluginLoader* replaygainPluginLoader = new ReplayGainPluginLoader(); + RipperPluginLoader* ripperPluginLoader = new RipperPluginLoader(); + + if( convertPluginLoader->verifyFile(getPluginFilePathName) == -1 && + replaygainPluginLoader->verifyFile(getPluginFilePathName) == -1 && + ripperPluginLoader->verifyFile(getPluginFilePathName) == -1 ) + { + KIO::del( getPluginFilePathName, false, false ); + KMessageBox::error( this, + i18n("The plugin could not be installed. Please ensure that you have selected a valid soundKonverter plugin file."), + i18n("Error while installing plugin") ); + } + else + { + // TODO reload plugins without restart +// ConvertPlugin* plugin = convertPluginLoader->loadFile( getPluginFilePathName ); +// if( plugin->info.version != -1 ) { +// lPlugins->insertItem( plugin->info.name + " v. " + QString::number(plugin->info.version) + " (" + i18n("restart necessary") + ")" ); +// } +// else { +// delete plugin; +// ConvertPlugin* plugin = convertPluginLoader->loadFile( getPluginFilePathName ); +// if( plugin->info.version != -1 ) { +// lPlugins->insertItem( plugin->info.name + " v. " + QString::number(plugin->info.version) + " (" + i18n("restart necessary") + ")" ); +// } +// else { +// delete plugin; +// ConvertPlugin* plugin = convertPluginLoader->loadFile( getPluginFilePathName ); +// if( plugin->info.version != -1 ) { +// lPlugins->insertItem( plugin->info.name + " v. " + QString::number(plugin->info.version) + " (" + i18n("restart necessary") + ")" ); +// } +// } +// } +// delete plugin; + KMessageBox::information( this, + i18n("The plugin was installed successfully. Please restart soundKonverter in order to activate it."), + i18n("Plugin successfully installed") ); + //config->reloadPlugins(); + //refreshPlugins(); + //emit rescanForBackends(); + //emit reloadEnDecoderPage(); + } + + delete convertPluginLoader; + delete replaygainPluginLoader; + delete ripperPluginLoader; + } + else { + KMessageBox::error( this, + i18n("The plugin could not be installed. Please ensure that you have write permission on your whole user directory."), + i18n("Error while installing plugin") ); + } +} + +void ConfigPluginsPage::removePlugin() +{ + // TODO reload plugins without restart + + QString name = lPlugins->currentText(); + + QValueList converters = config->allConverters(); + for( QValueList::Iterator it = converters.begin(); it != converters.end(); ++it ) { + if( name == (*it)->info.name + " v. " + QString::number((*it)->info.version) ) { + QFile file( (*it)->filePathName ); + if( file.remove() ) { + lPlugins->removeItem( lPlugins->currentItem() ); + KMessageBox::information( this, + i18n("The plugin was removed successfully. Please restart soundKonverter in order to deactivate it."), + i18n("Plugin successfully removed") ); + } + else { + KMessageBox::error( this, + i18n("The plugin could not be removed. Please ensure that you have write permission on your whole user directory."), + i18n("Error while removing plugin") ); + } + break; + } + } + + QValueList replaygains = config->allReplayGains(); + for( QValueList::Iterator it = replaygains.begin(); it != replaygains.end(); ++it ) { + if( name == (*it)->info.name + " v. " + QString::number((*it)->info.version) ) { + QFile file( (*it)->filePathName ); + if( file.remove() ) { + lPlugins->removeItem( lPlugins->currentItem() ); + KMessageBox::information( this, + i18n("The plugin was removed successfully. Please restart soundKonverter in order to deactivate it."), + i18n("Plugin successfully removed") ); + } + else { + KMessageBox::error( this, + i18n("The plugin could not be removed. Please ensure that you have write permission on your whole user directory."), + i18n("Error while removing plugin") ); + } + break; + } + } + + QValueList rippers = config->allRippers(); + for( QValueList::Iterator it = rippers.begin(); it != rippers.end(); ++it ) { + if( name == (*it)->info.name + " v. " + QString::number((*it)->info.version) ) { + QFile file( (*it)->filePathName ); + if( file.remove() ) { + lPlugins->removeItem( lPlugins->currentItem() ); + KMessageBox::information( this, + i18n("The plugin was removed successfully. Please restart soundKonverter in order to deactivate it."), + i18n("Plugin successfully removed") ); + } + else { + KMessageBox::error( this, + i18n("The plugin could not be removed. Please ensure that you have write permission on your whole user directory."), + i18n("Error while removing plugin") ); + } + break; + } + } + +/* backendPlugins.remove(lPlugins->currentText()); + replayGainPlugins.remove(lPlugins->currentText()); + backendPlugins.reload(); + replayGainPlugins.reload(); + lPlugins->clear(); + lPlugins->insertStringList(backendPlugins.loadedPlugins()); + lPlugins->insertStringList(replayGainPlugins.loadedPlugins()); + emit rescanForBackends(); + emit reloadEnDecoderPage();*/ +} + +void ConfigPluginsPage::aboutPlugin() +{ + // TODO add link support + + QString name = lPlugins->currentText(); + + QValueList converters = config->allConverters(); + for( QValueList::Iterator it = converters.begin(); it != converters.end(); ++it ) { + if( name == (*it)->info.name + " v. " + QString::number((*it)->info.version) ) { + KMessageBox::information( this, + i18n((*it)->info.about) + "\n" + + i18n("Version") + ": " + QString::number((*it)->info.version) + "\n" + + i18n("Author") + ": " + (*it)->info.author, + i18n("About") + ": " + (*it)->info.name ); + break; + } + } + + QValueList replaygains = config->allReplayGains(); + for( QValueList::Iterator it = replaygains.begin(); it != replaygains.end(); ++it ) { + if( name == (*it)->info.name + " v. " + QString::number((*it)->info.version) ) { + KMessageBox::information( this, + i18n((*it)->info.about) + "\n" + + i18n("Version") + ": " + QString::number((*it)->info.version) + "\n" + + i18n("Author") + ": " + (*it)->info.author, + i18n("About") + ": " + (*it)->info.name ); + break; + } + } + + QValueList rippers = config->allRippers(); + for( QValueList::Iterator it = rippers.begin(); it != rippers.end(); ++it ) { + if( name == (*it)->info.name + " v. " + QString::number((*it)->info.version) ) { + KMessageBox::information( this, + i18n((*it)->info.about) + "\n" + + i18n("Version") + ": " + QString::number((*it)->info.version) + "\n" + + i18n("Author") + ": " + (*it)->info.author, + i18n("About") + ": " + (*it)->info.name ); + break; + } + } +} + +void ConfigPluginsPage::onlinePluginsSelectionChanged( int index ) +{ + if( lOnlinePlugins->currentText() != i18n("No new plugins available!") ) { + pInstallOnlinePlugin->setEnabled( true ); + pAboutOnlinePlugin->setEnabled( true ); + } + else { + pInstallOnlinePlugin->setEnabled( false ); + pAboutOnlinePlugin->setEnabled( false ); + } +} + +void ConfigPluginsPage::refreshOnlinePlugins() +{ + pRefreshOnlinePlugins->setEnabled( false ); + + refreshOnlinePluginsJob = KIO::file_copy( "http://kaligames.de/downloads/soundkonverter/plugins/download.php?version=" + QString::number(config->data.app.configVersion), + locateLocal("data","soundkonverter/pluginlist.txt"), -1, true, false, false ); + connect( refreshOnlinePluginsJob, SIGNAL(result(KIO::Job*)), + this, SLOT(refreshOnlinePluginsFinished(KIO::Job*)) + ); +} + +void ConfigPluginsPage::refreshOnlinePluginsFinished( KIO::Job* job ) +{ + if( job->error() == 0 ) { + lOnlinePlugins->clear(); + + QString line; + bool add; + QFile file( locateLocal("data","soundkonverter/pluginlist.txt") ); + if( file.open(IO_ReadOnly) ) { + QTextStream stream( &file ); + while( !stream.atEnd() ) { + line = stream.readLine(); // line of text excluding '\n' + line.replace( "&", "&" ); + line.replace( "ä", "ä" ); + line.replace( "Ä", "Ä" ); + line.replace( "ö", "ö" ); + line.replace( "Ö", "Ö" ); + line.replace( "ü", "ü" ); + line.replace( "Ü", "Ü" ); + line.replace( "ß", "ß" ); + + add = true; + for( uint i=0; icount(); i++ ) { + if( lPlugins->text(i) == line ) { + add = false; + break; + } + } + if( add ) lOnlinePlugins->insertItem( line ); + } + file.close(); + } + + if( lOnlinePlugins->count() == 0 ) { + lOnlinePlugins->insertItem( i18n("No new plugins available!") ); + } + } + else { + KMessageBox::error( this, + i18n("The plugin list could not be downloaded. Please ensure, that your internet connection works correct.\nMaybe our server is busy at the moment, please try it again later."), + i18n("Error while loading plugin list") ); + } + + pRefreshOnlinePlugins->setEnabled( true ); +} + +void ConfigPluginsPage::getOnlinePlugin() +{ + pInstallOnlinePlugin->setEnabled( false ); + QString name; + + for( uint i=0; icount(); i++ ) { + if( lOnlinePlugins->isSelected(i) ) { + name = lOnlinePlugins->text( i ); + lOnlinePlugins->removeItem( i ); + break; + } + } + + name.replace( "&", "&" ); + name.replace( "ä", "ä" ); + name.replace( "Ä", "Ä" ); + name.replace( "ö", "ö" ); + name.replace( "Ö", "Ö" ); + name.replace( "ü", "ü" ); + name.replace( "Ü", "Ü" ); + name.replace( "ß", "ß" ); + KURL::encode_string( name ); + getOnlinePluginJob = KIO::file_copy( "http://kaligames.de/downloads/soundkonverter/plugins/getfile.php?version=" + QString::number(config->data.app.configVersion) + "&file=" + name, + locateLocal("data","soundkonverter/plugins/newplugin.xml"), -1, true, false, false ); + connect( getOnlinePluginJob, SIGNAL(result(KIO::Job*)), + this, SLOT(getOnlinePluginFinished(KIO::Job*)) + ); +} + +void ConfigPluginsPage::getOnlinePluginFinished( KIO::Job* job ) +{ + if( job->error() == 0 ) { + QString name; + QString line; + QFile file( locateLocal("data","soundkonverter/plugins/newplugin.xml") ); + if( file.open(IO_ReadOnly) ) { + QTextStream stream( &file ); + name = stream.readLine(); // read the file name from the top of the file + getPluginFilePathName = locateLocal("data","soundkonverter/plugins/") + name; + QFile newFile( getPluginFilePathName ); + if( newFile.open(IO_WriteOnly) ) { + QTextStream newStream( &newFile ); + while( !stream.atEnd() ) { + line = stream.readLine(); // line of text excluding '\n' + newStream << line << "\n"; + } + newFile.close(); + } + file.close(); + } + file.remove(); + + ConvertPluginLoader* convertPluginLoader = new ConvertPluginLoader(); + ReplayGainPluginLoader* replaygainPluginLoader = new ReplayGainPluginLoader(); + RipperPluginLoader* ripperPluginLoader = new RipperPluginLoader(); + + if( convertPluginLoader->verifyFile(getPluginFilePathName) == -1 && + replaygainPluginLoader->verifyFile(getPluginFilePathName) == -1 && + ripperPluginLoader->verifyFile(getPluginFilePathName) == -1 ) + { + KIO::del( getPluginFilePathName, false, false ); + KMessageBox::error( this, + i18n("The plugin could not be installed. Please ensure that you have selected a valid soundKonverter plugin file."), + i18n("Error while installing plugin") ); + } + else + { + // TODO reload plugins without restart +// ConvertPlugin* plugin = convertPluginLoader->loadFile( getPluginFilePathName ); +// if( plugin->info.version != -1 ) { +// lPlugins->insertItem( plugin->info.name + " v. " + QString::number(plugin->info.version) + " (" + i18n("restart necessary") + ")" ); +// } +// else { +// delete plugin; +// ConvertPlugin* plugin = convertPluginLoader->loadFile( getPluginFilePathName ); +// if( plugin->info.version != -1 ) { +// lPlugins->insertItem( plugin->info.name + " v. " + QString::number(plugin->info.version) + " (" + i18n("restart necessary") + ")" ); +// } +// else { +// delete plugin; +// ConvertPlugin* plugin = convertPluginLoader->loadFile( getPluginFilePathName ); +// if( plugin->info.version != -1 ) { +// lPlugins->insertItem( plugin->info.name + " v. " + QString::number(plugin->info.version) + " (" + i18n("restart necessary") + ")" ); +// } +// } +// } +// delete plugin; + KMessageBox::information( this, + i18n("The plugin was installed successfully. Please restart soundKonverter in order to activate it."), + i18n("Plugin successfully installed") ); + //config->reloadPlugins(); + //refreshPlugins(); + //emit rescanForBackends(); + //emit reloadEnDecoderPage(); + } + + delete convertPluginLoader; + delete replaygainPluginLoader; + delete ripperPluginLoader; + } + else { + KMessageBox::error( this, + i18n("The plugin could not be installed. Please ensure that you have write permission on your whole user directory."), + i18n("Error while installing plugin") ); + } +} + +void ConfigPluginsPage::aboutOnlinePlugin() +{ + pAboutOnlinePlugin->setEnabled( false ); + + QString name = lOnlinePlugins->currentText(); + name.replace( "&", "&" ); + name.replace( "ä", "ä" ); + name.replace( "Ä", "Ä" ); + name.replace( "ö", "ö" ); + name.replace( "Ö", "Ö" ); + name.replace( "ü", "ü" ); + name.replace( "Ü", "Ü" ); + name.replace( "ß", "ß" ); + KURL::encode_string( name ); + aboutOnlinePluginJob = KIO::file_copy( "http://kaligames.de/downloads/soundkonverter/plugins/info.php?file=" + name + "&lang=" + QLocale::languageToString(QLocale::system().language()), + locateLocal("data","soundkonverter/plugin_info.txt"), -1, true, false, false ); + connect( aboutOnlinePluginJob, SIGNAL(result(KIO::Job*)), + this, SLOT(aboutOnlinePluginFinished(KIO::Job*)) + ); +} + +void ConfigPluginsPage::aboutOnlinePluginFinished( KIO::Job* job ) +{ + if( job->error() == 0 ) { + QString name = lOnlinePlugins->currentText(); + + QFile file( locateLocal("data","soundkonverter/plugin_info.txt") ); + if( file.open(IO_ReadOnly) ) { + QTextStream stream( &file ); + QString data = stream.readLine(); + KMessageBox::information( this, i18n(data), i18n("About") + ": " + name, + QString::null, KMessageBox::Notify | KMessageBox::AllowLink ); + } + else { + KMessageBox::error( this, + i18n("The plugin info could not be downloaded. Please ensure, that your internet connection works correctly."), + i18n("Error while loading plugin info") ); + } + } + else { + KMessageBox::error( this, + i18n("The plugin info could not be downloaded. Please ensure, that your internet connection works correctly."), + i18n("Error while loading plugin info") ); + } + + pAboutOnlinePlugin->setEnabled( true ); +} + + diff --git a/src/configpluginspage.h b/src/configpluginspage.h new file mode 100755 index 0000000..2cca5ed --- /dev/null +++ b/src/configpluginspage.h @@ -0,0 +1,82 @@ + +#ifndef CONFIGPLUGINSPAGE_H +#define CONFIGPLUGINSPAGE_H + +#include + +#include + +class Config; +class KPushButton; +class KListBox; +class QCheckBox; + +/** + * @short The page for configuring the plugins + * @author Daniel Faust + * @version 0.3 + */ +class ConfigPluginsPage : public ConfigPageBase +{ + Q_OBJECT +public: + /** + * Default Constructor + */ + ConfigPluginsPage( Config*, QWidget *parent=0, const char *name=0 ); + + /** + * Default Destructor + */ + virtual ~ConfigPluginsPage(); + +private: + KListBox* lPlugins; + KPushButton* pAddPlugin; + KIO::FileCopyJob* getPluginJob; + KPushButton* pRemovePlugin; + KPushButton* pAboutPlugin; + KListBox* lOnlinePlugins; + KPushButton* pRefreshOnlinePlugins; + KIO::FileCopyJob* refreshOnlinePluginsJob; + KPushButton* pInstallOnlinePlugin; + KIO::FileCopyJob* getOnlinePluginJob; + KPushButton* pUpgradeOnlinePlugins; + KPushButton* pAboutOnlinePlugin; + KIO::FileCopyJob* aboutOnlinePluginJob; + QCheckBox* cCheckOnlinePlugins; + + QString getPluginFilePathName; + + Config* config; + +public slots: + void resetDefaults(); + void saveSettings(); + +// signals: +// void configChanged(); +// void recalcEnDecoderPage(); +// void reloadEnDecoderPage(); +// void rescanForBackends(); + +private slots: + void pluginsSelectionChanged( int ); + void refreshPlugins(); + void getPlugin(); + void getPluginFinished( KIO::Job* ); + void removePlugin(); + void aboutPlugin(); + + void onlinePluginsSelectionChanged( int ); + void refreshOnlinePlugins(); + void refreshOnlinePluginsFinished( KIO::Job* ); + void getOnlinePlugin(); + void getOnlinePluginFinished( KIO::Job* ); + void aboutOnlinePlugin(); + void aboutOnlinePluginFinished( KIO::Job* ); + +}; + +#endif // CONFIGPLUGINSPAGE_H + diff --git a/src/conversionoptions.cpp b/src/conversionoptions.cpp new file mode 100755 index 0000000..2c5ad22 --- /dev/null +++ b/src/conversionoptions.cpp @@ -0,0 +1,86 @@ + +#include "conversionoptions.h" + +ConversionOptions::ConversionOptions() // TODO reset all values +{} + +ConversionOptions::~ConversionOptions() +{} + +bool ConversionOptions::nearlyEqual( const ConversionOptions& other ) +{ + if( encodingOptions.sFormat != other.encodingOptions.sFormat || + encodingOptions.sQualityMode != other.encodingOptions.sQualityMode || + encodingOptions.iQuality != other.encodingOptions.iQuality || + encodingOptions.sBitrateMode != other.encodingOptions.sBitrateMode || + encodingOptions.bBitrateRange != other.encodingOptions.bBitrateRange || + encodingOptions.samplingRate.bEnabled != other.encodingOptions.samplingRate.bEnabled || + encodingOptions.channels.bEnabled != other.encodingOptions.channels.bEnabled || + encodingOptions.replaygain.bEnabled != other.encodingOptions.replaygain.bEnabled || + encodingOptions.sInOutFiles != other.encodingOptions.sInOutFiles ) { + return false; + } + if( encodingOptions.bBitrateRange ) { + if( encodingOptions.iMinBitrate != other.encodingOptions.iMinBitrate || + encodingOptions.iMaxBitrate != other.encodingOptions.iMaxBitrate ) { + return false; + } + } + if( encodingOptions.samplingRate.bEnabled ) { + if( encodingOptions.samplingRate.iSamplingRate != other.encodingOptions.samplingRate.iSamplingRate ) { + return false; + } + } + if( encodingOptions.channels.bEnabled ) { + if( encodingOptions.channels.sChannels != other.encodingOptions.channels.sChannels ) { + return false; + } + } + + if( outputOptions.mode != other.outputOptions.mode || + outputOptions.directory != other.outputOptions.directory ) { + return false; + } + + return true; +} + +/*bool ConversionOptions::nearlyEqual( ConversionOptions* other ) +{ + if( encodingOptions.sFormat != other->encodingOptions.sFormat || + encodingOptions.sQualityMode != other->encodingOptions.sQualityMode || + encodingOptions.iQuality != other->encodingOptions.iQuality || + encodingOptions.sBitrateMode != other->encodingOptions.sBitrateMode || + encodingOptions.bBitrateRange != other->encodingOptions.bBitrateRange || + encodingOptions.samplingRate.bEnabled != other->encodingOptions.samplingRate.bEnabled || + encodingOptions.channels.bEnabled != other->encodingOptions.channels.bEnabled || + encodingOptions.replaygain.bEnabled != other->encodingOptions.replaygain.bEnabled || + encodingOptions.sInOutFiles != other->encodingOptions.sInOutFiles ) { + return false; + } + if( encodingOptions.bBitrateRange ) { + if( encodingOptions.iMinBitrate != other->encodingOptions.iMinBitrate || + encodingOptions.iMaxBitrate != other->encodingOptions.iMaxBitrate ) { + return false; + } + } + if( encodingOptions.samplingRate.bEnabled ) { + if( encodingOptions.samplingRate.iSamplingRate != other->encodingOptions.samplingRate.iSamplingRate ) { + return false; + } + } + if( encodingOptions.channels.bEnabled ) { + if( encodingOptions.channels.sChannels != other->encodingOptions.channels.sChannels ) { + return false; + } + } + + if( outputOptions.mode != other->outputOptions.mode || + outputOptions.directory != other->outputOptions.directory ) { + return false; + } + + return true; +}*/ + + diff --git a/src/conversionoptions.h b/src/conversionoptions.h new file mode 100755 index 0000000..b1e9d9a --- /dev/null +++ b/src/conversionoptions.h @@ -0,0 +1,65 @@ + + +#ifndef CONVERSIONOPTIONS_H +#define CONVERSIONOPTIONS_H + +#include "outputdirectory.h" + +#include + +/** + * @short Here the options for the conversion process can be stored + * @author Daniel Faust + * @version 0.3 + */ +class ConversionOptions +{ +public: + struct EncodingOptions { + QString sFormat; // output format + QString sQualityMode; // which mode are we using? quality, bitrate, lossless? i18n()!!! + int iQuality; // the encoding quality / bitrate + QString sBitrateMode; // when using bitrate mode, which? abr, cbr? + bool bBitrateRange; // enable bitrate range? + int iMinBitrate, iMaxBitrate; // when using bitrate range + struct SamplingRateOptions { // special options, when sampling rate is enabled + bool bEnabled; + int iSamplingRate; + } samplingRate; + struct ChannelsOptions { // special options, when channels is enabled + bool bEnabled; + QString sChannels; + } channels; + struct ReplaygainOptions { // special options, when replaygain is enabled + bool bEnabled; + } replaygain; + QString sInOutFiles; // could be called 'user defined parameter' + // but it is analog to the in_out_files option in the plugins + }; + struct OutputOptions { + OutputDirectory::Mode mode; + QString directory; + }; + + /** + * Constructor + */ + ConversionOptions(); + + /** + * Destructor + */ + virtual ~ConversionOptions(); + + /** + * Checks whether this ConversionOptions and @p other are equal, except the 'filePathName' and 'outputFilePathName' members + */ + bool nearlyEqual( const ConversionOptions& other ); + + QString filePathName; // the path and name of the file + QString outputFilePathName; // if the user wants to change the output directory/file name per file! + EncodingOptions encodingOptions; // what shall we do with the file? + OutputOptions outputOptions; // where to save the file? +}; + +#endif // CONVERSIONOPTIONS_H diff --git a/src/convert.cpp b/src/convert.cpp new file mode 100755 index 0000000..ce435ab --- /dev/null +++ b/src/convert.cpp @@ -0,0 +1,1615 @@ + +#include "convert.h" +//#include "conversionoptions.h" +#include "convertpluginloader.h" +#include "replaygainpluginloader.h" +#include "replaygain.h" +#include "ripperpluginloader.h" +#include "config.h" +#include "tagengine.h" +#include "cdmanager.h" +#include "logger.h" +#include "filelist.h" +#include "replaygainscanner.h" + +#include + +#include +#include +//#include +#include +#include +//#include +#include + +#include +#include + +ConvertItem::ConvertItem() +{ + // create a new item with the file list item pointer set to zero + ConvertItem( (FileListItem*)0 ); +} + +ConvertItem::ConvertItem( FileListItem* item ) +{ + fileListItem = item; + getTime = getCorrectionTime = ripTime = decodeTime = encodeTime = replaygainTime = 0; +} + +ConvertItem::~ConvertItem() +{} + + +Convert::Convert( Config* _config, TagEngine* _tagEngine, CDManager* _cdManager, FileList* _fileList, Logger* _logger ) +{ + config = _config; + tagEngine = _tagEngine; + cdManager = _cdManager; + fileList = _fileList; + connect( fileList, SIGNAL(convertItem(FileListItem*)), + this, SLOT(add(FileListItem*)) + ); + connect( fileList, SIGNAL(stopItem(FileListItem*)), + this, SLOT(stop(FileListItem*)) + ); + connect( this, SIGNAL(finished(FileListItem*,int)), + fileList, SLOT(itemFinished(FileListItem*,int)) + ); + connect( this, SIGNAL(rippingFinished(const QString&)), + fileList, SLOT(rippingFinished(const QString&)) + ); + logger = _logger; + connect( this, SIGNAL(finishedProcess(int,int)), + logger, SLOT(processCompleted(int,int)) + ); + + tUpdateProgressIndicator = new QTimer( this, "tUpdateProgressIndicator" ); + connect( tUpdateProgressIndicator, SIGNAL(timeout()), + this, SLOT(updateProgressIndicator()) + ); +} + +Convert::~Convert() +{} + +void Convert::cleanUp() +{ + // TODO clean up +} + +void Convert::get( ConvertItem* item ) +{ + logger->log( item->logID, i18n("Getting file") ); + item->state = ConvertItem::get; + + item->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Getting file")+"... 00 %" ); + + KURL source( item->fileListItem->options.filePathName.replace("?","%3f") ); + KURL destination( item->tempInFile->name() ); + + if( source.isLocalFile() && destination.isLocalFile() ) { + item->convertProcess->clearArguments(); + + *(item->convertProcess) << "cp"; + *(item->convertProcess) << source.path(); + *(item->convertProcess) << destination.path(); + + logger->log( item->logID, "cp \"" + source.path() + "\" \"" + destination.path() + "\"" ); + + item->convertProcess->setPriority( config->data.general.priority ); + item->convertProcess->start( KProcess::NotifyOnExit, KProcess::AllOutput ); + } + else { + item->moveJob = new KIO::FileCopyJob( source, destination, -1, false, true, false, false ); + connect( item->moveJob, SIGNAL(percent(KIO::Job*,unsigned long)), + this, SLOT(moveProgress(KIO::Job*,unsigned long)) + ); + connect( item->moveJob, SIGNAL(result(KIO::Job*)), + this, SLOT(moveFinished(KIO::Job*)) + ); + } +} + +void Convert::getCorrection( ConvertItem* item ) +{ + logger->log( item->logID, i18n("Getting correction file") ); + item->state = ConvertItem::get_correction; + + // calculate the name of the correction input file + QFile file( OutputDirectory::changeExtension(item->fileListItem->options.filePathName,item->correctionInputExtension) ); + if( !file.exists() ) { + logger->log( item->logID, " " + i18n("Aborting, file does not exist") + " (" + file.name() + ")" ); + executeNextStep( item ); + return; + } + + KURL source( file.name() ); + KURL destination( item->correctionInFile ); + + item->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Getting correction file")+"... 00 %" ); + + if( source.isLocalFile() && destination.isLocalFile() ) { + item->convertProcess->clearArguments(); + + *(item->convertProcess) << "cp"; + *(item->convertProcess) << source.path(); + *(item->convertProcess) << destination.path(); + + logger->log( item->logID, "cp \"" + source.path() + "\" \"" + destination.path() + "\"" ); + + item->convertProcess->setPriority( config->data.general.priority ); + item->convertProcess->start( KProcess::NotifyOnExit, KProcess::AllOutput ); + } + else { + item->moveJob = new KIO::FileCopyJob( source, destination, -1, false, true, false, false ); + connect( item->moveJob, SIGNAL(percent(KIO::Job*,unsigned long)), + this, SLOT(moveProgress(KIO::Job*,unsigned long)) + ); + connect( item->moveJob, SIGNAL(result(KIO::Job*)), + this, SLOT(moveFinished(KIO::Job*)) + ); + } +} + +void Convert::rip( ConvertItem* item ) +{ + logger->log( item->logID, i18n("Ripping") ); + item->state = ConvertItem::rip; + +/** kaudiocreator + QString wavFile; + QString args = job->device; + if(!args.isEmpty()) + args = QString("?device=%1").arg(args); + args = args+"&fileNameTemplate=Track %{number}"; + if(job->track < 10) + wavFile = QString("audiocd:/Wav/Track 0%1.wav%2").arg(job->track).arg(args); + else + wavFile = QString("audiocd:/Wav/Track %1.wav%2").arg(job->track).arg(args); +*/ + + RipperPlugin* plugin = config->getCurrentRipper(); + + if( plugin == 0 ) { + // NOTE process devices like '/dev/cdrom' - seems to be done + // TODO implement process priority (nice level) + QString src; + if( item->fileListItem->track != 0 ) { + // TODO does it work with cds with less than 10 tracks? + src.sprintf( "audiocd:/Wav/Track %02i.wav?device=" + item->fileListItem->device + "&fileNameTemplate=Track %%{number}", item->fileListItem->track ); + } + else { + // FIXME implement ripping of full cds + src = "audiocd:/Full CD/Full CD.wav?device=" + item->fileListItem->device + "&albumTemplate=Full CD"; + item->tracks = 1; + } + KURL source( src ); + KURL dest( item->tempWavFile->name() ); + + item->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Ripping")+"... 00 %" ); + item->fileListItem->ripping = true; + + item->moveJob = new KIO::FileCopyJob( source, dest, -1, false, true, false, false ); + connect( item->moveJob, SIGNAL(percent(KIO::Job*,unsigned long)), + this, SLOT(moveProgress(KIO::Job*,unsigned long)) + ); + connect( item->moveJob, SIGNAL(result(KIO::Job*)), + this, SLOT(moveFinished(KIO::Job*)) + ); + } + else { + QStringList params; + QString param, paramSplinter; + + + item->convertProcess->clearArguments(); + + param = QString::null; + if( plugin->rip.param ) param.append( " " + plugin->rip.param ); + if( plugin->rip.device ) param.append( " " + plugin->rip.device ); + if( plugin->rip.overwrite ) param.append( " " + plugin->rip.overwrite ); + + if( item->fileListItem->track != 0 ) { + if( plugin->rip.track ) param.append( " " + plugin->rip.track ); + } + else { + if( plugin->rip.full_disc.param ) param.append( " " + plugin->rip.full_disc.param ); + item->tracks = cdManager->getTrackCount( item->fileListItem->device ); + item->track = 0; + } + +// if( plugin->rip.out_file.find("%p") != -1 ) { +// QString t_str = plugin->rip.out_file; +// t_str.replace( "%p", param ); +// param = plugin->rip.bin + " " + t_str; +// } +// else { +// param = plugin->rip.bin + param + " " + plugin->rip.out_file; +// } + + QString t_str = plugin->rip.out_file; + t_str.replace( "%p", param ); + param = config->binaries[plugin->rip.bin] + " " + t_str; + + param.simplifyWhiteSpace(); + + params = QStringList::split( ' ', param ); + + for( QStringList::Iterator it = params.begin(); it != params.end(); ++it ) + { + paramSplinter = *it; + paramSplinter.replace( "%d", item->fileListItem->device ); + paramSplinter.replace( "%t", QString().sprintf("%i",item->fileListItem->track) ); + paramSplinter.replace( "%n", QString().sprintf("%i",cdManager->getTrackCount(item->fileListItem->device)) ); + paramSplinter.replace( "%o", item->tempWavFile->name() ); + *(item->convertProcess) << paramSplinter; + } + + param.replace( "%d", item->fileListItem->device ); + param.replace( "%t", QString().sprintf("%i",item->fileListItem->track) ); + param.replace( "%n", QString().sprintf("%i",cdManager->getTrackCount(item->fileListItem->device)) ); + param.replace( "%o", "\""+item->tempWavFile->name()+"\"" ); + logger->log( item->logID, param ); + + //kdDebug() << " Executing: `" << param << "'" << endl; + + //item->readOutputTimer.start(); + item->lastOutputTimer.start(); + + item->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Ripping")+"... 00 %" ); + item->fileListItem->ripping = true; + + item->convertProcess->setPriority( config->data.general.priority ); + item->convertProcess->start( KProcess::NotifyOnExit, KProcess::AllOutput ); + } +} + +void Convert::decode( ConvertItem* item ) +{ + logger->log( item->logID, i18n("Decoding") ); + item->state = ConvertItem::decode; + + QStringList params; + QString param, paramSplinter; + + item->convertProcess->clearArguments(); + + ConvertPlugin* plugin = config->decoderForFormat( item->fileListItem->mimeType ); + if( plugin == 0 ) { + logger->log( item->logID, " NULL POINTER: Convert::decode( ... ) / plugin" ); + return; + } + + param = ""; + if( !plugin->dec.param.isEmpty() ) param.append( " " + plugin->dec.param ); + if( !plugin->dec.overwrite.isEmpty() ) param.append( " " + plugin->dec.overwrite ); + + QString t_str = plugin->dec.in_out_files; + t_str.replace( "%p", param ); + param = config->binaries[plugin->dec.bin] + " " + t_str; + + param = param.simplifyWhiteSpace(); + + params = QStringList::split( ' ', param ); + + for( QStringList::Iterator it = params.begin(); it != params.end(); ++it ) + { + paramSplinter = *it; + paramSplinter.replace( "%i", item->tempInFile->name() ); + paramSplinter.replace( "%o", item->tempWavFile->name() ); + *(item->convertProcess) << paramSplinter; + } + + param.replace( "%i", "\""+item->tempInFile->name()+"\"" ); + param.replace( "%o", "\""+item->tempWavFile->name()+"\"" ); + //item->log = param; + logger->log( item->logID, param ); + + //kdDebug() << " Executing: `" << param << "'" << endl; + + //item->readOutputTimer.start(); + item->lastOutputTimer.start(); + + item->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Decoding")+"... 00 %" ); + + item->convertProcess->setPriority( config->data.general.priority ); + item->convertProcess->start( KProcess::NotifyOnExit, KProcess::AllOutput ); +} + +void Convert::encode( ConvertItem* item ) +{ + // TODO test quality profiles (never done) + + QString sStrength; + QString sBitrate; + QString sQuality; + QString sMinBitrate; + QString sMaxBitrate; + QString sSamplingRate; + + int t_int; + float t_float; + + logger->log( item->logID, i18n("Encoding") ); + item->state = ConvertItem::encode; + + QStringList params; + QString param, paramSplinter; + + item->convertProcess->clearArguments(); + + // NOTE use mimetype + FormatItem* formatItem = config->getFormatItem( item->fileListItem->options.encodingOptions.sFormat ); + if( formatItem == 0 ) { + //kdDebug() << "NULL POINTER: `" << "Convert::encode( ... ) / formatItem" << "'" << endl; + logger->log( 1000, "NULL POINTER: `Convert::encode( ... ) / formatItem'" ); + return; + } + ConvertPlugin* plugin = formatItem->encoder; + if( plugin == 0 ) { + //kdDebug() << "NULL POINTER: `" << "Convert::encode( ... ) / plugin" << "'" << endl; + logger->log( 1000, "NULL POINTER: `Convert::encode( ... ) / plugin'" ); + return; + } + +// item->binary = plugin->enc.bin; + + param = ""; + if( !plugin->enc.param.isEmpty() ) param.append( " " + plugin->enc.param ); + if( !plugin->enc.overwrite.isEmpty() ) param.append( " " + plugin->enc.overwrite ); + + if( plugin->enc.strength.enabled ) { + param.append( " " + plugin->enc.strength.param ); + int compressionLevel = formatItem->compressionLevel; + + if( plugin->enc.strength.profiles.empty() ) { + if( plugin->enc.strength.step < 1 ) { + if( plugin->enc.strength.range_max >= plugin->enc.strength.range_min ) + sStrength = QString::number( compressionLevel * plugin->enc.strength.step ); + else + sStrength = QString::number( plugin->enc.strength.range_min - compressionLevel * plugin->enc.strength.step ); + } + else { + if( plugin->enc.strength.range_max >= plugin->enc.strength.range_min ) + sStrength = QString::number( int(compressionLevel * plugin->enc.strength.step) ); + else + sStrength = QString::number( int(plugin->enc.strength.range_min - compressionLevel * plugin->enc.strength.step) ); + } + if( plugin->enc.strength.separator != '.' ) sStrength.replace( QChar('.'), plugin->enc.strength.separator ); + } + else { + QStringList::Iterator it = plugin->enc.strength.profiles.at( compressionLevel ); + sStrength = *it; + } + } + + if( item->fileListItem->options.encodingOptions.sQualityMode == i18n("Bitrate") ) { + if( item->fileListItem->options.encodingOptions.sBitrateMode == "cbr" && plugin->enc.lossy.bitrate.cbr.enabled ) { + param.append( " " + plugin->enc.lossy.bitrate.cbr.param ); + sBitrate = QString::number( item->fileListItem->options.encodingOptions.iQuality ); + } + else if( item->fileListItem->options.encodingOptions.sBitrateMode == "abr" && plugin->enc.lossy.bitrate.abr.enabled ) { + param.append( " " + plugin->enc.lossy.bitrate.abr.param ); + sBitrate = QString::number( item->fileListItem->options.encodingOptions.iQuality ); + if( item->fileListItem->options.encodingOptions.bBitrateRange && plugin->enc.lossy.bitrate.abr.bitrate_range.enabled ) { + param.append( " " + plugin->enc.lossy.bitrate.abr.bitrate_range.param_min ); + sMinBitrate = QString::number( item->fileListItem->options.encodingOptions.iMinBitrate ); + param.append( " " + plugin->enc.lossy.bitrate.abr.bitrate_range.param_max ); + sMaxBitrate = QString::number( item->fileListItem->options.encodingOptions.iMaxBitrate ); + } + } + } + else if( item->fileListItem->options.encodingOptions.sQualityMode == i18n("Quality") && plugin->enc.lossy.quality.enabled ) { + param.append( " " + plugin->enc.lossy.quality.param ); + if( plugin->enc.lossy.quality.profiles.empty() ) { + if( plugin->enc.lossy.quality.step < 1 ) { + if( plugin->enc.lossy.quality.range_max >= plugin->enc.lossy.quality.range_min) + t_float = ( (float)item->fileListItem->options.encodingOptions.iQuality * ( plugin->enc.lossy.quality.range_max - plugin->enc.lossy.quality.range_min ) / 100 ) + plugin->enc.lossy.quality.range_min; + else + t_float = ( (100.0f - (float)item->fileListItem->options.encodingOptions.iQuality) * ( plugin->enc.lossy.quality.range_min - plugin->enc.lossy.quality.range_max ) / 100 ) + plugin->enc.lossy.quality.range_max; + //t_float -= t_float%plugin->enc.quality.step; + //sQuality = QString().sprintf( "%.2f", t_float ); + sQuality = QString::number( t_float ); + } + else { + if( plugin->enc.lossy.quality.range_max >= plugin->enc.lossy.quality.range_min) + t_int = ( item->fileListItem->options.encodingOptions.iQuality * (int)( plugin->enc.lossy.quality.range_max - plugin->enc.lossy.quality.range_min ) / 100) + (int)plugin->enc.lossy.quality.range_min; + else + t_int = ( (100 - item->fileListItem->options.encodingOptions.iQuality) * (int)( plugin->enc.lossy.quality.range_min - plugin->enc.lossy.quality.range_max ) / 100) + (int)plugin->enc.lossy.quality.range_max; + //t_int -= t_int%plugin->enc.quality.step; + sQuality = QString::number( t_int ); + } + if( plugin->enc.bin == "oggenc" ) sQuality.replace(QChar('.'),KGlobal::locale()->decimalSymbol()); // HACK make oggenc usable with all langauges + else if( plugin->enc.lossy.quality.separator != '.' ) sQuality.replace(QChar('.'),plugin->enc.lossy.quality.separator); + } + else { + QStringList::Iterator it = plugin->enc.lossy.quality.profiles.at( rint(item->fileListItem->options.encodingOptions.iQuality*plugin->enc.lossy.quality.range_max/100) ); + sQuality = *it; + } + } + else if( item->fileListItem->options.encodingOptions.sQualityMode == i18n("Lossless") && plugin->enc.lossless.enabled ) { + param.append( " " + plugin->enc.lossless.param ); + } + else if( item->fileListItem->options.encodingOptions.sQualityMode == i18n("Hybrid") && plugin->enc.hybrid.enabled ) { + param.append( " " + plugin->enc.hybrid.param ); + sBitrate = QString::number( item->fileListItem->options.encodingOptions.iQuality ); + } + + if( item->fileListItem->options.encodingOptions.samplingRate.bEnabled && plugin->enc.lossy.samplingrate.enabled ) { + param.append( " " + plugin->enc.lossy.samplingrate.param ); + if( plugin->enc.lossy.samplingrate.unit == PluginLoaderBase::Hz ) { + sSamplingRate = QString::number( item->fileListItem->options.encodingOptions.samplingRate.iSamplingRate ); + } + else { + sSamplingRate = QString::number( (float)item->fileListItem->options.encodingOptions.samplingRate.iSamplingRate/1000 ); + } + } + + if( item->fileListItem->options.encodingOptions.channels.bEnabled ) { + if( item->fileListItem->options.encodingOptions.channels.sChannels == i18n("Mono") && plugin->enc.lossy.channels.mono_enabled ) { + param.append( " " + plugin->enc.lossy.channels.mono_param ); + } + else if( item->fileListItem->options.encodingOptions.channels.sChannels == i18n("Stereo") && plugin->enc.lossy.channels.stereo_enabled ) { + param.append( " " + plugin->enc.lossy.channels.stereo_param ); + } + else if( item->fileListItem->options.encodingOptions.channels.sChannels == i18n("Joint-Stereo") && plugin->enc.lossy.channels.joint_stereo_enabled ) { + param.append( " " + plugin->enc.lossy.channels.joint_stereo_param ); + } + else if( item->fileListItem->options.encodingOptions.channels.sChannels == i18n("Forced Joint-Stereo") && plugin->enc.lossy.channels.forced_joint_stereo_enabled ) { + param.append( " " + plugin->enc.lossy.channels.forced_joint_stereo_param ); + } + else if( item->fileListItem->options.encodingOptions.channels.sChannels == i18n("Dual Channels") && plugin->enc.lossy.channels.dual_channels_enabled ) { + param.append( " " + plugin->enc.lossy.channels.dual_channels_param ); + } + } + + if( item->fileListItem->options.encodingOptions.replaygain.bEnabled && plugin->enc.replaygain.enabled && plugin->enc.replaygain.use && formatItem->internalReplayGain ) { + param.append( " " + plugin->enc.replaygain.use ); + } + else if( plugin->enc.replaygain.enabled && plugin->enc.replaygain.avoid ) { + param.append( " " + plugin->enc.replaygain.avoid ); + } + +// if( !tagEngine->canWrite(item->fileListItem->options.encodingOptions.sFormat) && item->fileListItem->tags && plugin->enc.tag.enabled ) { + if( item->fileListItem->tags && plugin->enc.tag.enabled && item->fileListItem->options.encodingOptions.sFormat != "aac" ) { // HACK don't write metadata to aac + if( !plugin->enc.tag.param.isEmpty() ) param.append( " " + plugin->enc.tag.param ); + if( !plugin->enc.tag.artist.isEmpty() && !item->fileListItem->tags->artist.isEmpty() ) param.append( " " + plugin->enc.tag.artist ); + if( !plugin->enc.tag.album.isEmpty() && !item->fileListItem->tags->album.isEmpty() ) param.append( " " + plugin->enc.tag.album ); + if( !plugin->enc.tag.comment.isEmpty() && !item->fileListItem->tags->comment.isEmpty() ) param.append( " " + plugin->enc.tag.comment ); + if( !plugin->enc.tag.disc.isEmpty() && item->fileListItem->tags->disc != 0 ) param.append( " " + plugin->enc.tag.disc ); + if( !plugin->enc.tag.genre.isEmpty() && !item->fileListItem->tags->genre.isEmpty() ) param.append( " " + plugin->enc.tag.genre ); + if( !plugin->enc.tag.track.isEmpty() && item->fileListItem->tags->track != 0 ) param.append( " " + plugin->enc.tag.track ); + if( !plugin->enc.tag.composer.isEmpty() && !item->fileListItem->tags->composer.isEmpty() ) param.append( " " + plugin->enc.tag.composer ); + if( !plugin->enc.tag.title.isEmpty() && !item->fileListItem->tags->title.isEmpty() ) param.append( " " + plugin->enc.tag.title ); + if( !plugin->enc.tag.year.isEmpty() && item->fileListItem->tags->year != 0 ) param.append( " " + plugin->enc.tag.year ); + } + + QString sInOutFiles = item->fileListItem->options.encodingOptions.sInOutFiles; + param = sInOutFiles.replace( "%p", param ); + + // cosmetic surgery + param = param.simplifyWhiteSpace(); + + params = QStringList::split( ' ', param ); + + QString inputFile; + if( item->mode & ConvertItem::decode || item->mode & ConvertItem::rip ) inputFile = item->tempWavFile->name(); + else inputFile = item->tempInFile->name(); + + for( QStringList::Iterator it = params.begin(); it != params.end(); ++it ) + { + paramSplinter = *it; + paramSplinter.replace( "%i", inputFile ); + paramSplinter.replace( "%o", item->tempOutFile->name() ); + paramSplinter.replace( "%c", sStrength ); + paramSplinter.replace( "%b", sBitrate ); + paramSplinter.replace( "%q", sQuality ); + paramSplinter.replace( "%m", sMinBitrate ); + paramSplinter.replace( "%M", sMaxBitrate ); + paramSplinter.replace( "%s", sSamplingRate ); + + if( item->fileListItem->tags ) { + paramSplinter.replace( "%ta", ( item->fileListItem->tags->artist != "" ) ? item->fileListItem->tags->artist : i18n("Unknown") ); + paramSplinter.replace( "%tb", ( item->fileListItem->tags->album != "" ) ? item->fileListItem->tags->album : i18n("Unknown") ); + paramSplinter.replace( "%tc", ( item->fileListItem->tags->comment != "" ) ? item->fileListItem->tags->comment : i18n("Unknown") ); + paramSplinter.replace( "%td", ( QString::number(item->fileListItem->tags->disc) != "" ) ? QString::number(item->fileListItem->tags->disc) : "0" ); + paramSplinter.replace( "%tg", ( item->fileListItem->tags->genre != "" ) ? item->fileListItem->tags->genre : i18n("Unknown") ); + paramSplinter.replace( "%tn", ( QString::number(item->fileListItem->tags->track) != "" ) ? QString::number(item->fileListItem->tags->track) : "0" ); + paramSplinter.replace( "%tp", ( item->fileListItem->tags->composer != "" ) ? item->fileListItem->tags->composer : i18n("Unknown") ); + paramSplinter.replace( "%tt", ( item->fileListItem->tags->title != "" ) ? item->fileListItem->tags->title : i18n("Unknown") ); + paramSplinter.replace( "%ty", ( QString::number(item->fileListItem->tags->year) != "" ) ? QString::number(item->fileListItem->tags->year) : "0" ); + } + + if( paramSplinter != "" && paramSplinter != " " ) *(item->convertProcess) << paramSplinter; // NOTE fixes wavpack encoding + } + + param.replace( "%i", "\""+inputFile+"\"" ); + param.replace( "%o", "\""+item->tempOutFile->name()+"\"" ); + param.replace( "%c", sStrength ); + param.replace( "%b", sBitrate ); + param.replace( "%q", sQuality ); + param.replace( "%m", sMinBitrate ); + param.replace( "%M", sMaxBitrate ); + param.replace( "%s", sSamplingRate ); + + if( item->fileListItem->tags ) { + param.replace( "%ta", "\""+item->fileListItem->tags->artist+"\"" ); + param.replace( "%tb", "\""+item->fileListItem->tags->album+"\"" ); + param.replace( "%tc", "\""+item->fileListItem->tags->comment+"\"" ); + param.replace( "%td", QString::number(item->fileListItem->tags->disc) ); + param.replace( "%tg", "\""+item->fileListItem->tags->genre+"\"" ); + param.replace( "%tn", QString::number(item->fileListItem->tags->track) ); + param.replace( "%tp", "\""+item->fileListItem->tags->composer+"\"" ); + param.replace( "%tt", "\""+item->fileListItem->tags->title+"\"" ); + param.replace( "%ty", QString::number(item->fileListItem->tags->year) ); + } + + logger->log( item->logID, param ); + + //kdDebug() << " Executing: `" << param << "'" << endl; + + //item->readOutputTimer.start(); + item->lastOutputTimer.start(); + + item->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Encoding")+"... 00 %" ); + + item->convertProcess->setPriority( config->data.general.priority ); + item->convertProcess->start( KProcess::NotifyOnExit, KProcess::AllOutput ); +} + +void Convert::replaygain( ConvertItem* item ) +{ + logger->log( item->logID, i18n("Applying Replay Gain") ); + item->state = ConvertItem::replaygain; + + FormatItem* formatItem = config->getFormatItem( item->fileListItem->options.encodingOptions.sFormat ); + if( formatItem == 0 ) { + logger->log( item->logID, " NULL POINTER: Convert::replaygain( ... ) / formatItem" ); + return; + } + ConvertPlugin* plugin = formatItem->encoder; + if( plugin == 0 ) { + logger->log( item->logID, " NULL POINTER: Convert::replaygain( ... ) / plugin" ); + return; + } + + if( plugin->enc.replaygain.enabled && formatItem->internalReplayGain ) { + executeNextStep( item ); + return; + } + + item->replayGain = new ReplayGain( config, logger ); + bool ret = item->replayGain->apply( item->tempOutFile->name(), item->fileListItem->options.encodingOptions.sFormat, item->convertProcess, item->logID ); + + if( !ret ) { + executeNextStep( item ); + return; + } + + //item->readOutputTimer.start(); + item->lastOutputTimer.start(); + + item->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Replay Gain")+"... 00 %" ); +} + +void Convert::writeTags( ConvertItem* item ) +{ + logger->log( item->logID, i18n("Writing tags") ); + item->state = ConvertItem::write_tags; + + if( item->mode & ConvertItem::encode ) { + tagEngine->writeTags( item->tempOutFile->name(), item->fileListItem->tags ); + item->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Writing tags")+"... 00 %" ); + } + + executeNextStep( item ); +} + +void Convert::put( ConvertItem* item ) +{ + logger->log( item->logID, i18n("Moving file") ); + item->state = ConvertItem::put; + + QString src; + if( item->mode & ConvertItem::encode ) src = item->tempOutFile->name(); + else src = item->tempWavFile->name(); + item->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Moving file")+"... 00 %" ); + + item->outputFilePathName = OutputDirectory::makePath( OutputDirectory::uniqueFileName(OutputDirectory::calcPath(item->fileListItem,config)) ).replace("%2f","%252f"); + + KURL source( src ); + KURL destination( item->outputFilePathName ); + + if( source.isLocalFile() && destination.isLocalFile() ) { + item->convertProcess->clearArguments(); + + *(item->convertProcess) << "cp"; + *(item->convertProcess) << source.path(); + *(item->convertProcess) << destination.path(); + + logger->log( item->logID, "cp \"" + source.path() + "\" \"" + destination.path() + "\"" ); + + item->convertProcess->setPriority( config->data.general.priority ); + item->convertProcess->start( KProcess::NotifyOnExit, KProcess::AllOutput ); + } + else { + item->moveJob = new KIO::FileCopyJob( source, destination, -1, false, false, false, false ); + connect( item->moveJob, SIGNAL(percent(KIO::Job*,unsigned long)), + this, SLOT(moveProgress(KIO::Job*,unsigned long)) + ); + connect( item->moveJob, SIGNAL(result(KIO::Job*)), + this, SLOT(moveFinished(KIO::Job*)) + ); + } +} + +void Convert::putCorrection( ConvertItem* item ) +{ + logger->log( item->logID, i18n("Moving correction file") ); + item->state = ConvertItem::put_correction; + + QString src = item->correctionOutFile; + + QString dest = OutputDirectory::makePath( OutputDirectory::calcPath(item->fileListItem,config,item->correctionOutputExtension) ).replace("%2f","%252f"); + + KURL source( src ); +// KURL destination( dest ); + KURL destination; + destination.setPath( dest ); + + item->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Moving correction file")+"... 00 %" ); + + if( source.isLocalFile() && destination.isLocalFile() ) { + item->convertProcess->clearArguments(); + + *(item->convertProcess) << "cp"; + *(item->convertProcess) << source.path(); + *(item->convertProcess) << destination.path(); + + logger->log( item->logID, "cp \"" + source.path() + "\" \"" + destination.path() + "\"" ); + + item->convertProcess->setPriority( config->data.general.priority ); + item->convertProcess->start( KProcess::NotifyOnExit, KProcess::AllOutput ); + } + else { + item->moveJob = new KIO::FileCopyJob( source, destination, -1, false, false, false, false ); + connect( item->moveJob, SIGNAL(percent(KIO::Job*,unsigned long)), + this, SLOT(moveProgress(KIO::Job*,unsigned long)) + ); + connect( item->moveJob, SIGNAL(result(KIO::Job*)), + this, SLOT(moveFinished(KIO::Job*)) + ); + } +} + +void Convert::executeUserScript( ConvertItem* item ) +{ + logger->log( item->logID, i18n("Running user script") ); + item->state = ConvertItem::execute_userscript; + + KURL source( item->fileListItem->options.filePathName ); + KURL destination( item->outputFilePathName ); + + item->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Running user script")+"... 00 %" ); + + item->convertProcess->clearArguments(); + + QString userscript = locate( "data", "soundkonverter/userscript.sh" ); + if( userscript == "" ) executeNextStep( item ); + + *(item->convertProcess) << userscript; + *(item->convertProcess) << source.path(); + *(item->convertProcess) << destination.path(); + + logger->log( item->logID, userscript + " \"" + source.path() + "\" \"" + destination.path() + "\"" ); + + item->convertProcess->setPriority( config->data.general.priority ); + item->convertProcess->start( KProcess::NotifyOnExit, KProcess::AllOutput ); +} + +void Convert::executeNextStep( ConvertItem* item ) +{ + logger->log( item->logID, i18n("Executing next step") ); + + item->percent = 0; + item->lastPercent = 0; // used for ripping a whole cd to one file + + switch( item->state ) + { + case ConvertItem::get: + { + if( item->mode & ConvertItem::get_correction ) getCorrection( item ); + else if( item->mode & ConvertItem::rip ) rip( item ); + else if( item->mode & ConvertItem::decode ) decode( item ); + else if( item->mode & ConvertItem::encode ) encode( item ); + else if( item->mode & ConvertItem::replaygain ) replaygain( item ); + else if( item->mode & ConvertItem::write_tags ) writeTags( item ); + else if( item->mode & ConvertItem::put ) put( item ); + else if( item->mode & ConvertItem::put_correction ) putCorrection( item ); + else if( config->data.general.executeUserScript ) executeUserScript( item ); + else remove( item ); + break; + } + case ConvertItem::get_correction: + { + if( item->mode & ConvertItem::rip ) rip( item ); + else if( item->mode & ConvertItem::decode ) decode( item ); + else if( item->mode & ConvertItem::encode ) encode( item ); + else if( item->mode & ConvertItem::replaygain ) replaygain( item ); + else if( item->mode & ConvertItem::write_tags ) writeTags( item ); + else if( item->mode & ConvertItem::put ) put( item ); + else if( item->mode & ConvertItem::put_correction ) putCorrection( item ); + else if( config->data.general.executeUserScript ) executeUserScript( item ); + else remove( item ); + break; + } + case ConvertItem::rip: + { + if( item->mode & ConvertItem::decode ) decode( item ); + else if( item->mode & ConvertItem::encode ) encode( item ); + else if( item->mode & ConvertItem::replaygain ) replaygain( item ); + else if( item->mode & ConvertItem::write_tags ) writeTags( item ); + else if( item->mode & ConvertItem::put ) put( item ); + else if( item->mode & ConvertItem::put_correction ) putCorrection( item ); + else if( config->data.general.executeUserScript ) executeUserScript( item ); + else remove( item ); + break; + } + case ConvertItem::decode: + { + if( item->mode & ConvertItem::encode ) encode( item ); + else if( item->mode & ConvertItem::replaygain ) replaygain( item ); + else if( item->mode & ConvertItem::write_tags ) writeTags( item ); + else if( item->mode & ConvertItem::put ) put( item ); + else if( item->mode & ConvertItem::put_correction ) putCorrection( item ); + else if( config->data.general.executeUserScript ) executeUserScript( item ); + else remove( item ); + break; + } + case ConvertItem::encode: + { + if( item->mode & ConvertItem::replaygain ) replaygain( item ); + else if( item->mode & ConvertItem::write_tags ) writeTags( item ); + else if( item->mode & ConvertItem::put ) put( item ); + else if( item->mode & ConvertItem::put_correction ) putCorrection( item ); + else if( config->data.general.executeUserScript ) executeUserScript( item ); + else remove( item ); + break; + } + case ConvertItem::replaygain: + { + if( item->mode & ConvertItem::write_tags ) writeTags( item ); + else if( item->mode & ConvertItem::put ) put( item ); + else if( item->mode & ConvertItem::put_correction ) putCorrection( item ); + else if( config->data.general.executeUserScript ) executeUserScript( item ); + else remove( item ); + break; + } + case ConvertItem::write_tags: + { + if( item->mode & ConvertItem::put ) put( item ); + else if( item->mode & ConvertItem::put_correction ) putCorrection( item ); + else if( config->data.general.executeUserScript ) executeUserScript( item ); + else remove( item ); + break; + } + case ConvertItem::put: + { + if( item->mode & ConvertItem::put_correction ) putCorrection( item ); + else if( config->data.general.executeUserScript ) executeUserScript( item ); + else remove( item ); + break; + } + case ConvertItem::put_correction: + { + if( config->data.general.executeUserScript ) executeUserScript( item ); + else remove( item ); + break; + } + case ConvertItem::execute_userscript: + { + remove( item ); + break; + } + default: // case (ConvertItem::Mode)0x0000: + { + if( item->mode & ConvertItem::get ) get( item ); + else if( item->mode & ConvertItem::get_correction ) getCorrection( item ); + else if( item->mode & ConvertItem::rip ) rip( item ); + else if( item->mode & ConvertItem::decode ) decode( item ); + else if( item->mode & ConvertItem::encode ) encode( item ); + else if( item->mode & ConvertItem::replaygain ) replaygain( item ); + else if( item->mode & ConvertItem::write_tags ) writeTags( item ); + else if( item->mode & ConvertItem::put ) put( item ); + else if( item->mode & ConvertItem::put_correction ) putCorrection( item ); + else if( config->data.general.executeUserScript ) executeUserScript( item ); + else remove( item ); + break; + } + } +} + +void Convert::moveProgress( KIO::Job* job, unsigned long percent ) +{ + // search the item list for our item + for( QValueList::Iterator item = items.begin(); item != items.end(); item++ ) { + if( (*item)->moveJob == job ) { + (*item)->percent = percent; + } + } +} + +void Convert::moveFinished( KIO::Job* job ) +{ + // search the item list for our item + for( QValueList::Iterator item = items.begin(); item != items.end(); item++ ) { + if( (*item)->moveJob == job ) { + + (*item)->percent = 0; + if( (*item)->state == ConvertItem::get ) { + if( job->error() != 0 ) { + remove( *item, 1 ); + updateProgressIndicator(); + return; + } + + logger->log( (*item)->logID, " " + i18n("Got file") ); + + // if file is remote or the tag reding failed previously, read the tags now + if( (*item)->fileListItem->tags == 0 ) { + (*item)->fileListItem->tags = tagEngine->readTags( (*item)->tempInFile->name() ); + } + + emit countTime( (*item)->getTime ); + } + else if( (*item)->state == ConvertItem::get_correction ) { + if( job->error() != 0 ) { + emit uncountTime( (*item)->getTime ); + remove( *item, 1 ); + updateProgressIndicator(); + return; + } + + logger->log( (*item)->logID, " " + i18n("Got file") ); + emit countTime( (*item)->getCorrectionTime ); + } + else if( (*item)->state == ConvertItem::rip ) { + if( job->error() != 0 ) { + remove( *item, 1 ); + updateProgressIndicator(); + return; + } + + //logger->log( (*item)->logID, " " + i18n("Ripped track") ); + (*item)->fileListItem->ripping = false; + emit countTime( (*item)->ripTime ); + emit rippingFinished( (*item)->fileListItem->device ); + } + else if( (*item)->state == ConvertItem::put ) { + if( job->error() != 0 ) { + logger->log( (*item)->logID, i18n("Could not write to file: `%1'").arg(OutputDirectory::calcPath((*item)->fileListItem,config)) ); + emit uncountTime( (*item)->getTime ); + emit uncountTime( (*item)->getCorrectionTime ); + emit uncountTime( (*item)->ripTime ); + emit uncountTime( (*item)->decodeTime ); + emit uncountTime( (*item)->encodeTime ); + emit uncountTime( (*item)->replaygainTime ); + remove( *item, 1 ); + updateProgressIndicator(); + return; + } + + logger->log( (*item)->logID, " " + i18n("File moved") ); + } + else if( (*item)->state == ConvertItem::put_correction ) { + if( job->error() != 0 ) { + emit uncountTime( (*item)->getTime ); + emit uncountTime( (*item)->getCorrectionTime ); + emit uncountTime( (*item)->ripTime ); + emit uncountTime( (*item)->decodeTime ); + emit uncountTime( (*item)->encodeTime ); + emit uncountTime( (*item)->replaygainTime ); + remove( *item, 1 ); + updateProgressIndicator(); + return; + } + + logger->log( (*item)->logID, " " + i18n("File moved") ); + } + + executeNextStep( *item ); + return; + } + } +} + +void Convert::processOutput( KProcess* proc, char* data, int ) +{ + int iPercent = 0, iTime = 0, iPos = 0, iNum = 0; + + // search the item list for our item + for( QValueList::Iterator item = items.begin(); item != items.end(); item++ ) + { + if( (*item)->convertProcess == proc ) + { + QString log_data = data; +/* log_data.replace("\n","\\n"); + log_data.replace("\t","\\t"); + log_data.replace("\r","\\r"); + log_data.replace("\b","\\b");*/ + logger->log( (*item)->logID, " " + i18n("Output") + ": " + log_data ); + + //if( (*item)->readOutputTimer.elapsed() < /*config->pauseTime*/ 100 ) return; // TODO use config value + //(*item)->readOutputTimer.start(); + + if( (*item)->state == ConvertItem::decode ) + { + if( (*item)->fileListItem == 0 ) return; + + ConvertPlugin* plugin = config->decoderForFormat( (*item)->fileListItem->mimeType ); + // TODO null pointer check + + QString outputPattern = plugin->dec.output; + //outputPattern.replace( "%i", "%p" ); // for compatibility with old plugins + + if( outputPattern.find("%p") != -1 ) { + outputPattern.replace( "%p", "%i" ); + sscanf( data, outputPattern, &iPercent ); + } + else if( outputPattern.find("%t") != -1 ) { + outputPattern.replace( "%t", "%i" ); + sscanf( data, outputPattern, &iTime ); + iPercent = iTime * 100 / (*item)->fileListItem->time; + } + else if( outputPattern.find("%0") != -1 && outputPattern.find("%1") != -1 ) { + if( outputPattern.find("%0") < outputPattern.find("%1") ) { + outputPattern.replace( "%0", "%i" ); + outputPattern.replace( "%1", "%i" ); + sscanf( data, outputPattern, &iPos, &iNum ); + } + else { + outputPattern.replace( "%0", "%i" ); + outputPattern.replace( "%1", "%i" ); + sscanf( data, outputPattern, &iNum, &iPos ); + } + if( iPos != 0 && iNum != 0 ) iPercent = iPos * 100 / iNum; + } + + if( iPercent > 0 && iPercent <= 100 ) + { + // TODO guess progress, when no signal is received + (*item)->lastOutputTimer.start(); + (*item)->percent = iPercent; + } + } + else if( (*item)->state == ConvertItem::encode ) + { + if( (*item)->fileListItem == 0 ) return; + + // NOTE use mimetype + ConvertPlugin* plugin = config->encoderForFormat( (*item)->fileListItem->options.encodingOptions.sFormat ); + // TODO null pointer check + + QString outputPattern; + if( (*item)->fileListItem->options.encodingOptions.sQualityMode == i18n("Quality") ) outputPattern = plugin->enc.lossy.quality.output; + else if( (*item)->fileListItem->options.encodingOptions.sQualityMode == i18n("Bitrate") && (*item)->fileListItem->options.encodingOptions.sBitrateMode == "cbr" ) outputPattern = plugin->enc.lossy.bitrate.cbr.output; + else if( (*item)->fileListItem->options.encodingOptions.sQualityMode == i18n("Bitrate") && (*item)->fileListItem->options.encodingOptions.sBitrateMode == "abr" ) outputPattern = plugin->enc.lossy.bitrate.abr.output; + + //outputPattern.replace( "%i", "%p" ); // for compatibility with old plugins + + if( outputPattern.find("%p") != -1 ) { + outputPattern.replace( "%p", "%i" ); + sscanf( data, outputPattern, &iPercent ); + } + else if( outputPattern.find("%t") != -1 ) { + outputPattern.replace( "%t", "%i" ); + sscanf( data, outputPattern, &iTime ); + iPercent = iTime * 100 / (*item)->fileListItem->time; + } + else if( outputPattern.find("%0") != -1 && outputPattern.find("%1") != -1 ) { + if( outputPattern.find("%0") < outputPattern.find("%1") ) { + outputPattern.replace( "%0", "%i" ); + outputPattern.replace( "%1", "%i" ); + sscanf( data, outputPattern, &iPos, &iNum ); + } + else { + outputPattern.replace( "%0", "%i" ); + outputPattern.replace( "%1", "%i" ); + sscanf( data, outputPattern, &iNum, &iPos ); + } + if( iPos != 0 && iNum != 0 ) iPercent = iPos * 100 / iNum; + } + + if( iPercent > 0 && iPercent <= 100 ) + { + // TODO guess progress, when no signal is received + (*item)->lastOutputTimer.start(); + (*item)->percent = iPercent; + } + } + else if( (*item)->state == ConvertItem::rip ) // ### soundkonverter 0.4 make the progress dependent on the track length + { + if( (*item)->fileListItem == 0 ) return; + + RipperPlugin* plugin = config->getCurrentRipper(); + // TODO null pointer check + + QString outputPattern; + if( (*item)->fileListItem->track != 0 ) outputPattern = plugin->rip.output; + else outputPattern = plugin->rip.full_disc.output; + //outputPattern.replace( "%i", "%p" ); // for compatibility with old plugins + + if( outputPattern.find("%p") != -1 || outputPattern.find("%a") != -1 ) { + outputPattern.replace( "%p", "%i" ); + outputPattern.replace( "%a", "%i" ); + sscanf( data, outputPattern, &iPercent ); + } + else if( outputPattern.find("%t") != -1 ) { + outputPattern.replace( "%t", "%i" ); + sscanf( data, outputPattern, &iTime ); + iPercent = iTime * 100 / (*item)->fileListItem->time; + } + else if( outputPattern.find("%0") != -1 && outputPattern.find("%1") != -1 ) { + if( outputPattern.find("%0") < outputPattern.find("%1") ) { + outputPattern.replace( "%0", "%i" ); + outputPattern.replace( "%1", "%i" ); + sscanf( data, outputPattern, &iPos, &iNum ); + } + else { + outputPattern.replace( "%0", "%i" ); + outputPattern.replace( "%1", "%i" ); + sscanf( data, outputPattern, &iNum, &iPos ); + } + if( iPos != 0 && iNum != 0 ) iPercent = iPos * 100 / iNum; + } + + if( iPercent > 0 && iPercent <= 100 ) + { + // TODO guess progress, when no signal is received + (*item)->lastOutputTimer.start(); + if( (*item)->fileListItem->track == 0 && plugin->rip.full_disc.output.find("%a") != -1 ) { + if( iPercent < (*item)->lastPercent ) (*item)->track++; + (*item)->lastPercent = iPercent; + (*item)->percent = (*item)->track * 100 / (*item)->tracks + iPercent / (*item)->tracks; + } + else { + (*item)->percent = iPercent; + } + } + } + return; + } + } +} + +void Convert::processExit( KProcess* proc ) +{ + // search the item list for our item + for( QValueList::Iterator item = items.begin(); item != items.end(); item++ ) { +// if( (*item)->convertProcess == proc && (*item)->fileListItem != 0 ) { + if( (*item)->convertProcess == proc ) { + + (*item)->percent = 0; + if( (*item)->state == ConvertItem::rip ) { + if( proc->signalled() ) { // FIXME does only check, whether the process has been killed + remove( *item, 1 ); + updateProgressIndicator(); + return; + } + else if( !proc->normalExit() ) { + remove( *item, -1 ); + updateProgressIndicator(); + return; + } + else { + (*item)->fileListItem->ripping = false; + emit countTime( (*item)->ripTime ); + emit rippingFinished( (*item)->fileListItem->device ); + } + } + if( (*item)->state == ConvertItem::get ) { + if( proc->signalled() ) { + remove( *item, 1 ); + updateProgressIndicator(); + return; + } + else if( !proc->normalExit() ) { + remove( *item, -1 ); + updateProgressIndicator(); + return; + } + else { + logger->log( (*item)->logID, " " + i18n("Got file") ); + + // if file is remote or the tag reding failed previously, read the tags now + if( (*item)->fileListItem->tags == 0 ) { + (*item)->fileListItem->tags = tagEngine->readTags( (*item)->tempInFile->name() ); + } + + emit countTime( (*item)->getTime ); + } + } + if( (*item)->state == ConvertItem::get_correction ) { + if( proc->signalled() ) { + emit uncountTime( (*item)->getTime ); + remove( *item, 1 ); + updateProgressIndicator(); + return; + } + else if( !proc->normalExit() ) { + emit uncountTime( (*item)->getTime ); + remove( *item, -1 ); + updateProgressIndicator(); + return; + } + else { + logger->log( (*item)->logID, " " + i18n("Got file") ); + emit countTime( (*item)->getCorrectionTime ); + } + } + if( (*item)->state == ConvertItem::decode ) { + if( proc->signalled() ) { + emit uncountTime( (*item)->getTime ); + emit uncountTime( (*item)->getCorrectionTime ); + remove( *item, 1 ); + updateProgressIndicator(); + return; + } + else if( !proc->normalExit() ) { + emit uncountTime( (*item)->getTime ); + emit uncountTime( (*item)->getCorrectionTime ); + remove( *item, -1 ); + updateProgressIndicator(); + return; + } + else { + emit countTime( (*item)->decodeTime ); + } + } + if( (*item)->state == ConvertItem::encode ) { + if( proc->signalled() ) { + emit uncountTime( (*item)->getTime ); + emit uncountTime( (*item)->getCorrectionTime ); + emit uncountTime( (*item)->ripTime ); + emit uncountTime( (*item)->decodeTime ); + remove( *item, 1 ); + updateProgressIndicator(); + return; + } + else if( !proc->normalExit() ) { + emit uncountTime( (*item)->getTime ); + emit uncountTime( (*item)->getCorrectionTime ); + emit uncountTime( (*item)->ripTime ); + emit uncountTime( (*item)->decodeTime ); + remove( *item, -1 ); + updateProgressIndicator(); + return; + } + else { +/* if( (*item)->binary == "faac" ) { + emit uncountTime( (*item)->getTime ); + emit uncountTime( (*item)->getCorrectionTime ); + emit uncountTime( (*item)->ripTime ); + emit uncountTime( (*item)->decodeTime ); + remove( *item, 1 ); + updateProgressIndicator(); + return; + }*/ + emit countTime( (*item)->encodeTime ); + } + } + if( (*item)->state == ConvertItem::put ) { + if( proc->signalled() ) { + logger->log( (*item)->logID, i18n("Could not write to file: `%1'").arg(OutputDirectory::calcPath((*item)->fileListItem,config)) ); + emit uncountTime( (*item)->getTime ); + emit uncountTime( (*item)->getCorrectionTime ); + emit uncountTime( (*item)->ripTime ); + emit uncountTime( (*item)->decodeTime ); + emit uncountTime( (*item)->encodeTime ); + emit uncountTime( (*item)->replaygainTime ); + remove( *item, 1 ); + updateProgressIndicator(); + return; + } + if( !proc->normalExit() ) { + logger->log( (*item)->logID, i18n("Could not write to file: `%1'").arg(OutputDirectory::calcPath((*item)->fileListItem,config)) ); + emit uncountTime( (*item)->getTime ); + emit uncountTime( (*item)->getCorrectionTime ); + emit uncountTime( (*item)->ripTime ); + emit uncountTime( (*item)->decodeTime ); + emit uncountTime( (*item)->encodeTime ); + emit uncountTime( (*item)->replaygainTime ); + remove( *item, -1 ); + updateProgressIndicator(); + return; + } + else { + logger->log( (*item)->logID, " " + i18n("File moved") ); + } + } + if( (*item)->state == ConvertItem::put_correction ) { + if( proc->signalled() ) { + emit uncountTime( (*item)->getTime ); + emit uncountTime( (*item)->getCorrectionTime ); + emit uncountTime( (*item)->ripTime ); + emit uncountTime( (*item)->decodeTime ); + emit uncountTime( (*item)->encodeTime ); + emit uncountTime( (*item)->replaygainTime ); + remove( *item, 1 ); + updateProgressIndicator(); + return; + } + if( !proc->normalExit() ) { + emit uncountTime( (*item)->getTime ); + emit uncountTime( (*item)->getCorrectionTime ); + emit uncountTime( (*item)->ripTime ); + emit uncountTime( (*item)->decodeTime ); + emit uncountTime( (*item)->encodeTime ); + emit uncountTime( (*item)->replaygainTime ); + remove( *item, -1 ); + updateProgressIndicator(); + return; + } + else { + logger->log( (*item)->logID, " " + i18n("File moved") ); + } + } + if( (*item)->state == ConvertItem::replaygain ) { + if( proc->signalled() ) { + emit uncountTime( (*item)->getTime ); + emit uncountTime( (*item)->getCorrectionTime ); + emit uncountTime( (*item)->ripTime ); + emit uncountTime( (*item)->decodeTime ); + emit uncountTime( (*item)->encodeTime ); + remove( *item, 1 ); + updateProgressIndicator(); + return; + } + else if( !proc->normalExit() ) { + emit uncountTime( (*item)->getTime ); + emit uncountTime( (*item)->getCorrectionTime ); + emit uncountTime( (*item)->ripTime ); + emit uncountTime( (*item)->decodeTime ); + emit uncountTime( (*item)->encodeTime ); + remove( *item, -1 ); + updateProgressIndicator(); + return; + } + else { + emit countTime( (*item)->replaygainTime ); + } + } + // TODO did we get errors? (complete) + executeNextStep( *item ); + return; + } + } +} + +void Convert::add( FileListItem* item ) +{ + logger->log( 1000, i18n("Adding new item to conversion list: `%1'").arg(item->options.filePathName) ); + + // append the item to the item list and store the iterator + QValueList::Iterator newItem = items.append( new ConvertItem( item ) ); + + // register at the logger + (*newItem)->logID = logger->registerProcess( item->options.filePathName ); + logger->log( 1000, " " + i18n("Got log ID: %1").arg((*newItem)->logID) ); + + logger->log( (*newItem)->logID, "Mime Type: " + (*newItem)->fileListItem->mimeType ); + if( (*newItem)->fileListItem->tags ) logger->log( (*newItem)->logID, i18n("Tags successfully read") ); + else logger->log( (*newItem)->logID, i18n("Reading tags failed") ); + + // set some variables to default values + (*newItem)->mode = (ConvertItem::Mode)0x0000; + (*newItem)->state = (ConvertItem::Mode)0x0000; + (*newItem)->convertProcess = 0; + (*newItem)->moveJob = 0; + (*newItem)->replayGain = 0; + + /* seems to be unnecessary + (*newItem)->correctionInFile = QString::null(); + (*newItem)->correctionOutFile = QString::null(); + (*newItem)->correctionInputExtension = QString::null(); + (*newItem)->correctionOutputExtension = QString::null();*/ + + // connect convertProcess of our new item with the slots of Convert + (*newItem)->convertProcess = new KProcess(); + connect( (*newItem)->convertProcess, SIGNAL(receivedStdout(KProcess*,char*,int)), + this, SLOT(processOutput(KProcess*,char*,int)) + ); + connect( (*newItem)->convertProcess, SIGNAL(receivedStderr(KProcess*,char*,int)), + this, SLOT(processOutput(KProcess*,char*,int)) + ); + connect( (*newItem)->convertProcess, SIGNAL(processExited(KProcess*)), + this, SLOT(processExit(KProcess*)) + ); + + // NOTE the tempInFile is also created if the file is a audio cd track + + // set up the names of our temp files + (*newItem)->tempInFile = new KTempFile( QString::null, "." + item->fileFormat ); + (*newItem)->tempInFile->setAutoDelete( true ); + (*newItem)->tempInFile->close(); + + (*newItem)->tempWavFile = new KTempFile( QString::null, ".wav" ); + (*newItem)->tempWavFile->setAutoDelete( true ); + (*newItem)->tempWavFile->close(); + + (*newItem)->tempOutFile = new KTempFile( QString::null, "." + item->options.encodingOptions.sFormat ); + (*newItem)->tempOutFile->setAutoDelete( true ); + (*newItem)->tempOutFile->close(); + + if( item->track >= 0 ) // it's an audio cd track + { + (*newItem)->mode = ConvertItem::Mode( ConvertItem::rip ); + } + else // it's a file + { + (*newItem)->mode = ConvertItem::Mode( ConvertItem::get ); + if( item->fileFormat != "wav" ) + { + (*newItem)->mode = ConvertItem::Mode( (*newItem)->mode | ConvertItem::decode ); + } + } + + if( item->options.encodingOptions.sFormat != "wav" ) + { + (*newItem)->mode = ConvertItem::Mode( (*newItem)->mode | ConvertItem::encode ); + } + if( item->options.encodingOptions.replaygain.bEnabled ) + { + (*newItem)->mode = ConvertItem::Mode( (*newItem)->mode | ConvertItem::replaygain ); + } + + QString extension; + + extension = config->getCorrectionExtension( item->mimeType ); + if( !extension.isEmpty() ) { + (*newItem)->correctionInputExtension = extension; + (*newItem)->correctionInFile = OutputDirectory::changeExtension( (*newItem)->tempInFile->name(), extension ); + (*newItem)->mode = ConvertItem::Mode( (*newItem)->mode | ConvertItem::get_correction ); + logger->log( (*newItem)->logID, " correctionInFile: `" + (*newItem)->correctionInFile + "'" ); + } + + extension = config->getCorrectionExtension( item->options.encodingOptions.sFormat ); + if( !extension.isEmpty() && item->options.encodingOptions.sQualityMode == i18n("Hybrid") ) { + (*newItem)->correctionOutputExtension = extension; + (*newItem)->correctionOutFile = OutputDirectory::changeExtension( (*newItem)->tempOutFile->name(), extension ); + (*newItem)->mode = ConvertItem::Mode( (*newItem)->mode | ConvertItem::put_correction ); + logger->log( (*newItem)->logID, " correctionOutFile: `" + (*newItem)->correctionOutFile + "'" ); + } + + (*newItem)->mode = ConvertItem::Mode( (*newItem)->mode | ConvertItem::write_tags | ConvertItem::put ); + + // TODO use the values from the format info files !!! + + if( (*newItem)->mode & ConvertItem::get ) { + if( !item->local ) { + (*newItem)->getTime = 0.8; // TODO use the file size from the format info files + } + } + if( (*newItem)->mode & ConvertItem::get_correction ) { + if( !item->local ) { + (*newItem)->getCorrectionTime = 2.0; // TODO use the file size from the format info files + } + } + if( (*newItem)->mode & ConvertItem::rip ) { + (*newItem)->ripTime = 1.0; + } + if( (*newItem)->mode & ConvertItem::decode ) { + (*newItem)->decodeTime = 0.4; + } + if( (*newItem)->mode & ConvertItem::encode ) { + (*newItem)->encodeTime = 1.0; + } + if( (*newItem)->mode & ConvertItem::replaygain ) { + (*newItem)->replaygainTime = 0.2; + } + + float sum = ( (*newItem)->getTime + (*newItem)->getCorrectionTime + (*newItem)->ripTime + (*newItem)->decodeTime + (*newItem)->encodeTime + (*newItem)->replaygainTime ) / item->time; + + (*newItem)->getTime /= sum; + (*newItem)->getCorrectionTime /= sum; + (*newItem)->ripTime /= sum; + (*newItem)->decodeTime /= sum; + (*newItem)->encodeTime /= sum; + (*newItem)->replaygainTime /= sum; + + // visual feedback + item->converting = true; + + if( !tUpdateProgressIndicator->isActive() ) { + tUpdateProgressIndicator->start( config->data.general.updateDelay ); + } + + // and start + executeNextStep( *newItem ); +} + +void Convert::stop( FileListItem* item ) +{ + // search the item list for our item to stop + for( QValueList::Iterator stopItem = items.begin(); stopItem != items.end(); stopItem++ ) { + // is fileListItem pointing at the same address, as item + if( (*stopItem)->fileListItem == item ) { + + if( (*stopItem)->convertProcess->isRunning() ) { + bool ret = (*stopItem)->convertProcess->kill( SIGKILL ); + //kdDebug() << "Killing process... (" << ret << ")" << endl; + if( ret ) { + logger->log( (*stopItem)->logID, i18n("Killing process ...") ); + } + else { + logger->log( (*stopItem)->logID, i18n("Killing process failed. Stopping after files are completed ...") ); + } + } + else if( (*stopItem)->moveJob != 0 ) { + //kdDebug() << "Killing file copy..." << endl; + // FIXME crashes sometimes - should be fixed by SIGKILL + // FIXME crash if file_copy was stealthed + logger->log( (*stopItem)->logID, i18n("Killing process ...") ); + (*stopItem)->moveJob->kill( false ); + } + + return; + } + } +} + +void Convert::remove( ConvertItem* item, int state ) +{ + // TODO "remove" (re-add) the times to the progress indicator + //emit uncountTime( item->getTime + item->getCorrectionTime + item->ripTime + + // item->decodeTime + item->encodeTime + item->replaygainTime ); + + logger->log( item->logID, i18n("Removing file from conversion list. Exit code %1").arg(state) ); + + if( item->fileListItem->notify != "" ) { + QString command = item->fileListItem->notify; + command.replace( "%u", item->fileListItem->url ); + command.replace( "%i", item->fileListItem->options.filePathName.replace(" ","%20") ); + command.replace( "%o", item->outputFilePathName.replace(" ","%20") ); + logger->log( item->logID, " "+i18n("Executing command: \"%1\"").arg(command) ); + notify.clearArguments(); + QString paramSplinter; + // FIXME split correct (strings with spaces are splited by mistake) + // FIXME only one command can be executed at once!? + QStringList params = QStringList::split( ' ', item->fileListItem->notify ); + for( QStringList::Iterator it = params.begin(); it != params.end(); ++it ) + { + paramSplinter = *it; + paramSplinter.replace( "%u", item->fileListItem->url ); + paramSplinter.replace( "%i", item->fileListItem->options.filePathName ); + paramSplinter.replace( "%o", item->outputFilePathName ); + notify << paramSplinter; + } + notify.start( KProcess::DontCare ); + } + + item->fileListItem->converting = false; + emit finished( item->fileListItem, state ); // send signal to FileList + emit finishedProcess( item->logID, state ); // send signal to Logger + + item->fileListItem = 0; + if( item->convertProcess != 0 ) delete item->convertProcess; + item->convertProcess = 0; + //if( item->moveJob != 0 ) delete item->moveJob; // NOTE makes soundkonverter crash + //item->moveJob = 0; + if( item->replayGain != 0 ) delete item->replayGain; + item->replayGain = 0; + + if( item->tempInFile != 0 ) delete item->tempInFile; + item->tempInFile = 0; + if( item->tempWavFile != 0 ) delete item->tempWavFile; + item->tempWavFile = 0; + if( item->tempOutFile != 0 ) delete item->tempOutFile; + item->tempOutFile = 0; + QFile file; + file.setName( item->correctionInFile ); + if( file.exists() ) file.remove(); + file.setName( item->correctionOutFile ); + if( file.exists() ) file.remove(); + + for( QValueList::Iterator it = items.begin(); it != items.end(); it++ ) { + if( (*it) == item ) { + items.remove( it ); + break; + } + } + + delete item; + item = 0; + + if( items.count() == 0 ) { + tUpdateProgressIndicator->stop(); + } +} + +void Convert::updateProgressIndicator() +{ + float time = 0; + + for( QValueList::Iterator it = items.begin(); it != items.end(); it++ ) { + if( (*it)->state == ConvertItem::get ) { + time += (*it)->getTime * (*it)->percent / 100; + (*it)->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Getting file")+"... "+QString().sprintf("%02i %%",(*it)->percent) ); + } + else if( (*it)->state == ConvertItem::get_correction ) { + time += (*it)->getCorrectionTime * (*it)->percent / 100; + (*it)->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Getting correction file")+"... "+QString().sprintf("%02i %%",(*it)->percent) ); + } + else if( (*it)->state == ConvertItem::rip ) { + RipperPlugin* plugin = config->getCurrentRipper(); + if( plugin != 0 && plugin->rip.output.isEmpty() ) { + (*it)->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Ripping")+"... "+i18n("State")+": "+i18n("Unknown") ); + } + else { + time += (*it)->ripTime * (*it)->percent / 100; + (*it)->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Ripping")+"... "+QString().sprintf("%02i %%",(*it)->percent) ); + } + } + else if( (*it)->state == ConvertItem::decode ) { + ConvertPlugin* plugin = config->decoderForFormat( (*it)->fileListItem->mimeType ); + if( plugin == 0 || plugin->dec.output.isEmpty() ) { + (*it)->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Decoding")+"... "+i18n("State")+": "+i18n("Unknown") ); + } + else { + time += (*it)->decodeTime * (*it)->percent / 100; + (*it)->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Decoding")+"... "+QString().sprintf("%02i %%",(*it)->percent) ); + } + } + else if( (*it)->state == ConvertItem::encode ) { + ConvertPlugin* plugin = config->encoderForFormat( (*it)->fileListItem->options.encodingOptions.sFormat ); + QString outputPattern; + if( plugin != 0 && (*it)->fileListItem->options.encodingOptions.sQualityMode == i18n("Quality") ) outputPattern = plugin->enc.lossy.quality.output; + else if( plugin != 0 && (*it)->fileListItem->options.encodingOptions.sQualityMode == i18n("Bitrate") && (*it)->fileListItem->options.encodingOptions.sBitrateMode == "cbr" ) outputPattern = plugin->enc.lossy.bitrate.cbr.output; + else if( plugin != 0 && (*it)->fileListItem->options.encodingOptions.sQualityMode == i18n("Bitrate") && (*it)->fileListItem->options.encodingOptions.sBitrateMode == "abr" ) outputPattern = plugin->enc.lossy.bitrate.abr.output; + if( outputPattern.isEmpty() ) { + (*it)->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Encoding")+"... "+i18n("State")+": "+i18n("Unknown") ); + } + else { + time += (*it)->encodeTime * (*it)->percent / 100; + (*it)->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Encoding")+"... "+QString().sprintf("%02i %%",(*it)->percent) ); + } + } + else if( (*it)->state == ConvertItem::replaygain ) { + time += (*it)->replaygainTime * (*it)->percent / 100; + (*it)->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Replay Gain")+"... "+QString().sprintf("%02i %%",(*it)->percent) ); + } + else if( (*it)->state == ConvertItem::put ) { + (*it)->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Moving file")+"... "+QString().sprintf("%02i %%",(*it)->percent) ); + } + else if( (*it)->state == ConvertItem::put_correction ) { + time += (*it)->getCorrectionTime * (*it)->percent / 100; + (*it)->fileListItem->setText( fileList->columnByName(i18n("State")), i18n("Moving correction file")+"... "+QString().sprintf("%02i %%",(*it)->percent) ); + } + } + emit update( time ); +} + +// void Convert::priorityChanged( int priority ) +// { // FIXME setting a higher priority does not work +// KProcess pChangePriority; +// +// for( QValueList::Iterator it = items.begin(); it != items.end(); it++ ) { +// if( (*it)->convertProcess->isRunning() ) { +// //(*it)->convertProcess->setPriority( priority ); +// pChangePriority.clearArguments(); +// pChangePriority << "renice"; +// QString prio; +// prio.sprintf( "%i", priority ); +// pChangePriority << prio; +// QString pid; +// pid.sprintf( "%i", (*it)->convertProcess->pid() ); +// pChangePriority << pid; +// //QString cmd; +// //cmd.sprintf( "renice %i %i", ); +// pChangePriority.start( KProcess::Block ); +// } +// } +// } + + diff --git a/src/convert.h b/src/convert.h new file mode 100755 index 0000000..d69fec4 --- /dev/null +++ b/src/convert.h @@ -0,0 +1,281 @@ + + +#ifndef CONVERT_H +#define CONVERT_H + +#include + +#include +#include + +#include + +class Config; +class TagEngine; +class CDManager; +class FileList; +class FileListItem; +class ReplayGain; +class Logger; +class KTempFile; +//class KProcess; + +/** + * @short The items for the conversion (for every active file) + * @author Daniel Faust + * @version 0.3 + */ +class ConvertItem +{ +public: + /** + * A list of flags for knowing what to do + */ + enum Mode { + get = 0x0001, // Copy the file to tmp + get_correction = 0x0002, // Copy the correction file to tmp + rip = 0x0004, // Rip the file + decode = 0x0008, // Decode the file + encode = 0x0010, // Encode the file + replaygain = 0x0020, // Apply replaygain + write_tags = 0x0040, // Write the tags to the file + put = 0x0080, // Move the file to the output directory + put_correction = 0x0100, // Move the correction file to the output directory + execute_userscript= 0x0200 // Run the user script + }; + + /** + * Default Constructor + */ + ConvertItem(); + + /** + * Constructor + * @p item A pointer to the file list item + */ + ConvertItem( FileListItem* item ); + + /** + * Destructor + */ + virtual ~ConvertItem(); + + /** a reference to the file list item */ + FileListItem* fileListItem; + + /** for adding replay gain */ + ReplayGain* replayGain; + + /** if we need to encode, decode, etc. here we have our processes */ + KProcess* convertProcess; + /** for moving the file to the temporary or output directory */ + KIO::Job* moveJob; + + KTempFile* tempInFile; + KTempFile* tempWavFile; + KTempFile* tempOutFile; + + QString correctionInFile; + QString correctionOutFile; + QString correctionInputExtension; + QString correctionOutputExtension; + + //QTime readOutputTimer; + QTime lastOutputTimer; + + /** what shall we do with the file? */ + Mode mode; + /** and what are we doing with the file? */ + Mode state; + + /** the id with that the item is registered at the logger */ + int logID; + /** the binary for special treatment */ +// QString binary; + + /** the path and the name of the output file (needed for executing a command after conversion) */ + QString outputFilePathName; + + /** if it is an audio cd and it should be ripped to one file: the number of tracks on the cd */ + int tracks; + /** the current track */ + int track; + int lastPercent; + + /** the time from the file list item splitted up */ + float getTime; + float getCorrectionTime; + float ripTime; + float decodeTime; + float encodeTime; + float replaygainTime; + /** the current conversion progress */ + int percent; +}; + + +/** + * @short The conversion engine + * @author Daniel Faust + * @version 0.3 + */ +class Convert : public QObject +{ + Q_OBJECT +public: + /** + * Constructor + */ + Convert( Config*, TagEngine*, CDManager*, FileList*, Logger* ); + + /** + * Destructor + */ + virtual ~Convert(); + + void cleanUp(); + +private: + /** + * Copy the file with the file list item @p item to a temporary directory and download or rip, when necessary + */ + void get( ConvertItem* item ); + + /** + * Copy the correction file with the file list item @p item to a temporary directory and download or rip, when necessary + */ + void getCorrection( ConvertItem* item ); + + /** + * Rip the file with the convert item @p item from the CD + */ + void rip( ConvertItem* item ); + + /** + * Decode the file with the convert item @p item + */ + void decode( ConvertItem* item ); + + /** + * Encode the file with the convert item @p item + */ + void encode( ConvertItem* item ); + + /** + * Calculate replaygain tags of the file with the convert item @p item + */ + void replaygain( ConvertItem* item ); + + /** + * Write the tags of the file with the convert item @p item + */ + void writeTags( ConvertItem* item ); + + /** + * Copy the file with the convert item @p item to the output directory + */ + void put( ConvertItem* item ); + + /** + * Copy the correction file with the convert item @p item to the output directory + */ + void putCorrection( ConvertItem* item ); + + /** + * Run the userscript for the convert item @p item + */ + void executeUserScript( ConvertItem* item ); + + /** + * Decide, what to do next with out item @p item + */ + void executeNextStep( ConvertItem* item ); + + /** + * Remove item @p item and emit the state @p state + */ + void remove( ConvertItem* item, int state = 0 ); + + /** holds all active files */ + QValueList items; + + Config* config; + TagEngine* tagEngine; + CDManager* cdManager; + FileList* fileList; + Logger* logger; + QTimer* tUpdateProgressIndicator; + KProcess notify; + +private slots: + /** + * The file is being moved + * @p job The pinter to the job + */ + void moveProgress( KIO::Job* job, unsigned long percent ); + + /** + * The file has been moved + * @p job The pinter to the job + */ + void moveFinished( KIO::Job* job ); + + /** + * Get the process' output + * @p proc The pinter to the progess + * @p data The output data + * @p length The length of the data + */ + void processOutput( KProcess *proc, char *data, int length ); + + /** + * The process has exited + * @p proc The pinter to the progess + */ + void processExit( KProcess *proc ); + + /** + * Updates the progress indicator + */ + void updateProgressIndicator(); + +public slots: + /** + * Add a new @p item to the item list and start + */ + void add( FileListItem* item ); + + /** + * Stop the item with the file list item @p item in the item list and remove it + */ + void stop( FileListItem* item ); + + /** + * Change the process priorities + */ +// void priorityChanged( int ); + +signals: + /** + * A job was completed + * The job with the file list item @p item was completed + * And report the finish @p state ( 0 = ok, -1 = error, 1 = aborted ) + */ + void finished( FileListItem* item, int state ); + + /** + * Send the logger a signal + */ + void finishedProcess( int id, int state ); + + /** + * The next track from @p device can be ripped while the track is being encoded + */ + void rippingFinished( const QString& device ); + + void countTime( float ); + void uncountTime( float ); + void update( float ); +}; + +#endif // CONVERT_H diff --git a/src/cuesheeteditor.cpp b/src/cuesheeteditor.cpp new file mode 100755 index 0000000..206611b --- /dev/null +++ b/src/cuesheeteditor.cpp @@ -0,0 +1,325 @@ + +#include "cuesheeteditor.h" + +#include +#include + +#include +#include +#include +#include +//#include + +/*#include // KPart Factory +#include // LibLoader, contains factories +#include // Katepart document +#include // Katepart view +*/ + +// ### soundkonverter 0.4: import/export flac cuesheet + +CuesheetEditor::CuesheetEditor( QWidget *parent, const char *name, bool modal, WFlags f ) + : KDialog( parent, name, modal, f ) +{ + // TODO can the cuesheet editor be extendet by more tags (composer), etc. + + // create an icon loader object for loading icons + KIconLoader* iconLoader = new KIconLoader(); + + setCaption( i18n("Cuesheet Editor") ); + resize( 600, 400 ); + setIcon( iconLoader->loadIcon("kwrite",KIcon::Small) ); + + QGridLayout *grid = new QGridLayout( this, 4, 1, 11, 6 ); + + tTextEdit = new KTextEdit( this, "tTextEdit" ); + tTextEdit->setFocus(); + grid->addWidget( tTextEdit, 0, 0 ); + +/* + // Get KPart factory for the katepart library. + // This returns 0, if the library can not be found + KParts::Factory* factory = (KParts::Factory *) + KLibLoader::self()->factory ("libkatepart"); + + if (factory) + { + // The library was found, so create the Kate::Document + KTextEditor::Document *doc = (KTextEditor::Document *) + factory->createPart( 0, "", this, "", "KTextEditor::Document" ); + + // The document only represents the document, to view + // the document's content + // we have to create a view for the document. + Kate::View *view = (Kate::View *) doc->createView( this, 0L ); + + // all went well, so return the view + //return view; + grid->addWidget( view, 0, 0 ); + } + else + { + // The library was not found + //return 0L; + } +*/ + + QHBoxLayout *buttonBox = new QHBoxLayout(); + grid->addLayout( buttonBox, 3, 0 ); + + pHelp = new KPushButton( iconLoader->loadIcon("help",KIcon::Small), "", this, "pHelp" ); + buttonBox->addWidget( pHelp ); + connect( pHelp, SIGNAL(clicked()), + this, SLOT(help()) + ); + + pGenerate = new KPushButton( iconLoader->loadIcon("filenew",KIcon::Small), i18n("Generate"), this, "pGenerate" ); + buttonBox->addWidget( pGenerate ); + connect( pGenerate, SIGNAL(clicked()), + this, SLOT(generate()) + ); + + pConvert = new KPushButton( iconLoader->loadIcon("run",KIcon::Small), i18n("Format"), this, "pConvert" ); + buttonBox->addWidget( pConvert ); + connect( pConvert, SIGNAL(clicked()), + this, SLOT(convert()) + ); + + pShift = new KPushButton( iconLoader->loadIcon("reload",KIcon::Small), i18n("Shift Title/Performer"), this, "pShift" ); + buttonBox->addWidget( pShift ); + connect( pShift, SIGNAL(clicked()), + this, SLOT(shift()) + ); + + buttonBox->addStretch(); + + pOk = new KPushButton(iconLoader->loadIcon("exit",KIcon::Small), i18n("Close"), this, "pOk" ); + pOk->setFocus(); + buttonBox->addWidget( pOk ); + connect( pOk, SIGNAL(clicked()), + this, SLOT(accept()) + ); + + // delete the icon loader object + delete iconLoader; +} + +CuesheetEditor::~CuesheetEditor() +{} + +void CuesheetEditor::help() +{ + KMessageBox::information( this, + i18n("

With this small tool you can process cue files as they are used for burning music mixes and for organizing them in media players like amaroK.

You can generate a new file by pasting text into the input area. It must be formated the following way:

Title - Artist [time]
Title - Artist [3:25]
Title - Artist [2:37]
...
A tip: Use kwrite and regular expressions to format it this way.

"), + i18n("Cuesheet Editor - Help") ); +} + +void CuesheetEditor::generate() +{ + QString text = tTextEdit->text(); + QString newText; + QStringList titleList, performerList; + QValueList timeList; + QString time; + int min, sec; + int index; + + while( index != -1 ) + { + index = text.find( " - " ); + if( index == -1 ) + break; + titleList.append( text.left(index) ); + text.remove( 0, index + 3 ); + index=text.find( " [" ); + if( index == -1 ) + break; + performerList.append( text.left(index) ); + text.remove( 0, index + 2 ); + index = text.find( "]" ); + if( index == -1 ) + break; + time = text.left( index ); + sscanf( time, "%i:%i", &min, &sec ); + timeList.append( min * 60 + sec ); + text.remove( 0, index + 2 ); + } + + newText.append( "TITLE \"\"\n" ); + newText.append( "PERFORMER \"\"\n" ); + newText.append( "FILE \"\" MP3\n" ); + + int TRACK = 1; + int INDEX = 0; + bool addFrames = false; + QStringList::Iterator performerIt = performerList.begin(); + QValueList::Iterator timeIt = timeList.begin(); + for( QStringList::Iterator titleIt = titleList.begin(); titleIt != titleList.end(); ++titleIt ) + { + newText.append( QString().sprintf(" TRACK %02i AUDIO\n",TRACK ) ); + newText.append( " TITLE \"" + (*titleIt) + "\"\n" ); + newText.append( " PERFORMER \"" + (*performerIt) + "\"\n" ); + if( addFrames ) { + newText.append( QString().sprintf(" INDEX 01 %02i:%02i:37\n",INDEX/60,INDEX%60) ); + INDEX++; + addFrames = false; + } + else { + newText.append( QString().sprintf(" INDEX 01 %02i:%02i:00\n",INDEX/60,INDEX%60) ); + addFrames = true; + } + + performerIt++; + timeIt++; + TRACK++; + INDEX += (*timeIt); + } + + tTextEdit->setText(newText); +} + +void CuesheetEditor::convert() +{ + QString text=tTextEdit->text(); + QString newText; + QString tmpText; + QString first, rest; + QStringList splinters; + int index; + + while( index!=-1 ) + { + index=text.find("\""); + if( index==-1 ) + break; + newText+=text.left(index+1); + text.remove(0,index+1); + index=text.find("\""); + tmpText=text.left(index+1); + text.remove(0,index+1); + if( newText.right(6) == "FILE \"" ) + { + newText+=tmpText; + continue; + } + splinters=QStringList::split(' ',tmpText); + for( QStringList::Iterator it=splinters.begin(); it!=splinters.end(); ++it ) + { + for( uint i=0; i<(*it).length(); i++ ) + { + if( (*it).left(i).lower() != (*it).left(i).upper() ) + { + index=i; + break; + } + } + first=(*it).left(index); + first=first.upper(); + rest=(*it).right((*it).length()-index); + rest=rest.lower(); + for( uint i=0; isetText( newText ); +} + +void CuesheetEditor::shift() //move the title to "PERFORMER" and performer to "TITLE" +{ + QString text = tTextEdit->text(); + QString newText; + QString line, title="", performer=""; + int index; + + while( index !=- 1 ) + { + index = text.find("\n"); + if( index == -1 ) + break; + line = text.left(index+1); + text.remove(0,index+1); + // TODO clean up + if( line.find( "TITLE" ) != -1 ) { + line.replace( "TITLE", "PERFORMER" ); + if( performer != "" ) newText += performer; + performer=line; + } + else if( line.find( "PERFORMER" ) != -1 ) { + line.replace( "PERFORMER", "TITLE" ); + if( title != "" ) newText += title; + title = line; + } + else { + if( title != "" ) newText += title; + if( performer != "" ) newText += performer; + title = ""; + performer = ""; + newText += line; + } + + if( title != "" && performer != "" ) { + newText += title; + newText += performer; + title = ""; + performer = ""; + } + } + + tTextEdit->setText( newText ); +} + + +/* +void CuesheetEditor::shift() //replace title by performer and reverse +{ + QString text=tTextEdit->text(); + QString newText; + QString line, title, performer; + int index; + + while( index!=-1 ) + { + index=text.find("\n"); + if( index==-1 ) + break; + line=text.left(index+1); + text.remove(0,index+1); + if( line.find(" TITLE \"") != -1 ) { + line.replace(" TITLE \""," PERFORMER \""); + newText+=line; + } + else if( line.find(" PERFORMER \"") != -1 ) { + line.replace(" PERFORMER \""," TITLE \""); + newText+=line; + } + else { + newText+=line; + } + } + + tTextEdit->setText(newText); +} +*/ diff --git a/src/cuesheeteditor.h b/src/cuesheeteditor.h new file mode 100755 index 0000000..db5d986 --- /dev/null +++ b/src/cuesheeteditor.h @@ -0,0 +1,50 @@ + + +#ifndef CUESHEETEDITOR_H +#define CUESHEETEDITOR_H + +#include +#include + + +//class KTextEdit; +class KPushButton; + +/** + * @short The editor tool for cuesheet files + * @author Daniel Faust + * @version 0.3 + */ +class CuesheetEditor : public KDialog +{ + Q_OBJECT +public: + /** + * Default Constructor + */ + CuesheetEditor( QWidget* parent=0, const char* name=0, bool modal=true, WFlags f=0 ); + + /** + * Default Destructor + */ + virtual ~CuesheetEditor(); + + void setContent( const QString& text ) { tTextEdit->setText( text ); } + +private slots: + void help(); + void convert(); + void generate(); + void shift(); + +private: + KTextEdit* tTextEdit; + KPushButton* pHelp; + KPushButton* pGenerate; + KPushButton* pConvert; + KPushButton* pShift; + KPushButton* pOk; + +}; + +#endif // CUESHEETEDITOR_H diff --git a/src/dcopinterface.h b/src/dcopinterface.h new file mode 100755 index 0000000..18a097c --- /dev/null +++ b/src/dcopinterface.h @@ -0,0 +1,58 @@ + + +#ifndef DCOPINTERFACE_H +#define DCOPINTERFACE_H + +#include + +#include + +/** + * @short The soundKonverter DCOP interface + * @author Daniel Faust + * @version 0.3 + */ +class DCOPInterface : virtual public DCOPObject +{ + K_DCOP +k_dcop: + /** + * When a new instance of soundKonverter should be created, + * this function is called and all @p files are passed, that should be opened (for conversion). + */ + virtual void openArgFiles( const QStringList &files ) = 0; + + /** + * When a new instance of soundKonverter should be created, + * this function is called and all @p files are passed, that should be opened for editing the replaygain tag. + */ + virtual void openArgReplayGainFiles( const QStringList &files ) = 0; + + /* + * When a new instance of soundKonverter should be created, + * this function is called and all @p files are passed, that should be opened for repair. + */ +// virtual void openArgRepairFiles( const QStringList &files ) = 0; + + +// TODO code cleanups +/* + virtual void openFiles(const QStringList &files) = 0; + virtual void openReplayGainFiles(const QStringList &files) = 0; + virtual void showFileDialog() = 0; + virtual void showDirDialog() = 0; + virtual void showCDDialog() = 0; + virtual void showURLDialog() = 0; + virtual void showReplayGainScanner() = 0; + virtual void showCuesheetEditor() = 0; + virtual void showConfigDialog() = 0; + virtual void showLogViewer() = 0; + virtual void startConversion() = 0; + virtual void stopConversion() = 0; + virtual void killConversion() = 0; + virtual void removeFiles(const QStringList &files) = 0; +*/ +}; + + +#endif // DCOPINTERFACE_H diff --git a/src/dirdialog.cpp b/src/dirdialog.cpp new file mode 100755 index 0000000..924036d --- /dev/null +++ b/src/dirdialog.cpp @@ -0,0 +1,154 @@ + +#include "dirdialog.h" +#include "config.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +// #include +#include +#include + +DirDialog::DirDialog( Config* config, Mode mode, QWidget *parent, const char *name, bool modal, WFlags f ) + : KDialog( parent, name, modal, f ) +{ + // create an icon loader object for loading icons + KIconLoader* iconLoader = new KIconLoader(); + + setCaption( i18n("Add folder") ); + resize( 400, 235 ); + setIcon( iconLoader->loadIcon("folder_open",KIcon::Small) ); + + QGridLayout* grid = new QGridLayout( this, 4, 1, 11, 6 ); + + QHBoxLayout* directoryBox = new QHBoxLayout(); + grid->addLayout( directoryBox, 0, 0 ); + + QLabel* labelDirectory = new QLabel( i18n("Directory:"), this, "labelDirectory" ); + directoryBox->addWidget( labelDirectory ); + +// uDirectory = new KURLRequester( this, "uDirectory" ); +// uDirectory->setMode( KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly ); +// uDirectory->setURL( QDir::homeDirPath() ); +// directoryBox->addWidget( uDirectory ); + + lDirectory = new KLineEdit( this, "lDirectory" ); + directoryBox->addWidget( lDirectory ); + + pDirectory = new KPushButton( iconLoader->loadIcon("folder_open",KIcon::Small), "", this, "pDirectory" ); + directoryBox->addWidget( pDirectory ); + connect( pDirectory, SIGNAL(clicked()), + this, SLOT(selectDirectoryClicked()) + ); + + QHBoxLayout* fileTypesBox = new QHBoxLayout(); + grid->addLayout( fileTypesBox, 1, 0 ); + + fileTypes = new KListBox( this, "fileTypes" ); + if( mode == Convert ) fileTypes->insertStringList( config->fileTypes() ); + else if( mode == ReplayGain ) fileTypes->insertStringList( config->replayGainFileTypes() ); + fileTypes->setSelectionMode( QListBox::Multi ); + for( int i = 0; i < fileTypes->count(); i++ ) fileTypes->setSelected( i, true ); + fileTypesBox->addWidget( fileTypes ); + + QVBoxLayout* fileTypesButtonsBox = new QVBoxLayout(); + fileTypesBox->addLayout( fileTypesButtonsBox ); + + pSelectAll = new KPushButton( iconLoader->loadIcon("font",KIcon::Small), i18n("Select all"), this, "pSelectAll" ); + fileTypesButtonsBox->addWidget( pSelectAll ); + connect( pSelectAll, SIGNAL(clicked()), + this, SLOT(selectAllClicked()) + ); + + pSelectNone = new KPushButton( iconLoader->loadIcon("empty",KIcon::Small), i18n("Select none"), this, "pSelectNone" ); + fileTypesButtonsBox->addWidget( pSelectNone ); + connect( pSelectNone, SIGNAL(clicked()), + this, SLOT(selectNoneClicked()) + ); + + cRecursive = new QCheckBox( i18n("Recursive"), this, "cRecursive" ); + cRecursive->setChecked( true ); + recursive = true; + fileTypesButtonsBox->addWidget( cRecursive ); + connect( cRecursive, SIGNAL(toggled(bool)), + this, SLOT(recursiveToggled(bool)) + ); + + fileTypesButtonsBox->addStretch(); + + QHBoxLayout* buttonBox = new QHBoxLayout(); + grid->addLayout( buttonBox, 2, 0 ); + + pOk = new KPushButton( iconLoader->loadIcon("folder_open",KIcon::Small), i18n("Open"), this, "pOk" ); + buttonBox->addWidget( pOk ); + connect( pOk, SIGNAL(clicked()), + this, SLOT(okClicked()) + ); + + buttonBox->addStretch(); + + pCancel = new KPushButton( iconLoader->loadIcon("cancel",KIcon::Small),i18n("Cancel"), this, "pCancel" ); + pOk->setFocus(); + buttonBox->addWidget( pCancel ); + connect( pCancel, SIGNAL(clicked()), + this, SLOT(reject()) + ); + + // delete the icon loader object + delete iconLoader; + + QString directory = KFileDialog::getExistingDirectory( ":file_open", this, i18n("Choose a directory") ); + if( !directory.isEmpty() ) + { + lDirectory->setText( directory ); + } + else + { + lDirectory->setText( QDir::homeDirPath() ); + } +} + +DirDialog::~DirDialog() +{} + +void DirDialog::okClicked() +{ + selectedFileTypes.clear(); + for( int i = 0; i < fileTypes->count(); i++ ) { + if( fileTypes->isSelected(i) ) selectedFileTypes += QStringList::split(", ",fileTypes->text(i)); + } + directory = lDirectory->text(); + + emit accept(); +} + +void DirDialog::selectDirectoryClicked() +{ + QString directory = KFileDialog::getExistingDirectory( lDirectory->text(), this, i18n("Choose a directory") ); + if( !directory.isEmpty() ) + { + lDirectory->setText( directory ); + } +} + +void DirDialog::selectAllClicked() +{ + for( int i = 0; i < fileTypes->count(); i++ ) fileTypes->setSelected( i, true ); +} + +void DirDialog::selectNoneClicked() +{ + for( int i = 0; i < fileTypes->count(); i++ ) fileTypes->setSelected( i, false ); +} + +void DirDialog::recursiveToggled( bool checked ) +{ + recursive = checked; +} + diff --git a/src/dirdialog.h b/src/dirdialog.h new file mode 100755 index 0000000..4227a9e --- /dev/null +++ b/src/dirdialog.h @@ -0,0 +1,65 @@ + +#ifndef DIRDIALOG_H +#define DIRDIALOG_H + +#include + +class Config; + +class QCheckBox; + +class KLineEdit; +class KPushButton; +// class KURLRequester; +class KListBox; + +/** + * @short The Replay Gain Tool + * @author Daniel Faust + * @version 0.3 + */ +class DirDialog : public KDialog +{ + Q_OBJECT +public: + enum Mode { + Convert = 0x0001, + ReplayGain = 0x0002 + }; + + /** + * Constructor + */ + DirDialog( Config*, Mode, QWidget* parent=0, const char* name=0, bool modal=true, WFlags f=0 ); + + /** + * Destructor + */ + virtual ~DirDialog(); + + QString directory; + QStringList selectedFileTypes; + bool recursive; + +private slots: + void selectDirectoryClicked(); + void okClicked(); + void selectAllClicked(); + void selectNoneClicked(); + void recursiveToggled( bool ); + +private: +// KURLRequester* uDirectory; + KLineEdit* lDirectory; + KPushButton* pDirectory; + KListBox* fileTypes; + KPushButton* pSelectAll; + KPushButton* pSelectNone; + QCheckBox* cRecursive; + KPushButton* pCancel; + KPushButton* pOk; + +}; + + +#endif diff --git a/src/filelist.cpp b/src/filelist.cpp new file mode 100755 index 0000000..c4e6b5d --- /dev/null +++ b/src/filelist.cpp @@ -0,0 +1,1445 @@ + +#include "filelist.h" +#include "cdmanager.h" +#include "tagengine.h" +#include "options.h" +#include "convert.h" +#include "optionseditor.h" +#include "outputdirectory.h" +#include "config.h" +#include "logger.h" +#include "convertpluginloader.h" // NOTE DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// TODO when stopping items by using the context menu, the queue mode restarts that item + +// TODO when dropping items, don't let the user select the position + +// ### soundkonverter 0.4: draw tooltip like bubble info box + +FileListItem::FileListItem( KListView* parent, FileListItem* after ) + : KListViewItem( parent, after ) +{ + tags = 0; + converting = false; + time = 0; + ripping = false; +} + +FileListItem::FileListItem( KListView* parent ) + : KListViewItem( parent ) +{ + tags = 0; + converting = false; + time = 0; + ripping = false; +} + +FileListItem::~FileListItem() +{} + +void FileListItem::paintCell( QPainter *p, const QColorGroup &cg, int column, int width, int alignment ) +{ + // NOTE speed up this function + // NOTE calculate the red color + + QColorGroup _cg( cg ); + QColor c; + + if( column == ((FileList*)listView())->columnByName(i18n("Input")) || column == ((FileList*)listView())->columnByName(i18n("Output")) ) + { + int margin = listView()->itemMargin(); + int w = width - 2*margin; + int h = height(); + QRect textRect = p->boundingRect( margin, 0, w, h, alignment, text(column) ); + + if( textRect.width() > w ) { + alignment = Qt::AlignRight | Qt::SingleLine; + } + + /*if ( textRect.width() <= w ) { + p->drawText( margin, 0, w, h, alignment | Qt::SingleLine | Qt::ExpandTabs, text(column), -1 ); + } + else { + textRect = p->boundingRect( margin, 0, w, h, Qt::AlignLeft, "... " ); + p->drawText( margin, 0, textRect.width(), h, Qt::AlignLeft | Qt::SingleLine | Qt::ExpandTabs, "...", -1 ); + p->drawText( margin+textRect.width(), 0, w-textRect.width(), h, Qt::AlignRight | Qt::SingleLine | Qt::ExpandTabs, text(column), -1 ); + }*/ + } + + if( isSelected() && converting ) { + _cg.setColor( QColorGroup::Highlight, QColor( 215, 62, 62 ) ); + QListViewItem::paintCell( p, _cg, column, width, alignment ); + return; + } + else if( converting && column != listView()->sortColumn() ) { + _cg.setColor( QColorGroup::Base, QColor( 255, 234, 234 ) ); + QListViewItem::paintCell( p, _cg, column, width, alignment ); + return; + } + else if( converting && column == listView()->sortColumn() ) { + _cg.setColor( QColorGroup::Base, QColor( 247, 227, 227 ) ); + QListViewItem::paintCell( p, _cg, column, width, alignment ); + return; + } + + KListViewItem::paintCell( p, _cg, column, width, alignment ); +} + +/*void FileListItem::updateOutputCell() +{ + setText( ((FileList*)listView())->columnByName(i18n("Output")), OutputDirectory::calcPath(this) ); // FIXME no config !!! +} + +void FileListItem::updateOptionsCell() +{ + setText( ((FileList*)listView())->columnByName(i18n("Quality")), ((FileList*)listView())->config->getProfileName(options) ); +}*/ + +FileList::FileList( CDManager* _cdManager, TagEngine* _tagEngine, Config* _config, Options* _options, Logger* _logger, QWidget* parent, const char* name ) + : KListView( parent, name ) +{ + cdManager = _cdManager; + tagEngine = _tagEngine; + config = _config; + options = _options; + logger = _logger; + optionsEditor = 0; + + queue = false; + notify = ""; + + setAcceptDrops( true ); + setDragEnabled( true ); + + addColumn( i18n("State"), 120 ); + addColumn( i18n("Input"), 180 ); + addColumn( i18n("Output"), 180 ); + addColumn( i18n("Quality") ); + + header()->setClickEnabled( false ); + + setSelectionMode( QListView::Extended ); + setAllColumnsShowFocus( true ); + setResizeMode( LastColumn ); + setSorting( -1 ); // NOTE if commented out, items aren't moveable anymore + + setMinimumHeight( 200 ); + + QGridLayout* grid = new QGridLayout( this, 2, 1, 11, 6 ); + grid->setRowStretch( 0, 1 ); + grid->setRowStretch( 2, 1 ); + grid->setColStretch( 0, 1 ); + grid->setColStretch( 2, 1 ); + pScanStatus = new KProgress( this, "pScanStatus" ); + pScanStatus->setMinimumHeight( pScanStatus->height() ); + pScanStatus->setFormat( "%v / %m" ); + pScanStatus->hide(); + grid->addWidget( pScanStatus, 1, 1 ); + grid->setColStretch( 1, 2 ); + + contextMenu = new KPopupMenu( this ); + connect( this, SIGNAL(contextMenuRequested( QListViewItem*, const QPoint&, int )), + this, SLOT(showContextMenu( QListViewItem*, const QPoint&, int )) + ); + + // we haven't got access to the action collection of soundKonverter, so let's create a new one + actionCollection = new KActionCollection( this ); + + edit = new KAction( i18n("Edit options ..."), "view_text", 0, this, SLOT(showOptionsEditorDialog()), actionCollection, "edit_options" ); + start = new KAction( i18n("Start conversion"), "run", 0, this, SLOT(convertSelectedItems()), actionCollection, "start_conversion" ); + stop = new KAction( i18n("Stop conversion"), "stop", 0, this, SLOT(stopSelectedItems()), actionCollection, "stop_conversion" ); + remove = new KAction( i18n("Remove"), "edittrash", Key_Delete, this, SLOT(removeSelectedItems()), actionCollection, "remove" ); + paste = new KAction( i18n("Paste"), "editpaste", 0, this, 0, actionCollection, "paste" ); // TODO paste + + connect( this, SIGNAL(selectionChanged()), + this, SLOT(itemsSelected()) + ); + +// connect( this, SIGNAL(clicked(QListViewItem*,const QPoint&,int)), +// this, SLOT(clickedSomewhere(QListViewItem*,const QPoint&,int)) +// ); + + bubble = new QSimpleRichText( i18n( "
" + "

File List

" + "Select your desired output options in the form above and add some files.
" + "You can add files by clicking on \"Add files ...\" or dropping them here." +// "
Learn more about audio compression ..." + "
" ), QApplication::font() ); + + connect( header(), SIGNAL(sizeChange( int, int, int )), + SLOT(columnResizeEvent( int, int, int )) + ); + connect( this, SIGNAL( dropped(QDropEvent*, QListViewItem*, QListViewItem*) ), + SLOT( slotDropped(QDropEvent*, QListViewItem*, QListViewItem*) ) + ); + +// if( QFile::exists(locateLocal("data","soundkonverter/filelist.autosave.xml")) ) load( true ); + +// debug(); // NOTE DEBUG +} + +FileList::~FileList() +{ + delete optionsEditor; +} + +int FileList::columnByName( const QString& name ) +{ + for( int i = 0; i < columns(); ++i ) { + if( columnText( i ) == name ) return i; + } + return -1; +} + +void FileList::viewportPaintEvent( QPaintEvent* e ) +{ + KListView::viewportPaintEvent( e ); + + // the bubble help + if( childCount() == 0 ) { + QPainter p( viewport() ); + + bubble->setWidth( width() - 50 ); + + const uint w = bubble->width() + 20; + const uint h = bubble->height() + 20; + + p.setBrush( colorGroup().background() ); + p.drawRoundRect( 15, 15, w, h, (8*200)/w, (8*200)/h ); + bubble->draw( &p, 20, 20, QRect(), colorGroup() ); + } +} + +void FileList::viewportResizeEvent( QResizeEvent* ) +{ + // needed for correct redraw of bubble help + triggerUpdate(); +} + +void FileList::columnResizeEvent( int, int, int ) +{ + // needed for correct redraw of bubble help + triggerUpdate(); +} + +// void FileList::clickedSomewhere( QListViewItem*, const QPoint& pos, int ) +// { +// /* if( childCount() == 0 ) { +// kdDebug() << "clicked: `" << bubble->anchorAt(mapFromGlobal(pos)-QPoint(24,0)) << " (" << pos.x() << " | " << pos.y() << ")'" << endl; +// }*/ +// } + +bool FileList::acceptDrag( QDropEvent* e ) const +{ + return ( e->source() == viewport() || KURLDrag::canDecode(e) ); // TODO verify the files +} + +void FileList::slotDropped( QDropEvent* e, QListViewItem*, QListViewItem* itemAfter ) +{ + QString file; + KURL::List list; + QStringList files; + if( KURLDrag::decode( e, list ) ) // TODO local? + { + save( true ); + for( KURL::List::Iterator it = list.begin(); it != list.end(); ++it ) + { + // TODO verify the files (necessary when multiple files are being dropped) + // TODO implement cdda:/ + file = QDir::convertSeparators( (*it).pathOrURL() ); // TODO implement that in the url/file dialog, too? + QFileInfo fileInfo( file ); + if( fileInfo.isDir() ) + { + addDir( file ); + } + else + { + files.append( (*it).url() ); + } + } + addFiles( files, (FileListItem*)itemAfter, true ); + save( true ); + } +} + +void FileList::showContextMenu( QListViewItem* item, const QPoint& point, int ) +{ + // if item is null, we can abort here + if( !item ) return; + + // remove all items from the context menu + contextMenu->clear(); + + // add a tilte to our context manu + //contextMenu->insertTitle( static_cast(item)->fileName ); // TODO sqeeze or something else + + // TODO implement pasting, etc. + + // is this file (of our item) beeing converted at the moment? + if( !static_cast(item)->converting ) { + edit->plug( contextMenu ); + contextMenu->insertSeparator(); + remove->plug( contextMenu ); + //paste->plug( contextMenu ); + contextMenu->insertSeparator(); + start->plug( contextMenu ); + } + else { + stop->plug( contextMenu ); + //contextMenu->insertSeparator(); + //remove->plug( contextMenu ); + //paste->plug( contextMenu ); + } + + // show the popup menu + contextMenu->popup( point ); +} + +void FileList::removeSelectedItems() +{ + FileListItem *item = firstChild(), *nextitem = 0; + + while( item != 0 ) { + if( item->isSelected() && !item->converting ) { + nextitem = item->nextSibling(); + emit decreaseTime( item->time ); + delete item; + item = nextitem; + } + else { + item = item->nextSibling(); + } + } + emit fileCountChanged( childCount() ); + itemsSelected(); +} + +void FileList::convertSelectedItems() +{ + FileListItem* item = firstChild(); + + while( item != 0 ) { + if( item->isSelected() && !item->converting ) { + emit convertItem( item ); + } + item = item->nextSibling(); + } + itemsSelected(); + emit startedConversion(); +} + +void FileList::stopSelectedItems() +{ + FileListItem* item = firstChild(); + + while( item != 0 ) { + if( item->isSelected() && item->converting ) { + emit stopItem( item ); + } + item = item->nextSibling(); + } +} + +int FileList::listDir( const QString& directory, QStringList filter, bool recursive, bool fast, int count ) +{ // NOTE speed up? + QDir dir( directory ); + dir.setFilter( QDir::Files | QDir::Dirs | QDir::NoSymLinks | QDir::Readable ); + + QStringList list = dir.entryList(); + + for( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { + if( *it == "." || *it == ".." ) continue; + QFileInfo fileInfo( directory + "/" + *it ); + if( fast ) { + if( fileInfo.isDir() && recursive ) { + count = listDir( fileInfo.filePath(), filter, recursive, fast, count ); + } + else if( !fileInfo.isDir() || !recursive ) { // NOTE checking for isFile may not work with all file names + // NOTE filter feature + for( QStringList::Iterator jt = filter.begin(); jt != filter.end(); ++jt ) { + if( (*it).endsWith("."+(*jt),false) ) { + count++; + pScanStatus->setTotalSteps( count ); + break; + } + } + if( filter.first() == "" ) { + count++; + pScanStatus->setTotalSteps( count ); + } + } + } + else { + if( fileInfo.isDir() && recursive ) { + count = listDir( fileInfo.filePath(), filter, recursive, fast, count ); + } + else if( !fileInfo.isDir() || !recursive ) { // NOTE checking for isFile may not work with all file names + // NOTE filter feature + for( QStringList::Iterator jt = filter.begin(); jt != filter.end(); ++jt ) { + if( (*it).endsWith("."+(*jt),false) ) { + addFiles( KURL::encode_string(directory + "/" + *it) ); + count++; + pScanStatus->setProgress( count ); + break; + } + } + if( filter.first() == "" ) { + addFiles( KURL::encode_string(directory + "/" + *it) ); + count++; + pScanStatus->setProgress( count ); + } + } + } + } + + return count; +} + +// NOTE progressbar when adding files? +void FileList::addFiles( QStringList fileList, FileListItem* after, bool enabled ) +{ + // TODO test if everything works with remote files (http://) and local files (media://) + FileListItem* lastListItem; + if( !after && !enabled ) lastListItem = lastItem(); + else lastListItem = after; + QString filePathName; + QString device; + + for( QStringList::Iterator it = fileList.begin(); it != fileList.end(); ++it ) { + FileListItem* newItem = new FileListItem( this, lastListItem ); + lastListItem = newItem; + newItem->options = options->getCurrentOptions(); // FIXME speed up + newItem->notify = notify; + newItem->local = false; + newItem->track = -1; + newItem->url = *it; + + if( (*it).left( 1 ) == "/" ) { + filePathName = *it; + newItem->local = true; + } + else if( (*it).left( 7 ) == "file://" ) { + filePathName = *it; + filePathName.remove( 0, 7 ); + newItem->local = true; + } + else if( (*it).left( 13 ) == "system:/home/" ) { + filePathName = *it; + filePathName.remove( 0, 13 ); + filePathName = QDir::homeDirPath() + "/" + filePathName; + newItem->local = true; + } + else if( (*it).left( 14 ) == "system:/users/" || (*it).left( 6 ) == "home:/" ) { + int length = ( (*it).left(6) == "home:/" ) ? 6 : 14; + QString username = *it; + username.remove( 0, length ); + username = username.left( username.find("/") ); + filePathName = *it; + filePathName.remove( 0, length + username.length() ); + KUser user( username ); + filePathName = user.homeDir() + filePathName; + newItem->local = true; + } + else if( (*it).left( 14 ) == "system:/media/" || (*it).left( 7 ) == "media:/" ) { + int length = ( (*it).left(7) == "media:/" ) ? 7 : 14; + device = *it; + device.remove( 0, length ); + device = "/dev/" + device.left( device.find( "/" ) ); + + KMountPoint::List mountPoints = KMountPoint::possibleMountPoints(); + + for( KMountPoint::List::ConstIterator jt = mountPoints.begin(); jt != mountPoints.end(); ++jt ) + { + const KSharedPtr mp = *jt; + logger->log( 1000, mp->mountedFrom() + " : " + mp->mountPoint() ); + if( mp->mountedFrom() == device ) + { + filePathName = ( mp->mountPoint() == "/" ) ? mp->mountPoint() : mp->mountPoint() + "/"; + filePathName += (*it).right( (*it).length() - device.length() - length + 4 ); + } + } + + newItem->local = true; + } +// else if( (*it).left( 14 ) == "system:/trash/" || (*it).left( 7 ) == "trash:/" ) { +// } + + if( newItem->local == true ) { +// logger->log( 1000, i18n("Adding file") + ": " + filePathName ); + newItem->mimeType = KMimeType::findByFileContent( filePathName )->name(); + newItem->fileFormat = KMimeType::findByFileContent( filePathName )->patterns().first().lower(); + newItem->fileFormat.remove( 0, 2 ); +// logger->log( 1000, " " + i18n("Mime type") + ": " + newItem->mimeType + " (" + i18n("Format") + ": " + newItem->fileFormat + ")" ); +// newItem->mimeType=""; + if( newItem->mimeType.isEmpty() || newItem->mimeType == "application/octet-stream" || newItem->mimeType == "text/plain" ) { + newItem->mimeType = KMimeType::findByURL( filePathName.lower() )->name(); + newItem->fileFormat = KMimeType::findByURL( filePathName.lower() )->patterns().first().lower(); + newItem->fileFormat.remove( 0, 2 ); +// logger->log( 1000, " " + i18n("Mime type") + ": " + newItem->mimeType + " (" + i18n("Format") + ": " + newItem->fileFormat + ")" ); +// newItem->mimeType=""; + // HACK last choise is to use the extension without KDE's help + if( newItem->mimeType.isEmpty() || newItem->mimeType == "application/octet-stream" || newItem->mimeType == "text/plain" ) { + newItem->fileFormat = filePathName.right( filePathName.length() - filePathName.findRev(".") - 1 ); + FormatItem *formatItem = config->getFormatItem( newItem->fileFormat ); + if( formatItem ) newItem->mimeType = formatItem->mime_types.first(); +// logger->log( 1000, " " + i18n("Mime type") + ": " + newItem->mimeType + " (" + i18n("Format") + ": " + newItem->fileFormat + ")" ); + } + } +// logger->log( 1000, " " + i18n("Mime type") + ": " + newItem->mimeType + " (" + i18n("Format") + ": " + newItem->fileFormat + ")" ); + // check whether the mime type has a decoder registered + if( !config->acceptFile( newItem->mimeType ) || ( newItem->fileFormat == "wav" && newItem->options.encodingOptions.sFormat == "wav" ) ) { + delete newItem; + continue; + } + newItem->options.filePathName = filePathName; + QFileInfo fileInfo( filePathName ); + newItem->fileName = fileInfo.fileName(); + newItem->tags = tagEngine->readTags( KURL::decode_string(filePathName) ); + if( newItem->tags == 0 ) { +// logger->log( 1000, " " + i18n("Reading tags failed") ); + // FIXME check for wav files + FormatItem* formatItem = config->getFormatItem( newItem->mimeType ); + if( formatItem && formatItem->size > 0 ) { + newItem->time = fileInfo.size() / formatItem->size; + } + else { + newItem->time = 210; + } + } + else { +// logger->log( 1000, " " + i18n("Tags successfully read") ); + newItem->time = newItem->tags->length; + } + } + else { +// logger->log( 1000, " File is remote (not yet implemented) (" + *it + ")" ); + filePathName = *it; + newItem->fileName = filePathName.right( filePathName.length() - filePathName.findRev("/") - 1 ); + newItem->fileFormat = newItem->fileName.right( newItem->fileName.length() - newItem->fileName.findRev(".") - 1 ).lower(); + // NOTE http will not work with KMimeType - this just works + if( filePathName.startsWith("http://") ) { + newItem->mimeType = KMimeType::findByURL( "file:///" + newItem->fileName.lower() )->name(); + } + else { + newItem->mimeType = KMimeType::findByURL( filePathName.lower() )->name(); + } + // check whether the mime type has a decoder registered + if( newItem->mimeType == "" ) { + newItem->mimeType = newItem->fileFormat; + } + if( !config->acceptFile( newItem->mimeType ) || ( newItem->fileFormat == "wav" && newItem->options.encodingOptions.sFormat == "wav" ) ) { + delete newItem; + continue; + } + newItem->options.filePathName = filePathName; + newItem->tags = 0; + newItem->time = 210; // NOTE we can't neither get the length nor guess it without accessing the file + // TODO get the file size and guess the length + } + + updateItem( newItem ); + emit increaseTime( newItem->time ); + } + emit fileCountChanged( childCount() ); +} + +void FileList::addDir( const QString& directory, const QStringList& filter, bool recursive ) +{ + pScanStatus->setProgress( 0 ); + pScanStatus->setTotalSteps( 0 ); + pScanStatus->show(); // show the status while scanning the directories + kapp->processEvents(); + + int count = listDir( directory, filter, recursive, true ); + listDir( directory, filter, recursive ); + + pScanStatus->hide(); // hide the status bar, when the scan is done +} + +void FileList::addTracks( const QString& device, QValueList trackList ) +{ + for( QValueList::Iterator it = trackList.begin(); it != trackList.end(); ++it ) { +// logger->log( 1000, i18n("Adding track") + QString().sprintf(" %02i",*it) ); + FileListItem* newItem = new FileListItem( this, lastItem() ); + newItem->options = options->getCurrentOptions(); // FIXME speed up +// if( newItem->options.outputOptions.mode != OutputDirectory::Specify ) newItem->options.outputOptions.mode = OutputDirectory::MetaData; + newItem->notify = notify; + newItem->track = (*it); + newItem->fileName = i18n("Audio CD (%1)").arg(device) + ": " + i18n("Track") + QString().sprintf(" %02i",newItem->track); + newItem->mimeType = "application/x-cda"; + newItem->fileFormat = "cda"; + newItem->local = true; + newItem->device = device; + newItem->tags = cdManager->getTags( device, newItem->track ); + if( newItem->tags == 0 ) { // NOTE shouldn't happen +// logger->log( 1000, " " + i18n("Reading tags failed") ); + newItem->time = 210; + newItem->options.filePathName = QDir::homeDirPath() + "/" + i18n("Track") + QString().sprintf(" %02i",newItem->track) + "." + newItem->fileFormat; + } + else { +// logger->log( 1000, " " + i18n("Tags successfully read") ); + newItem->time = newItem->tags->length; + newItem->options.filePathName = QDir::homeDirPath() + "/" + QString().sprintf("%02i - ",newItem->track) + newItem->tags->title + "." + newItem->fileFormat; + newItem->fileName = i18n("Audio CD (%1)").arg(device) + ": " + QString().sprintf("%02i - ",newItem->track) + newItem->tags->title; + } + updateItem( newItem ); + emit increaseTime( newItem->time ); + } + emit fileCountChanged( childCount() ); +} + +void FileList::addDisc( const QString& device ) +{ +// logger->log( 1000, i18n("Adding full audio CD (%1)").arg(device) ); + FileListItem* newItem = new FileListItem( this, lastItem() ); + newItem->options = options->getCurrentOptions(); +// if( newItem->options.outputOptions.mode != OutputDirectory::Specify ) newItem->options.outputOptions.mode = OutputDirectory::MetaData; + newItem->notify = notify; + newItem->track = 0; + newItem->fileName = i18n("Full audio CD (%1)").arg(device); + newItem->mimeType = "application/x-cda"; + newItem->fileFormat = "cda"; + newItem->local = true; + newItem->device = device; + newItem->tags = cdManager->getTags( device, 0 ); + if( newItem->tags == 0 ) { // NOTE shouldn't happen +// logger->log( 1000, " " + i18n("Reading tags failed") ); + newItem->time = 3600; + newItem->options.filePathName = QDir::homeDirPath() + "/" + i18n("Audio CD") + "." + newItem->fileFormat; + } + else { +// logger->log( 1000, " " + i18n("Tags successfully read") ); + newItem->time = newItem->tags->length; + newItem->options.filePathName = QDir::homeDirPath() + newItem->tags->title + "." + newItem->fileFormat; + newItem->fileName = i18n("Full audio CD (%1)").arg(device) + ": " + newItem->tags->title; + } + updateItem( newItem ); + emit increaseTime( newItem->time ); + emit fileCountChanged( childCount() ); +} + +void FileList::itemFinished( FileListItem* item, int state ) +{ + if( state == 0 ) { + if( item ) delete item; + itemsSelected(); + } + else if( state == 1 ) { + item->setText( columnByName(i18n("State")), i18n("Stopped") ); + } + else { + item->setText( columnByName(i18n("State")), i18n("Failed") ); + } + + save( true ); + + FileListItem* it = firstChild(); + int waitingCount = 0, convertingCount = 0; + + while( it != 0 ) { + if( it->text(columnByName(i18n("State"))) != i18n("Failed") && it->text(columnByName(i18n("State"))) != i18n("Stopped") && it->text(columnByName(i18n("State"))) != i18n("Will be skipped") ) { + if( it->text(columnByName(i18n("State"))) == i18n("Waiting") /*|| it->text(columnByName(i18n("State"))) == i18n("Stopped")*/ ) { + waitingCount++; + } + else { + convertingCount++; + } + } + it = it->nextSibling(); + } + + if( waitingCount > 0 && queue ) { + convertNextItem(); + } + else if( convertingCount == 0 ) { + queue = false; + float time = 0; + it = firstChild(); + while( it != 0 ) { +// it->setText( columnByName(i18n("State")), i18n("Waiting") ); + updateItem( it ); + time += it->time; + it = it->nextSibling(); + } + emit finished( time ); + emit stoppedConversion(); + emit fileCountChanged( childCount() ); + } +} + +void FileList::rippingFinished( const QString& device ) +{ + if( !queue ) return; + + int count = 0; + FileListItem *item = firstChild(); + while( item != 0 ) { + if( item->converting ) { + count++; + } + item = item->nextSibling(); + } + + // look for "Waiting" files first ... + item = firstChild(); + while( item != 0 && count < config->data.general.numFiles ) { + if( !item->converting && item->text(columnByName(i18n("State"))) == i18n("Waiting") ) { + if( item->track >= 0 && item->device == device ) { + convertItem( item ); + itemsSelected(); + return; + } + } + item = item->nextSibling(); + } + + // ... then convert the stopped, too +/* item = firstChild(); + while( item != 0 && count < config->data.general.numFiles ) { + if( !item->converting && item->text(columnByName(i18n("State"))) == i18n("Stopped") ) { + if( item->track >= 0 && item->device == device ) { + convertItem( item ); + itemsSelected(); + return; + } + } + item = item->nextSibling(); + }*/ +} + +void FileList::updateItem( FileListItem* item ) +{ + if( !item ) return; + + if( !item->converting ) { + if( config->data.general.conflictHandling == 1 && QFile::exists(KURL::decode_string(OutputDirectory::calcPath(item,config))) ) { // was: .replace("%2f","%252f") + item->setText( columnByName(i18n("State")), i18n("Will be skipped") ); + } + else { + item->setText( columnByName(i18n("State")), i18n("Waiting") ); + } + } + else { + item->setText( columnByName(i18n("State")), i18n("Converting") ); + } + + if( item->track >= 0 ) item->setText( columnByName(i18n("Input")), KURL::decode_string(item->fileName).replace("%2f","/").replace("%%","%") ); + else item->setText( columnByName(i18n("Input")), KURL::decode_string(item->options.filePathName).replace("%2f","/").replace("%%","%") ); + + item->setText( columnByName(i18n("Output")), KURL::decode_string(OutputDirectory::uniqueFileName(OutputDirectory::calcPath(item,config))).replace("%2f","/").replace("%%","%") ); + + item->setText( columnByName(i18n("Quality")), config->getProfileName(item->options) ); +} + +void FileList::showOptionsEditorDialog() +{ + // FIXME options are set to defaults + + if( optionsEditor == 0 ) { + optionsEditor = new OptionsEditor( tagEngine, config, this, 0, "optionsEditor" ); + if( optionsEditor == 0 ) { + // TODO error message + return; + } +// } + connect( this, SIGNAL(editItems(QValueList)), + optionsEditor, SLOT(itemsSelected(QValueList)) + ); + connect( this, SIGNAL(setPreviousItemEnabled(bool)), + optionsEditor, SLOT(setPreviousEnabled(bool)) + ); + connect( this, SIGNAL(setNextItemEnabled(bool)), + optionsEditor, SLOT(setNextEnabled(bool)) + ); + connect( optionsEditor, SIGNAL(user2Clicked()), + this, SLOT(selectPreviousItem()) + ); + connect( optionsEditor, SIGNAL(user1Clicked()), + this, SLOT(selectNextItem()) + ); + /*connect( this, SIGNAL(moveEditor(int,int)), + optionsEditor, SLOT(moveWindow(int,int)) + );*/ +} + itemsSelected(); + optionsEditor->show(); +} + +// FIXME still makes some troubles (wreaks some items) and crashes +void FileList::selectPreviousItem() +{ + if( selectedFiles.first() == 0 ) return; + FileListItem* item = selectedFiles.first()->itemAbove(); + if( item != 0 ) { + item->setSelected( true ); + repaintItem( item ); + ensureItemVisible( item ); + } + + for( QValueList::Iterator it = selectedFiles.begin(); it != selectedFiles.end(); ++it ) { + (*it)->setSelected( false ); + repaintItem( *it ); + } + + itemsSelected(); +} + +void FileList::selectNextItem() +{ + if( selectedFiles.last() == 0 ) return; + FileListItem* item = selectedFiles.last()->itemBelow(); + if( item != 0 ) { + item->setSelected( true ); + repaintItem( item ); + ensureItemVisible( item ); + } + + for( QValueList::Iterator it = selectedFiles.begin(); it != selectedFiles.end(); ++it ) { + (*it)->setSelected( false ); + repaintItem( *it ); + } + + itemsSelected(); +} + +void FileList::itemsSelected() +{ + selectedFiles.clear(); + for( FileListItem *item = firstChild(); item != NULL; item = item->nextSibling() ) { + if( item->isSelected() ) { + selectedFiles.append( item ); + } + } + + if( selectedFiles.count() > 0 ) { + if( selectedFiles.first()->itemAbove() != 0 ) emit setPreviousItemEnabled( true ); + else emit setPreviousItemEnabled( false ); + if( selectedFiles.last()->itemBelow() != 0 ) emit setNextItemEnabled( true ); + else emit setNextItemEnabled( false ); + } + else { + emit setPreviousItemEnabled( false ); + emit setNextItemEnabled( false ); + } + + emit editItems( selectedFiles ); +} + +/*void FileList::moveOptionsEditor( int x, int y ) +{ + emit moveEditor( x, y ); +}*/ + +void FileList::startConversion() +{ + // iterate through all items and set the state to "Waiting" + FileListItem* it = firstChild(); + while( it != 0 ) { +// it->setText( columnByName(i18n("State")), i18n("Waiting") ); + if( !it->converting && it->text(columnByName(i18n("State"))) != i18n("Will be skipped") ) { + it->setText( columnByName(i18n("State")), i18n("Waiting") ); + } + it = it->nextSibling(); + } + queue = true; + emit startedConversion(); + convertNextItem(); +} + +void FileList::stopConversion() +{ + queue = false; + emit stopClicked(); +} + +void FileList::continueConversion() +{ + queue = true; + emit continueClicked(); +} + +void FileList::killConversion() +{ + queue = false; + + FileListItem *item = firstChild(); + + while( item != 0 ) { + if( item->converting ) { + emit stopItem( item ); + } + item = item->nextSibling(); + } +} + +void FileList::convertNextItem() +{ + if( !queue ) return; + + QStringList devices; + + // look for tracks that are being ripped + int count = 0; + FileListItem *item = firstChild(); + while( item != 0 ) { + if( item->converting ) { + count++; + if( item->ripping ) { + devices += item->device; + } + } + item = item->nextSibling(); + } + + // look for "Waiting" files first ... + item = firstChild(); + while( item != 0 && count < config->data.general.numFiles ) { + if( !item->converting && item->text(columnByName(i18n("State"))) == i18n("Waiting") ) { + if( item->track >= 0 && devices.findIndex(item->device) == -1 ) { + convertItem( item ); + count++; + devices += item->device; + } + else if( item->track < 0 ) { + convertItem( item ); + count++; + } + } + item = item->nextSibling(); + } + + // ... then convert the stopped, too +// item = firstChild(); +// while( item != 0 && count < config->data.general.numFiles ) { +// if( !item->converting && item->text(columnByName(i18n("State"))) == i18n("Stopped") ) { +// if( item->track >= 0 && devices.findIndex(item->device) == -1 ) { +// convertItem( item ); +// count++; +// devices += item->device; +// } +// else if( item->track < 0 ) { +// convertItem( item ); +// count++; +// } +// } +// item = item->nextSibling(); +// } + + itemsSelected(); + + FileListItem* it = firstChild(); + int waitingCount = 0, convertingCount = 0; + + while( it != 0 ) { + if( it->text(columnByName(i18n("State"))) != i18n("Failed") && it->text(columnByName(i18n("State"))) != i18n("Stopped") && it->text(columnByName(i18n("State"))) != i18n("Will be skipped") ) { + if( it->text(columnByName(i18n("State"))) == i18n("Waiting") /*|| it->text(columnByName(i18n("State"))) == i18n("Stopped")*/ ) { + waitingCount++; + } + else { + convertingCount++; + } + } + it = it->nextSibling(); + } + + if( waitingCount == 0 && convertingCount == 0 ) itemFinished( 0, 0 ); +} + +void FileList::load( bool autosave ) +{ + // NOTE clear the file list befor adding the saved items? + + int version; + QString name; + FileListItem* lastListItem = lastItem(); + QString filename; + if( autosave ) filename = locateLocal("data","soundkonverter/filelist.autosave.xml"); + else filename = locateLocal("data","soundkonverter/filelist.xml"); + + QDomDocument domTree; + QFile opmlFile( filename ); + if( !opmlFile.open( IO_ReadOnly ) ) return; + if( !domTree.setContent( &opmlFile ) ) return; + opmlFile.close(); + + QDomElement root = domTree.documentElement(); + if( root.attribute("type") != "filelist" ) return; + QDomNode node, sub1Node, sub2Node; + node = root.firstChild(); + + while( !node.isNull() ) { + if( node.isElement() && node.nodeName() == "info" ) { + + version = node.toElement().attribute("version").toInt(); + + } + else if( node.isElement() && node.nodeName() == "file" ) { + + FileListItem* item = new FileListItem( this, lastListItem ); + lastListItem = item; + + item->fileName = node.toElement().attribute("fileName"); + item->mimeType = node.toElement().attribute("mimeType"); + item->fileFormat = node.toElement().attribute("fileFormat"); + item->local = node.toElement().attribute("local").toInt(); + item->track = node.toElement().attribute("track").toInt(); + item->time = node.toElement().attribute("time").toInt(); + + item->options.filePathName = node.toElement().attribute("filePathName"); + item->options.outputFilePathName = node.toElement().attribute("outputFilePathName"); + + sub1Node = node.toElement().firstChild(); + while( !sub1Node.isNull() ) { + if( sub1Node.isElement() && sub1Node.nodeName() == "encodingOptions" ) { + + item->options.encodingOptions.sFormat = sub1Node.toElement().attribute("sFormat"); + item->options.encodingOptions.sQualityMode = sub1Node.toElement().attribute("sQualityMode"); + item->options.encodingOptions.iQuality = sub1Node.toElement().attribute("iQuality").toInt(); + item->options.encodingOptions.sBitrateMode = sub1Node.toElement().attribute("sBitrateMode"); + item->options.encodingOptions.bBitrateRange = sub1Node.toElement().attribute("bBitrateRange").toInt(); + item->options.encodingOptions.iMinBitrate = sub1Node.toElement().attribute("iMinBitrate").toInt(); + item->options.encodingOptions.iMaxBitrate = sub1Node.toElement().attribute("iMaxBitrate").toInt(); + item->options.encodingOptions.sInOutFiles = sub1Node.toElement().attribute("sInOutFiles"); + + sub2Node = sub1Node.toElement().firstChild(); + while( !sub2Node.isNull() ) { + if( sub2Node.isElement() && sub2Node.nodeName() == "samplingRate" ) { + + item->options.encodingOptions.samplingRate.bEnabled = sub2Node.toElement().attribute("bEnabled").toInt(); + item->options.encodingOptions.samplingRate.iSamplingRate = sub2Node.toElement().attribute("iSamplingRate").toInt(); + + } + else if( sub2Node.isElement() && sub2Node.nodeName() == "channels" ) { + + item->options.encodingOptions.channels.bEnabled = sub2Node.toElement().attribute("bEnabled").toInt(); + item->options.encodingOptions.channels.sChannels = sub2Node.toElement().attribute("sChannels"); + + } + else if( sub2Node.isElement() && sub2Node.nodeName() == "replaygain" ) { + + item->options.encodingOptions.replaygain.bEnabled = sub2Node.toElement().attribute("bEnabled").toInt(); + + } + sub2Node = sub2Node.nextSibling(); + } + + } + else if( sub1Node.isElement() && sub1Node.nodeName() == "outputOptions" ) { + + item->options.outputOptions.mode = (OutputDirectory::Mode)sub1Node.toElement().attribute("mode").toInt(); + item->options.outputOptions.directory = sub1Node.toElement().attribute("directory"); + + } + else if( sub1Node.isElement() && sub1Node.nodeName() == "tags" ) { + + item->tags = new TagData(); + + item->tags->artist = sub1Node.toElement().attribute("artist"); + item->tags->composer = sub1Node.toElement().attribute("composer"); + item->tags->album = sub1Node.toElement().attribute("album"); + item->tags->title = sub1Node.toElement().attribute("title"); + item->tags->genre = sub1Node.toElement().attribute("genre"); + item->tags->comment = sub1Node.toElement().attribute("comment"); + item->tags->track = sub1Node.toElement().attribute("track").toInt(); + item->tags->disc = sub1Node.toElement().attribute("disc").toInt(); + item->tags->year = sub1Node.toElement().attribute("year").toInt(); + item->tags->track_gain = sub1Node.toElement().attribute("track_gain").toFloat(); + item->tags->album_gain = sub1Node.toElement().attribute("album_gain").toFloat(); + item->tags->length = sub1Node.toElement().attribute("length").toInt(); + item->tags->fileSize = sub1Node.toElement().attribute("fileSize").toInt(); + item->tags->bitrate = sub1Node.toElement().attribute("bitrate").toInt(); + item->tags->samplingRate = sub1Node.toElement().attribute("samplingRate").toInt(); + + } + sub1Node = sub1Node.nextSibling(); + } + updateItem( item ); + emit increaseTime( item->time ); + } + node = node.nextSibling(); + } + emit fileCountChanged( childCount() ); +} + +void FileList::save( bool autosave ) +{ + // NOTE filenames should be encoded before saving - but it works fine without it (hm...) + + QTime time; + time.start(); + + QDomDocument domTree; + QDomElement root = domTree.createElement( "soundkonverter" ); + root.setAttribute( "type", "filelist" ); + domTree.appendChild( root ); + + QDomElement info = domTree.createElement( "info" ); + info.setAttribute( "version", "300" ); + root.appendChild( info ); + + for( FileListItem* item = firstChild(); item != 0; item = item->nextSibling() ) { + QDomElement file = domTree.createElement( "file" ); + file.setAttribute( "fileName", item->fileName ); + file.setAttribute( "mimeType", item->mimeType ); + file.setAttribute( "fileFormat", item->fileFormat ); + file.setAttribute( "local", item->local ); + file.setAttribute( "track", item->track ); + file.setAttribute( "device", item->device ); + file.setAttribute( "time", item->time ); + + file.setAttribute( "filePathName", item->options.filePathName ); + file.setAttribute( "outputFilePathName", item->options.outputFilePathName ); + + QDomElement encodingOptions = domTree.createElement( "encodingOptions" ); + + encodingOptions.setAttribute( "sFormat", item->options.encodingOptions.sFormat ); + encodingOptions.setAttribute( "sQualityMode", item->options.encodingOptions.sQualityMode ); + encodingOptions.setAttribute( "iQuality", item->options.encodingOptions.iQuality ); + encodingOptions.setAttribute( "sBitrateMode", item->options.encodingOptions.sBitrateMode ); + encodingOptions.setAttribute( "bBitrateRange", item->options.encodingOptions.bBitrateRange ); + encodingOptions.setAttribute( "iMinBitrate", item->options.encodingOptions.iMinBitrate ); + encodingOptions.setAttribute( "iMaxBitrate", item->options.encodingOptions.iMaxBitrate ); + + QDomElement samplingRate = domTree.createElement( "samplingRate" ); + + samplingRate.setAttribute( "bEnabled", item->options.encodingOptions.samplingRate.bEnabled ); + samplingRate.setAttribute( "iSamplingRate", item->options.encodingOptions.samplingRate.iSamplingRate ); + + encodingOptions.appendChild( samplingRate ); + + QDomElement channels = domTree.createElement( "channels" ); + + channels.setAttribute( "bEnabled", item->options.encodingOptions.channels.bEnabled ); + channels.setAttribute( "sChannels", item->options.encodingOptions.channels.sChannels ); + + encodingOptions.appendChild( channels ); + + QDomElement replaygain = domTree.createElement( "replaygain" ); + + replaygain.setAttribute( "bEnabled", item->options.encodingOptions.replaygain.bEnabled ); + + encodingOptions.appendChild( replaygain ); + + encodingOptions.setAttribute( "sInOutFiles", item->options.encodingOptions.sInOutFiles ); + + file.appendChild( encodingOptions ); + + QDomElement outputOptions = domTree.createElement( "outputOptions" ); + + outputOptions.setAttribute( "mode", int(item->options.outputOptions.mode) ); + outputOptions.setAttribute( "directory", item->options.outputOptions.directory ); + + file.appendChild( outputOptions ); + + if( item->tags ) + { + QDomElement tags = domTree.createElement( "tags" ); + + tags.setAttribute( "artist", item->tags->artist ); + tags.setAttribute( "composer", item->tags->composer ); + tags.setAttribute( "album", item->tags->album ); + tags.setAttribute( "title", item->tags->title ); + tags.setAttribute( "genre", item->tags->genre ); + tags.setAttribute( "comment", item->tags->comment ); + tags.setAttribute( "track", item->tags->track ); + tags.setAttribute( "disc", item->tags->disc ); + tags.setAttribute( "year", item->tags->year ); + tags.setAttribute( "track_gain", item->tags->track_gain ); + tags.setAttribute( "album_gain", item->tags->album_gain ); + tags.setAttribute( "length", item->tags->length ); + tags.setAttribute( "fileSize", item->tags->fileSize ); + tags.setAttribute( "bitrate", item->tags->bitrate ); + tags.setAttribute( "samplingRate", item->tags->samplingRate ); + + file.appendChild( tags ); + } + + root.appendChild( file ); + } + + QString filename; + if( autosave ) filename = locateLocal("data","soundkonverter/filelist.autosave.xml"); + else filename = locateLocal("data","soundkonverter/filelist.xml"); + + QFile opmlFile( filename ); + if( !opmlFile.open( IO_WriteOnly ) ) return; + + QTextStream ts( &opmlFile ); + ts << domTree.toString(); + + opmlFile.close(); + + logger->log( 1000, "save file list: " + QString::number(time.elapsed()) ); +} + +void FileList::debug() // NOTE DEBUG +{ + logger->log( 1000, "DEBUG begin" ); + + ConversionOptions conversionOptions; + + QStringList formats = config->allEncodableFormats(); + + for( QStringList::Iterator a = formats.begin(); a != formats.end(); ++a ) + { + logger->log( 1000, "format: " + (*a) ); + FormatItem* formatItem = config->getFormatItem( *a ); + if( formatItem == 0 ) continue; + + for( QValueList::Iterator b = formatItem->encoders.begin(); b != formatItem->encoders.end(); ++b ) { + logger->log( 1000, " encoder: " + (*b)->enc.bin ); + formatItem->encoder = (*b); + if( (*b)->enc.strength.enabled ) { + formatItem->compressionLevel = (*b)->enc.strength.default_value; + } + if( (*b)->enc.replaygain.enabled ) { + formatItem->internalReplayGain = true; + } + + if( (*b)->enc.lossless.enabled ) { + options->setProfile( "Lossless" ); + options->setFormat( *a ); + options->setOutputDirectory( "/home/daniel/soundKonverter/test_output" ); + conversionOptions = options->getCurrentOptions(); + conversionOptions.encodingOptions.sInOutFiles = debug_params( conversionOptions, formatItem ); + options->setCurrentOptions( conversionOptions ); + addFiles( "/home/daniel/soundKonverter/test.mp3" ); + } + if( (*b)->enc.lossy.enabled ) { + options->setProfile( "Medium" ); + if( (*b)->enc.lossy.bitrate.cbr.enabled ) { + options->setFormat( *a ); + conversionOptions = options->getCurrentOptions(); + conversionOptions.encodingOptions.sQualityMode = i18n("Bitrate"); + conversionOptions.encodingOptions.sBitrateMode = "cbr"; + conversionOptions.encodingOptions.iQuality = 128; + conversionOptions.encodingOptions.sInOutFiles = debug_params( conversionOptions, formatItem ); + options->setCurrentOptions( conversionOptions ); + options->setOutputDirectory( "/home/daniel/soundKonverter/test_output" ); + addFiles( "/home/daniel/soundKonverter/test.mp3" ); + } + if( (*b)->enc.lossy.bitrate.abr.enabled ) { + options->setFormat( *a ); + conversionOptions = options->getCurrentOptions(); + conversionOptions.encodingOptions.sQualityMode = i18n("Bitrate"); + conversionOptions.encodingOptions.sBitrateMode = "abr"; + conversionOptions.encodingOptions.iQuality = 128; + conversionOptions.encodingOptions.sInOutFiles = debug_params( conversionOptions, formatItem ); + options->setCurrentOptions( conversionOptions ); + options->setOutputDirectory( "/home/daniel/soundKonverter/test_output" ); + addFiles( "/home/daniel/soundKonverter/test.mp3" ); + if( (*b)->enc.lossy.bitrate.abr.bitrate_range.enabled ) { + options->setFormat( *a ); + conversionOptions = options->getCurrentOptions(); + conversionOptions.encodingOptions.sQualityMode = i18n("Bitrate"); + conversionOptions.encodingOptions.sBitrateMode = "abr"; + conversionOptions.encodingOptions.iQuality = 128; + conversionOptions.encodingOptions.bBitrateRange = true; + conversionOptions.encodingOptions.iMinBitrate = 64; + conversionOptions.encodingOptions.iMaxBitrate = 192; + conversionOptions.encodingOptions.sInOutFiles = debug_params( conversionOptions, formatItem ); + options->setCurrentOptions( conversionOptions ); + options->setOutputDirectory( "/home/daniel/soundKonverter/test_output" ); + addFiles( "/home/daniel/soundKonverter/test.mp3" ); + } + } + if( (*b)->enc.lossy.quality.enabled ) { + options->setFormat( *a ); + conversionOptions = options->getCurrentOptions(); + conversionOptions.encodingOptions.sQualityMode = i18n("Quality"); + conversionOptions.encodingOptions.iQuality = 40; + conversionOptions.encodingOptions.sInOutFiles = debug_params( conversionOptions, formatItem ); + options->setCurrentOptions( conversionOptions ); + options->setOutputDirectory( "/home/daniel/soundKonverter/test_output" ); + addFiles( "/home/daniel/soundKonverter/test.mp3" ); + } + } + } + + for( QValueList::Iterator b = formatItem->decoders.begin(); b != formatItem->decoders.end(); ++b ) { + formatItem->decoder = (*b); + } + + for( QValueList::Iterator b = formatItem->replaygains.begin(); b != formatItem->replaygains.end(); ++b ) { + formatItem->replaygain = (*b); + } + } + + logger->log( 1000, "DEBUG end" ); +} + +QString FileList::debug_params( ConversionOptions conversionOptions, FormatItem* formatItem ) // NOTE DEBUG +{ + ConvertPlugin* plugin = formatItem->encoder; + + QString sStrength; + QString sBitrate; + QString sQuality; + QString sMinBitrate; + QString sMaxBitrate; + QString sSamplingRate; + + int t_int; + float t_float; + + QString param = ""; + if( !plugin->enc.param.isEmpty() ) param.append( " " + plugin->enc.param ); + if( !plugin->enc.overwrite.isEmpty() ) param.append( " " + plugin->enc.overwrite ); + + if( plugin->enc.strength.enabled ) { + param.append( " " + plugin->enc.strength.param ); + int compressionLevel = formatItem->compressionLevel; + + if( plugin->enc.strength.profiles.empty() ) { + if( plugin->enc.strength.step < 1 ) { + if( plugin->enc.strength.range_max >= plugin->enc.strength.range_min ) + sStrength = QString::number( compressionLevel ); + else + sStrength = QString::number( plugin->enc.strength.range_min - compressionLevel ); + } + else { + if( plugin->enc.strength.range_max >= plugin->enc.strength.range_min ) + sStrength = QString::number( int(compressionLevel) ); + else + sStrength = QString::number( int(plugin->enc.strength.range_min - compressionLevel) ); + } + if( plugin->enc.strength.separator != '.' ) sStrength.replace( QChar('.'), plugin->enc.strength.separator ); + } + else { + QStringList::Iterator it = plugin->enc.strength.profiles.at( compressionLevel ); + sStrength = *it; + } + } + + if( conversionOptions.encodingOptions.sQualityMode == i18n("Bitrate") ) { + if( conversionOptions.encodingOptions.sBitrateMode == "cbr" && plugin->enc.lossy.bitrate.cbr.enabled ) { + param.append( " " + plugin->enc.lossy.bitrate.cbr.param ); + sBitrate = QString::number( conversionOptions.encodingOptions.iQuality ); + } + else if( conversionOptions.encodingOptions.sBitrateMode == "abr" && plugin->enc.lossy.bitrate.abr.enabled ) { + param.append( " " + plugin->enc.lossy.bitrate.abr.param ); + sBitrate = QString::number( conversionOptions.encodingOptions.iQuality ); + if( conversionOptions.encodingOptions.bBitrateRange && plugin->enc.lossy.bitrate.abr.bitrate_range.enabled ) { + param.append( " " + plugin->enc.lossy.bitrate.abr.bitrate_range.param_min ); + sMinBitrate = QString::number( conversionOptions.encodingOptions.iMinBitrate ); + param.append( " " + plugin->enc.lossy.bitrate.abr.bitrate_range.param_max ); + sMaxBitrate = QString::number( conversionOptions.encodingOptions.iMaxBitrate ); + } + } + } + else if( conversionOptions.encodingOptions.sQualityMode == i18n("Quality") && plugin->enc.lossy.quality.enabled ) { + param.append( " " + plugin->enc.lossy.quality.param ); + if( plugin->enc.lossy.quality.profiles.empty() ) { + if( plugin->enc.lossy.quality.step < 1 ) { + if( plugin->enc.lossy.quality.range_max >= plugin->enc.lossy.quality.range_min) + t_float = ( (float)conversionOptions.encodingOptions.iQuality * ( plugin->enc.lossy.quality.range_max - plugin->enc.lossy.quality.range_min ) / 100 ) + plugin->enc.lossy.quality.range_min; + else + t_float = ( (100.0f - (float)conversionOptions.encodingOptions.iQuality) * ( plugin->enc.lossy.quality.range_min - plugin->enc.lossy.quality.range_max ) / 100 ) + plugin->enc.lossy.quality.range_max; + //t_float -= t_float%plugin->enc.quality.step; + //sQuality = QString().sprintf( "%.2f", t_float ); + sQuality = QString::number( t_float ); + } + else { + if( plugin->enc.lossy.quality.range_max >= plugin->enc.lossy.quality.range_min) + t_int = ( conversionOptions.encodingOptions.iQuality * (int)( plugin->enc.lossy.quality.range_max - plugin->enc.lossy.quality.range_min ) / 100) + (int)plugin->enc.lossy.quality.range_min; + else + t_int = ( (100 - conversionOptions.encodingOptions.iQuality) * (int)( plugin->enc.lossy.quality.range_min - plugin->enc.lossy.quality.range_max ) / 100) + (int)plugin->enc.lossy.quality.range_max; + //t_int -= t_int%plugin->enc.quality.step; + sQuality = QString::number( t_int ); + } + if( plugin->enc.bin == "oggenc" ) sQuality.replace(QChar('.'),KGlobal::locale()->decimalSymbol()); + else if( plugin->enc.lossy.quality.separator != '.' ) sQuality.replace(QChar('.'),plugin->enc.lossy.quality.separator); + } + else { + QStringList::Iterator it = plugin->enc.lossy.quality.profiles.at( int(conversionOptions.encodingOptions.iQuality*plugin->enc.lossy.quality.range_max/100) ); + sQuality = *it; + } + } + else if( conversionOptions.encodingOptions.sQualityMode == i18n("Lossless") && plugin->enc.lossless.enabled ) { + param.append( " " + plugin->enc.lossless.param ); + } + else if( conversionOptions.encodingOptions.sQualityMode == i18n("Hybrid") && plugin->enc.hybrid.enabled ) { + param.append( " " + plugin->enc.hybrid.param ); + sBitrate = QString::number( conversionOptions.encodingOptions.iQuality ); + } + + if( conversionOptions.encodingOptions.samplingRate.bEnabled && plugin->enc.lossy.samplingrate.enabled ) { + param.append( " " + plugin->enc.lossy.samplingrate.param ); + if( plugin->enc.lossy.samplingrate.unit == PluginLoaderBase::Hz ) { + sSamplingRate = QString::number( conversionOptions.encodingOptions.samplingRate.iSamplingRate ); + } + else { + sSamplingRate = QString::number( (float)conversionOptions.encodingOptions.samplingRate.iSamplingRate/1000 ); + } + } + + if( conversionOptions.encodingOptions.channels.bEnabled ) { + if( conversionOptions.encodingOptions.channels.sChannels == i18n("Mono") && plugin->enc.lossy.channels.mono_enabled ) { + param.append( " " + plugin->enc.lossy.channels.mono_param ); + } + else if( conversionOptions.encodingOptions.channels.sChannels == i18n("Stereo") && plugin->enc.lossy.channels.stereo_enabled ) { + param.append( " " + plugin->enc.lossy.channels.stereo_param ); + } + else if( conversionOptions.encodingOptions.channels.sChannels == i18n("Joint-Stereo") && plugin->enc.lossy.channels.joint_stereo_enabled ) { + param.append( " " + plugin->enc.lossy.channels.joint_stereo_param ); + } + else if( conversionOptions.encodingOptions.channels.sChannels == i18n("Forced Joint-Stereo") && plugin->enc.lossy.channels.forced_joint_stereo_enabled ) { + param.append( " " + plugin->enc.lossy.channels.forced_joint_stereo_param ); + } + else if( conversionOptions.encodingOptions.channels.sChannels == i18n("Dual Channels") && plugin->enc.lossy.channels.dual_channels_enabled ) { + param.append( " " + plugin->enc.lossy.channels.dual_channels_param ); + } + } + + if( conversionOptions.encodingOptions.replaygain.bEnabled && plugin->enc.replaygain.enabled && plugin->enc.replaygain.use && formatItem->internalReplayGain ) { + param.append( " " + plugin->enc.replaygain.use ); + } + else if( plugin->enc.replaygain.enabled && plugin->enc.replaygain.avoid ) { + param.append( " " + plugin->enc.replaygain.avoid ); + } + +// if( !tagEngine->canWrite(conversionOptions.encodingOptions.sFormat) && item->fileListItem->tags && plugin->enc.tag.enabled ) { + if( plugin->enc.tag.enabled && conversionOptions.encodingOptions.sFormat != "aac" ) { // HACK don't write metadata to aac + if( !plugin->enc.tag.param.isEmpty() ) param.append( " " + plugin->enc.tag.param ); + if( !plugin->enc.tag.artist.isEmpty() ) param.append( " " + plugin->enc.tag.artist ); + if( !plugin->enc.tag.album.isEmpty() ) param.append( " " + plugin->enc.tag.album ); + if( !plugin->enc.tag.comment.isEmpty() ) param.append( " " + plugin->enc.tag.comment ); + if( !plugin->enc.tag.disc.isEmpty() ) param.append( " " + plugin->enc.tag.disc ); + if( !plugin->enc.tag.genre.isEmpty() ) param.append( " " + plugin->enc.tag.genre ); + if( !plugin->enc.tag.track.isEmpty() ) param.append( " " + plugin->enc.tag.track ); + if( !plugin->enc.tag.composer.isEmpty() ) param.append( " " + plugin->enc.tag.composer ); + if( !plugin->enc.tag.title.isEmpty() ) param.append( " " + plugin->enc.tag.title ); + if( !plugin->enc.tag.year.isEmpty() ) param.append( " " + plugin->enc.tag.year ); + } + + param.replace( "%c", sStrength ); + param.replace( "%b", sBitrate ); + param.replace( "%q", sQuality ); + param.replace( "%m", sMinBitrate ); + param.replace( "%M", sMaxBitrate ); + param.replace( "%s", sSamplingRate ); + + return conversionOptions.encodingOptions.sInOutFiles.replace( "%p", param ); +} diff --git a/src/filelist.h b/src/filelist.h new file mode 100755 index 0000000..484eedc --- /dev/null +++ b/src/filelist.h @@ -0,0 +1,235 @@ + + +#ifndef FILELIST_H +#define FILELIST_H + +#include + +#include "conversionoptions.h" + +class CDManager; +class TagEngine; +class TagData; +class Options; +class OptionsEditor; +class Config; +class Logger; +class FormatItem; // NOTE DEBUG + +class QPainter; +class QColorGroup; +class QSimpleRichText; +class KProgress; +class KPopupMenu; +class KAction; +class KActionCollection; + +/** + * @short The items for the file list + * @author Daniel Faust + * @version 0.3 + */ +class FileListItem : public KListViewItem +{ +public: + /** + * Constructor + * @param parent The parent list view + */ + FileListItem( KListView* parent ); + + /** + * Constructor + * @param parent The parent list view + * @param after The item, the new item should be placed after + */ + FileListItem( KListView* parent, FileListItem* after ); + + /** + * Destructor + */ + virtual ~FileListItem(); + + virtual void paintCell( QPainter* p, const QColorGroup& cg, int column, int width, int alignment ); + + //void updateOutputCell(); + //void updateOptionsCell(); + + FileListItem* nextSibling() const { return static_cast( KListViewItem::nextSibling() ); } + FileListItem* itemAbove() { return static_cast( KListViewItem::itemAbove() ); } + FileListItem* itemBelow() { return static_cast( KListViewItem::itemBelow() ); } + //FileList* listView() const { return static_cast( KListViewItem::listView() ); } + + ConversionOptions options; // the information we get from the options class for creating the item + TagData* tags; // we need to instruct the tagengine to read the tags from the file! + // and the user can change them! + QString fileName; // just the _name_ of the file + QString mimeType; // the mime type of the file + QString fileFormat; // just the _format_ of the file (for easier use) + QString url; // the original input file name string + bool converting; // is this item being converted at the moment? + bool local; // is this file a local one? + int track; // the number of the track, if it is on an audio cd + // if it is lower than 0, it isn't an audio cd track at all + QString device; // the device of the audio cd + bool ripping; // is this track currently being ripped? + + float time; // the duration of the track, used for the calculation of the progress bar + QString notify; // execute this command, when the file is converted +}; + +/** + * @short The file list + * @author Daniel Faust + * @version 0.3 + */ +class FileList : public KListView +{ + Q_OBJECT +public: + /** + * Constructor + * @param parent The parent widget + * @param name The name of the file list + */ + FileList( CDManager*, TagEngine*, Config*, Options*, Logger*, QWidget *parent = 0, const char* name = 0 ); + + /** + * Destructor + */ + virtual ~FileList(); + + FileListItem* firstChild() const { return static_cast( KListView::firstChild() ); } + FileListItem* lastItem() const { return static_cast( KListView::lastItem() ); } + + int columnByName( const QString& name ); + void updateItem( FileListItem* item ); + + bool queueEnabled() { return queue; } + + void setNotify( const QString& cmd ) { notify = cmd; } + +protected: + virtual bool acceptDrag( QDropEvent *e ) const; + +private: + /** Lists all file in a directory and adds them to the file list, if @p fast is false. The number of listed files is returned */ + int listDir( const QString& directory, QStringList filter, bool recursive = true, bool fast = false, int count = 0 ); + + /** A progressbar, that is shown, when a directory is added recursive */ + KProgress* pScanStatus; + + void convertNextItem(); + + void viewportPaintEvent( QPaintEvent* ); + void viewportResizeEvent( QResizeEvent* ); + + void debug(); // NOTE DEBUG + QString debug_params( ConversionOptions conversionOptions, FormatItem* formatItem ); // NOTE DEBUG + + QSimpleRichText* bubble; + + /** The context menu for editing or starting the files */ + KPopupMenu* contextMenu; + + KActionCollection* actionCollection; + KAction* edit; + KAction* start; + KAction* stop; + KAction* remove; + KAction* paste; + + CDManager* cdManager; + TagEngine* tagEngine; + OptionsEditor* optionsEditor; + + Options* options; + Config* config; + Logger* logger; + + QValueList selectedFiles; + + bool queue; + + /** + * A command that should be executed after the conversion of a file is complete + * %i will be replaced by the input file path + * %o " " " " " output " " + */ + QString notify; + +private slots: + /* + * The user clicked somewhere into the list view (e.g. the link in the bubble) + */ +// void clickedSomewhere( QListViewItem*, const QPoint&, int ); + + /** + * We'll recive a signal, when we should show the context menu + * @p item The item, that's context menu should be shown + * @p point The position of the click (start position of the context menu) + */ + void showContextMenu( QListViewItem* item, const QPoint& point, int ); + + /** + * Remove selected items from the file list + */ + void removeSelectedItems(); + + /** + * Add selected items to the conversion list + */ + void convertSelectedItems(); + + /** + * Stop the conversion of all selected items + */ + void stopSelectedItems(); + + void columnResizeEvent( int, int, int ); + void slotDropped( QDropEvent*, QListViewItem*, QListViewItem* ); // NOTE rename? + +public slots: + void addFiles( QStringList, FileListItem* after = 0, bool enabled = false ); // NOTE const QStringList& ? + void addDir( const QString&, const QStringList& filter = "", bool recursive = true ); + void addTracks( const QString& device, QValueList ); + void addDisc( const QString& device ); + /** + * The conversion of an item has finished and the state is reported ( 0 = ok, -1 = error, 1 = aborted ) + */ + void itemFinished( FileListItem*, int ); + void rippingFinished( const QString& device ); + void showOptionsEditorDialog(); + void selectPreviousItem(); + void selectNextItem(); + void itemsSelected(); + //void moveOptionsEditor( int x, int y ); + void startConversion(); + void stopConversion(); + void continueConversion(); + void killConversion(); + + void load( bool autosave = false ); + void save( bool autosave = false ); + +signals: + void convertItem( FileListItem* ); + void stopItem( FileListItem* ); + void editItems( QValueList ); + void setPreviousItemEnabled( bool ); + void setNextItemEnabled( bool ); + //void moveEditor( int x, int y ); + void fileCountChanged( int ); + void startedConversion(); + void stopClicked(); + void continueClicked(); + void stoppedConversion(); + + void increaseTime( float ); + void decreaseTime( float ); + //void countTime( float ); + //void setTime( float ); + void finished( float ); +}; + +#endif // FILELIST_H diff --git a/src/hi16-app-soundkonverter.png b/src/hi16-app-soundkonverter.png new file mode 100755 index 0000000..2350f15 Binary files /dev/null and b/src/hi16-app-soundkonverter.png differ diff --git a/src/hi16-app-soundkonverter_replaygain.png b/src/hi16-app-soundkonverter_replaygain.png new file mode 100755 index 0000000..bd2821e Binary files /dev/null and b/src/hi16-app-soundkonverter_replaygain.png differ diff --git a/src/hi22-app-soundkonverter.png b/src/hi22-app-soundkonverter.png new file mode 100755 index 0000000..3896959 Binary files /dev/null and b/src/hi22-app-soundkonverter.png differ diff --git a/src/hi22-app-soundkonverter_replaygain.png b/src/hi22-app-soundkonverter_replaygain.png new file mode 100755 index 0000000..b76cf9c Binary files /dev/null and b/src/hi22-app-soundkonverter_replaygain.png differ diff --git a/src/hi32-app-soundkonverter.png b/src/hi32-app-soundkonverter.png new file mode 100755 index 0000000..fa39d12 Binary files /dev/null and b/src/hi32-app-soundkonverter.png differ diff --git a/src/hi32-app-soundkonverter_replaygain.png b/src/hi32-app-soundkonverter_replaygain.png new file mode 100755 index 0000000..ce3f56e Binary files /dev/null and b/src/hi32-app-soundkonverter_replaygain.png differ diff --git a/src/hi48-app-soundkonverter.png b/src/hi48-app-soundkonverter.png new file mode 100755 index 0000000..475589a Binary files /dev/null and b/src/hi48-app-soundkonverter.png differ diff --git a/src/hi48-app-soundkonverter_replaygain.png b/src/hi48-app-soundkonverter_replaygain.png new file mode 100755 index 0000000..0b0cc5a Binary files /dev/null and b/src/hi48-app-soundkonverter_replaygain.png differ diff --git a/src/hi64-app-soundkonverter.png b/src/hi64-app-soundkonverter.png new file mode 100755 index 0000000..abf4714 Binary files /dev/null and b/src/hi64-app-soundkonverter.png differ diff --git a/src/hi64-app-soundkonverter_replaygain.png b/src/hi64-app-soundkonverter_replaygain.png new file mode 100755 index 0000000..29834c4 Binary files /dev/null and b/src/hi64-app-soundkonverter_replaygain.png differ diff --git a/src/logger.cpp b/src/logger.cpp new file mode 100755 index 0000000..7b19fff --- /dev/null +++ b/src/logger.cpp @@ -0,0 +1,149 @@ + +#include "logger.h" + +#include +#include + +#include +#include + + +LoggerItem::LoggerItem() +{} + +LoggerItem::~LoggerItem() +{} + + +Logger::Logger() +{ + QValueList::Iterator item = processes.append( new LoggerItem() ); + (*item)->filename = "soundKonverter"; + (*item)->id = 1000; + (*item)->completed = true; + (*item)->state = 1; + (*item)->file.setName( locateLocal("data",QString("soundkonverter/log/%1.log").arg((*item)->id)) ); + // TODO error handling + (*item)->file.open( IO_WriteOnly ); + (*item)->textStream.setDevice( &((*item)->file) ); + srand( (unsigned)time(NULL) ); +} + +Logger::~Logger() +{} + +void Logger::cleanUp() +{ + for( QValueList::Iterator it = processes.begin(); it != processes.end(); ++it ) { + if( (*it)->id != 1000 ) { + emit removedProcess( (*it)->id ); + (*it)->file.close(); + (*it)->file.remove(); + delete *it; + } + } + processes.clear(); +} + +int Logger::registerProcess( const QString& filename ) +{ + // NOTE ok, it works now, but why prepend() and not append()? + QValueList::Iterator item = processes.append( new LoggerItem() ); + (*item)->filename = filename; + (*item)->id = getNewID(); + (*item)->completed = false; + (*item)->file.setName( locateLocal("data",QString("soundkonverter/log/%1.log").arg((*item)->id)) ); + // TODO error handling + (*item)->file.open( IO_WriteOnly ); + (*item)->textStream.setDevice( &((*item)->file) ); + + emit updateProcess( (*item)->id ); + + return (*item)->id; +} + +void Logger::log( int id, const QString& data ) +{ + for( QValueList::Iterator it = processes.begin(); it != processes.end(); ++it ) { + if( (*it)->id == id ) { + (*it)->data.append( data ); + if( (*it)->data.count() > 100000 ) (*it)->data.erase( (*it)->data.at(0) ); + (*it)->textStream << data; + (*it)->textStream << "\n"; + (*it)->file.flush(); + if( id == 1000 ) emit updateProcess( 1000 ); + return; + } + } +} + +int Logger::getNewID() +{ + bool ok; + int id; + + do { + id = rand(); + ok = true; + + for( QValueList::Iterator it = processes.begin(); it != processes.end(); ++it ) { + if( (*it)->id == id ) ok = false; + } + + } while( !ok ); + + return id; +} + +LoggerItem* Logger::getLog( int id ) +{ + for( QValueList::Iterator it = processes.begin(); it != processes.end(); ++it ) { + if( (*it)->id == id ) return *it; + } + + return 0; +} + +QValueList Logger::getLogs() +{ +/* QValueList items; + + for( QValueList::Iterator it = processes.begin(); it != processes.end(); ++it ) { + if( (*it)->completed ) items.append( *it ); + } + + return items;*/ + return processes; +} + +void Logger::processCompleted( int id, int state ) +{ + LoggerItem* item = 0; + QTime time = QTime::currentTime(); + bool remove = false; + + for( QValueList::Iterator it = processes.begin(); it != processes.end(); ++it ) { + // TODO test + if( time >= (*it)->time && (*it)->completed && (*it)->state == 0 ) { + time = (*it)->time; + item = *it; + remove = true; + } + else if( (*it)->id == id ) { + (*it)->state = state; + (*it)->completed = true; + (*it)->time = (*it)->time.currentTime(); + (*it)->textStream << i18n("Finished logging"); + (*it)->file.close(); + emit updateProcess( id ); + } + } + + if( remove && processes.count() > 11 ) { + emit removedProcess( item->id ); + item->file.remove(); + processes.remove( item ); + delete item; + } +} + diff --git a/src/logger.h b/src/logger.h new file mode 100755 index 0000000..c8d0076 --- /dev/null +++ b/src/logger.h @@ -0,0 +1,100 @@ + + +#ifndef LOGGER_H +#define LOGGER_H + +#include +#include +#include +#include +#include + + +/** + * @short An item for every process that is logged + * @author Daniel Faust + * @version 0.3 + */ +class LoggerItem +{ +public: + /** + * Constructor + */ + LoggerItem(); + + /** + * Destructor + */ + virtual ~LoggerItem(); + + QString filename; + int id; + QStringList data; + bool completed; + int state; // 0 = ok, -1 = failed, 1 = other (soundKonverter) + QTime time; + QFile file; + QTextStream textStream; + +}; + + +/** + * @short All data about the processes are collected here + * @author Daniel Faust + * @version 0.3 + */ +class Logger : public QObject +{ + Q_OBJECT +public: + /** + * Constructor + */ + Logger(); + + /** + * Destructor + */ + virtual ~Logger(); + + void cleanUp(); + + /** + * Creates a new logger item and returns the id of it, @p filename is added to the new logger item + */ + int registerProcess( const QString& filename ); + + /** + * Adds the string @p data to the data of the logger item with id @p id + */ + void log( int id, const QString& data ); + + /** + * Returns the logger item with id @p id + */ + LoggerItem* getLog( int id ); + + /** + * Returns a list of all logger items + */ + QValueList getLogs(); + +private: + /** the list of all logger items */ + QValueList processes; + + /** returns an unused random id */ + int getNewID(); + +public slots: + void processCompleted( int id, int state ); + +signals: + void removedProcess( int id ); + void updateProcess( int id ); + +}; + +#endif // LOGGER_H diff --git a/src/logviewer.cpp b/src/logviewer.cpp new file mode 100755 index 0000000..c76f7e6 --- /dev/null +++ b/src/logviewer.cpp @@ -0,0 +1,204 @@ + +#include "logviewer.h" +#include "logger.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +//#include + +// ### soundkonverter 0.4: make sub items for the output + +LogViewerItem::LogViewerItem( KListView* parent, LogViewerItem* after, QString label1 ) + : KListViewItem( parent, after, label1 ) +{ + converting = false; +} + +LogViewerItem::LogViewerItem( LogViewerItem* parent, LogViewerItem* after, QString label1 ) + : KListViewItem( parent, after, label1 ) +{ + converting = false; +} + +LogViewerItem::~LogViewerItem() +{} + +void LogViewerItem::paintCell( QPainter *p, const QColorGroup &cg, int column, int width, int alignment ) +{ + // NOTE calculate the red color + + QColorGroup _cg( cg ); + QColor c; + + if( isSelected() && converting ) { + _cg.setColor( QColorGroup::Highlight, QColor( 215, 62, 62 ) ); + QListViewItem::paintCell( p, _cg, column, width, alignment ); + return; + } + else if( converting && column != listView()->sortColumn() ) { + _cg.setColor( QColorGroup::Base, QColor( 255, 234, 234 ) ); + QListViewItem::paintCell( p, _cg, column, width, alignment ); + return; + } + else if( converting && column == listView()->sortColumn() ) { + _cg.setColor( QColorGroup::Base, QColor( 247, 227, 227 ) ); + QListViewItem::paintCell( p, _cg, column, width, alignment ); + return; + } + + KListViewItem::paintCell( p, _cg, column, width, alignment ); +} + + +LogViewerList::LogViewerList( QWidget* parent, const char* name ) + : KListView( parent, name ) +{} + +LogViewerList::~LogViewerList() +{} + + +LogViewer::LogViewer( Logger* _logger, QWidget *parent, const char *name, bool modal, WFlags f ) + : KDialog( parent, name, modal, f ) +{ + logger = _logger; + connect( logger, SIGNAL(removedProcess(int)), + this, SLOT(processRemoved(int)) + ); + connect( logger, SIGNAL(updateProcess(int)), + this, SLOT(updateProcess(int)) + ); + + // create an icon loader object for loading icons + KIconLoader* iconLoader = new KIconLoader(); + + setCaption( i18n("Log Viewer") ); + resize( 600, 400 ); + setIcon( iconLoader->loadIcon("view_text",KIcon::Small) ); + + QGridLayout *grid = new QGridLayout( this, 4, 1, 11, 6 ); + + lLogs = new LogViewerList( this, "lLogs" ); + lLogs->addColumn( i18n("Job/File") ); + //lLogs->setSelectionMode( QListView::Extended ); + //lLogs->setAllColumnsShowFocus( true ); + lLogs->setResizeMode( QListView::LastColumn ); + lLogs->setSorting( -1 ); + lLogs->setRootIsDecorated( true ); + lLogs->header()->setClickEnabled( false ); + grid->addWidget( lLogs, 0, 0 ); + + QHBoxLayout *buttonBox = new QHBoxLayout(); + grid->addLayout( buttonBox, 3, 0 ); + + pReload = new KPushButton(iconLoader->loadIcon("reload",KIcon::Small), i18n("Reload"), this, "pReload" ); + buttonBox->addWidget( pReload ); + connect( pReload, SIGNAL(clicked()), + this, SLOT(refillLogs()) + ); + + buttonBox->addStretch(); + + pOk = new KPushButton(iconLoader->loadIcon("exit",KIcon::Small), i18n("Close"), this, "pOk" ); + pOk->setFocus(); + buttonBox->addWidget( pOk ); + connect( pOk, SIGNAL(clicked()), + this, SLOT(accept()) + ); + + // delete the icon loader object + delete iconLoader; + + refillLogs(); +} + +LogViewer::~LogViewer() +{} + +void LogViewer::refillLogs() +{ + LogViewerItem *parent = 0, *last = 0; + + lLogs->clear(); + QValueList logs = logger->getLogs(); + for( QValueList::Iterator a = logs.begin(); a != logs.end(); ++a ) { + parent = new LogViewerItem( lLogs, parent, KURL::decode_string((*a)->filename).replace("%2f","/").replace("%%","%") + " - " + QString::number((*a)->id) ); + parent->converting = !(*a)->completed; + //parent->setOpen( true ); + last = 0; + for( QStringList::Iterator b = (*a)->data.begin(); b != (*a)->data.end(); ++b ) { + last = new LogViewerItem( parent, last, *b ); + last->setMultiLinesEnabled( true ); + last->converting = !(*a)->completed; + } + } +} + +void LogViewer::processRemoved( int id ) +{ + LoggerItem* item = logger->getLog( id ); // this is ok, because the item still exists. + // it will be deleted after is function is completed + + QListViewItem* it = lLogs->firstChild(); + + while( it != 0 ) { + if( it->text(0) == KURL::decode_string(item->filename).replace("%2f","/").replace("%%","%") + " - " + QString::number(item->id) ) { + delete it; + return; + } + it = it->nextSibling(); + } +} + +void LogViewer::updateProcess( int id ) +{ + LoggerItem* item = logger->getLog( id ); + + LogViewerItem* it = lLogs->firstChild(); + + LogViewerItem *lastItem = 0, *oldItem = 0; + + while( it != 0 ) { + if( it->text(0) == KURL::decode_string(item->filename).replace("%2f","/").replace("%%","%") + " - " + QString::number(item->id) ) { + LogViewerItem *a = it->firstChild(), *b; + while( a != 0 ) { + b = a->nextSibling(); + delete a; + a = b; + } + it->converting = !item->completed; + LogViewerItem* last = 0; + for( QStringList::Iterator b = item->data.begin(); b != item->data.end(); ++b ) { + last = new LogViewerItem( (LogViewerItem*)it, last, *b ); + last->setMultiLinesEnabled( true ); + } + return; + } + it = it->nextSibling(); + } + + LogViewerItem *parent = 0; + + // get the last list view item + for( QListViewItem* it = lLogs->firstChild(); it != 0; it = it->nextSibling() ) { + lastItem = (LogViewerItem*)it; + } + + parent = new LogViewerItem( lLogs, lastItem, KURL::decode_string(item->filename).replace("%2f","/").replace("%%","%") + " - " + QString::number(item->id) ); + parent->converting = !item->completed; + LogViewerItem* last = 0; + for( QStringList::Iterator b = item->data.begin(); b != item->data.end(); ++b ) { + last = new LogViewerItem( parent, last, *b ); + last->setMultiLinesEnabled( true ); + } +} + + diff --git a/src/logviewer.h b/src/logviewer.h new file mode 100755 index 0000000..be3a8a3 --- /dev/null +++ b/src/logviewer.h @@ -0,0 +1,111 @@ + + +#ifndef LOGVIEWER_H +#define LOGVIEWER_H + +#include +#include + + +class KPushButton; +class Logger; + +/** + * @short The items for the log viewer list + * @author Daniel Faust + * @version 0.3 + */ +class LogViewerItem : public KListViewItem +{ +public: + /** + * Constructor + * @param parent The parent list view + * @param after The item, the new item should be placed after + * @param label1 The text for the first column + */ + LogViewerItem( KListView* parent, LogViewerItem* after, QString label1 ); + + /** + * Constructor + * @param parent The parent list view item + * @param after The item, the new item should be placed after + * @param label1 The text for the first column + */ + LogViewerItem( LogViewerItem* parent, LogViewerItem* after, QString label1 ); + + /** + * Destructor + */ + virtual ~LogViewerItem(); + + virtual void paintCell( QPainter* p, const QColorGroup& cg, int column, int width, int alignment ); + + LogViewerItem* nextSibling() const { return static_cast( KListViewItem::nextSibling() ); } + LogViewerItem* firstChild() const { return static_cast( KListViewItem::firstChild() ); } + + bool converting; +}; + + +/** + * @short The log viewer list + * @author Daniel Faust + * @version 0.3 + */ +class LogViewerList : public KListView +{ + Q_OBJECT +public: + /** + * Constructor + * @param parent The parent widget + * @param name The name of the file list + */ + LogViewerList( QWidget * parent = 0, const char* name = 0 ); + + /** + * Destructor + */ + virtual ~LogViewerList(); + + LogViewerItem* firstChild() const { return static_cast( KListView::firstChild() ); } +}; + + +/** + * @short Shows the logs that are collected by the logger + * @author Daniel Faust + * @version 0.3 + */ +class LogViewer : public KDialog +{ + Q_OBJECT +public: + /** + * Default Constructor + */ + LogViewer( Logger* _logger, QWidget* parent=0, const char* name = 0, bool modal = true, WFlags f = 0 ); + + /** + * Default Destructor + */ + virtual ~LogViewer(); + +private: + Logger* logger; + LogViewerList* lLogs; + KPushButton* pOk; + KPushButton* pReload; + +private slots: + void refillLogs(); + void updateProcess( int id ); + +public slots: + /** get notification when a job has been removed */ + void processRemoved( int id ); + +}; + +#endif // LOGVIEWER_H diff --git a/src/main.cpp b/src/main.cpp new file mode 100755 index 0000000..7b42a3c --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,75 @@ + + +#include "soundkonverterapp.h" + +#include "tplugins.h" + +#include +#include +#include + +static const char description[] = + I18N_NOOP("soundKonverter is a frontend to various audio converters, Replay Gain tools and CD rippers.\n\nPlease file bug reports at https://bugs.launchpad.net/ubuntu/+source/soundkonverter\nor simply send me a mail to hessijames@gmail.com"); + +static const char version[] = "0.3.8"; + +static KCmdLineOptions options[] = +{ + { "replaygain", I18N_NOOP("Open the Replay Gain tool an add all given files"), 0 }, +// { "repair", I18N_NOOP("Open the repair files tool an add all given files"), 0 }, + { "rip ", I18N_NOOP("List all tracks on the cd drive , 'auto' will search for a cd"), 0 }, + { "profile ", I18N_NOOP("Add all files using the given profile"), 0 }, + { "format ", I18N_NOOP("Add all files using the given format"), 0 }, + { "output ", I18N_NOOP("Output all files to "), 0 }, + { "invisible", I18N_NOOP("Start soundKonverter invisible"), 0 }, + { "autoclose", I18N_NOOP("Close soundKonverter after all files are converted (enabled when using '--invisible')"), 0 }, + { "command ", I18N_NOOP("Execute after each file has been converted"), 0 }, + { "+[files]", I18N_NOOP("Audio file(s) to append to the file list"), 0 }, + KCmdLineLastOption +}; + +int main(int argc, char **argv) +{ + KAboutData about("soundkonverter", I18N_NOOP("soundKonverter"), version, description, + KAboutData::License_GPL, "(C) 2008 Daniel Faust", 0, 0, "hessijames@gmail.com"); + about.addAuthor( "Daniel Faust", 0, "hessijames@gmail.com" ); + about.addCredit( "David Vignoni", "Nuvola icon theme", 0, "http://www.icon-king.com" ); + about.addCredit( "Scott Wheeler", "TagLib", "wheeler@kde.org", "http://ktown.kde.org/~wheeler" ); + about.addCredit( "Amarok developers", "Amarok", 0, "http://amarok.kde.org" ); + about.addCredit( "Kaffeine developers", "Kaffeine", 0, "http://kaffeine.sourceforge.net" ); + about.addCredit( "All programmers of audioconverters", "Backends" ); + KCmdLineArgs::init(argc, argv, &about); + KCmdLineArgs::addCmdLineOptions( options ); + + soundKonverterApp::addCmdLineOptions(); + if( !soundKonverterApp::start() ) { + return 0; + } + + soundKonverterApp app; + + registerTaglibPlugins(); + + // mainWin has WDestructiveClose flag by default, so it will delete itself. + return app.exec(); +} + +/* +methods and files to update: +outputdirectory.cpp: vfatPath( const QString& path ) +metadata/ +cddb.cpp, cddb.h +cdmanager.cpp, cdmanager.h + + +audio/x-musepack;application/x-musepack;audio/musepack;application/musepack; +application/x-ape;audio/ape;audio/x-ape; +audio/x-mp3;application/x-id3;audio/mpeg;audio/x-mpeg;audio/x-mpeg-3;audio/mpeg3;audio/mp3;audio/x-mp3;application/x-id3;audio/mpeg;audio/x-mpeg;audio/x-mpeg-3;audio/mpeg3;audio/mp3; +audio/mp4;audio/x-m4a;audio/x-m4a; +audio/mpc;audio/x-mpc;audio/mp;audio/x-mp;audio/mpc;audio/x-mpc;audio/mp;audio/x-mp; +application/ogg;application/x-ogg;application/x-vorbis+ogg;audio/x-vorbis+ogg;audio/vorbis;audio/x-vorbis;audio/ogg;audio/x-ogg;application/ogg;application/x-ogg;audio/vorbis;audio/x-vorbis;audio/ogg;audio/x-ogg; +audio/x-flac;application/x-flac;audio/flac;audio/x-flac;application/x-flac;audio/flac; +audio/x-s3m;audio/x-mod;audio/x-xm;audio/x-it;audio/x-s3m;audio/x-mod;audio/x-xm;audio/x-it + +*/ + diff --git a/src/metadata/Makefile.am b/src/metadata/Makefile.am new file mode 100644 index 0000000..8e7209f --- /dev/null +++ b/src/metadata/Makefile.am @@ -0,0 +1,37 @@ +if with_mp4v2 +MP4_SUBDIR = mp4 +MP4_LDADD = mp4/libtagmp4.la +else +MP4_SUBDIR = m4a +MP4_LDADD = m4a/libtagm4a.la +endif + +SUBDIRS = speex wavpack trueaudio asf audible rmff $(MP4_SUBDIR) aac wav ape optimfrog + + +INCLUDES = $(all_includes) $(taglib_includes) +METASOURCES = AUTO +libmetadata_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libmetadata.la + +libmetadata_la_SOURCES = \ + tplugins.cpp \ + tagengine.cpp + +noinst_HEADERS = \ + tplugins.h \ + tagengine.h + +libmetadata_la_LIBADD = \ + speex/libtagspeex.la \ + trueaudio/libtagtrueaudio.la \ + wavpack/libtagwavpack.la \ + asf/libtagasf.la \ + wav/libtagwav.la \ + rmff/libtagrealmedia.la \ + $(MP4_LDADD) \ + $(taglib_libs) \ + aac/libtagaac.la \ + audible/libtagaudible.la \ + ape/libtagmonkeysaudio.la \ + optimfrog/libtagoptimfrog.la diff --git a/src/metadata/aac/Makefile.am b/src/metadata/aac/Makefile.am new file mode 100644 index 0000000..b6b0f43 --- /dev/null +++ b/src/metadata/aac/Makefile.am @@ -0,0 +1,12 @@ +SUBDIRS = +METASOURCES = AUTO +INCLUDES = $(all_includes) $(taglib_includes) + +libtagaac_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libtagaac.la + +libtagaac_la_SOURCES = \ + aacfiletyperesolver.cpp + +noinst_HEADERS = \ + aacfiletyperesolver.h diff --git a/src/metadata/aac/aacfiletyperesolver.cpp b/src/metadata/aac/aacfiletyperesolver.cpp new file mode 100644 index 0000000..fcc2a86 --- /dev/null +++ b/src/metadata/aac/aacfiletyperesolver.cpp @@ -0,0 +1,38 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : aumuell@reserv.at + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "aacfiletyperesolver.h" +#include + +#include + +TagLib::File *AACFileTypeResolver::createFile(const char *fileName, + bool readProperties, + TagLib::AudioProperties::ReadStyle propertiesStyle) const +{ + const char *ext = strrchr(fileName, '.'); + if(ext && !strcasecmp(ext, ".aac")) + { + return new TagLib::MPEG::File(fileName, readProperties, propertiesStyle); + } + + return 0; +} diff --git a/src/metadata/aac/aacfiletyperesolver.h b/src/metadata/aac/aacfiletyperesolver.h new file mode 100644 index 0000000..6c33b71 --- /dev/null +++ b/src/metadata/aac/aacfiletyperesolver.h @@ -0,0 +1,36 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : aumuell@reserv.at + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_AACFILETYPERESOLVER_H +#define TAGLIB_AACFILETYPERESOLVER_H + +#include +#include + + +class AACFileTypeResolver : public TagLib::FileRef::FileTypeResolver +{ + TagLib::File *createFile(const char *fileName, + bool readAudioProperties, + TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; +}; + +#endif diff --git a/src/metadata/ape/Makefile.am b/src/metadata/ape/Makefile.am new file mode 100755 index 0000000..156cf91 --- /dev/null +++ b/src/metadata/ape/Makefile.am @@ -0,0 +1,6 @@ +INCLUDES = $(all_includes) $(taglib_includes) +METASOURCES = AUTO +libtagmonkeysaudio_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libtagmonkeysaudio.la +noinst_HEADERS = taglib_monkeysaudiofiletyperesolver.h +libtagmonkeysaudio_la_SOURCES = taglib_monkeysaudiofiletyperesolver.cpp diff --git a/src/metadata/ape/taglib_monkeysaudiofiletyperesolver.cpp b/src/metadata/ape/taglib_monkeysaudiofiletyperesolver.cpp new file mode 100755 index 0000000..fea0344 --- /dev/null +++ b/src/metadata/ape/taglib_monkeysaudiofiletyperesolver.cpp @@ -0,0 +1,21 @@ +// (c) 2006 Martin Aumueller +// modified 2006 Daniel Faust +// See COPYING file for licensing information + +#include "taglib_monkeysaudiofiletyperesolver.h" +#include + +#include + +TagLib::File *MonkeysAudioFileTypeResolver::createFile(const char *fileName, + bool readProperties, + TagLib::AudioProperties::ReadStyle propertiesStyle) const +{ + const char *ext = strrchr(fileName, '.'); + if(ext && (!strcasecmp(ext, ".ape") || !strcasecmp(ext, ".mac"))) + { + return new TagLib::MPC::File(fileName, readProperties, propertiesStyle); + } + + return 0; +} diff --git a/src/metadata/ape/taglib_monkeysaudiofiletyperesolver.h b/src/metadata/ape/taglib_monkeysaudiofiletyperesolver.h new file mode 100755 index 0000000..4af4a7b --- /dev/null +++ b/src/metadata/ape/taglib_monkeysaudiofiletyperesolver.h @@ -0,0 +1,19 @@ +// (c) 2006 Martin Aumueller +// modified 2006 Daniel Faust +// See COPYING file for licensing information + +#ifndef TAGLIB_MONKEYSAUDIOFILETYPERESOLVER_H +#define TAGLIB_MONKEYSAUDIOFILETYPERESOLVER_H + +#include +#include + + +class MonkeysAudioFileTypeResolver : public TagLib::FileRef::FileTypeResolver +{ + TagLib::File *createFile(const char *fileName, + bool readAudioProperties, + TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; +}; + +#endif diff --git a/src/metadata/asf/Makefile.am b/src/metadata/asf/Makefile.am new file mode 100644 index 0000000..63fa0e1 --- /dev/null +++ b/src/metadata/asf/Makefile.am @@ -0,0 +1,20 @@ +SUBDIRS = + +INCLUDES = $(all_includes) $(taglib_includes) +METASOURCES = AUTO +libtagasf_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libtagasf.la + +libtagasf_la_SOURCES = \ + asfattribute.cpp \ + asfproperties.cpp \ + asftag.cpp \ + asffile.cpp \ + taglib_asffiletyperesolver.cpp + +noinst_HEADERS = \ + asfattribute.h \ + asfproperties.h \ + asftag.h \ + asffile.h \ + taglib_asffiletyperesolver.h diff --git a/src/metadata/asf/asfattribute.cpp b/src/metadata/asf/asfattribute.cpp new file mode 100644 index 0000000..bfe81c5 --- /dev/null +++ b/src/metadata/asf/asfattribute.cpp @@ -0,0 +1,304 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * + * USA * + ***************************************************************************/ + +#include +#include "asfattribute.h" +#include "asffile.h" + +using namespace TagLib; + +class ASF::Attribute::AttributePrivate : public RefCounter +{ +public: + AttributePrivate() + : stream(0), + language(0) {} + AttributeTypes type; + String stringValue; + ByteVector byteVectorValue; + union { + unsigned int intValue; + unsigned short shortValue; + unsigned long long longLongValue; + bool boolValue; + }; + int stream; + int language; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +ASF::Attribute::Attribute() +{ + d = new AttributePrivate; + d->type = UnicodeType; +} + +ASF::Attribute::Attribute(const ASF::Attribute &other) + : d(other.d) +{ + d->ref(); +} + +ASF::Attribute & +ASF::Attribute::operator=(const ASF::Attribute &other) +{ + if(d->deref()) + delete d; + d = other.d; + d->ref(); + return *this; +} + +ASF::Attribute::~Attribute() +{ + if(d->deref()) + delete d; +} + +ASF::Attribute::Attribute(const String &value) +{ + d = new AttributePrivate; + d->type = UnicodeType; + d->stringValue = value; +} + +ASF::Attribute::Attribute(const ByteVector &value) +{ + d = new AttributePrivate; + d->type = BytesType; + d->byteVectorValue = value; +} + +ASF::Attribute::Attribute(unsigned int value) +{ + d = new AttributePrivate; + d->type = DWordType; + d->intValue = value; +} + +ASF::Attribute::Attribute(unsigned long long value) +{ + d = new AttributePrivate; + d->type = QWordType; + d->longLongValue = value; +} + +ASF::Attribute::Attribute(unsigned short value) +{ + d = new AttributePrivate; + d->type = WordType; + d->shortValue = value; +} + +ASF::Attribute::Attribute(bool value) +{ + d = new AttributePrivate; + d->type = BoolType; + d->boolValue = value; +} + +ASF::Attribute::AttributeTypes +ASF::Attribute::type() const +{ + return d->type; +} + +String +ASF::Attribute::toString() const +{ + return d->stringValue; +} + +ByteVector +ASF::Attribute::toByteVector() const +{ + return d->byteVectorValue; +} + +unsigned short +ASF::Attribute::toBool() const +{ + return d->shortValue; +} + +unsigned short +ASF::Attribute::toUShort() const +{ + return d->shortValue; +} + +unsigned int +ASF::Attribute::toUInt() const +{ + return d->intValue; +} + +unsigned long long +ASF::Attribute::toULongLong() const +{ + return d->longLongValue; +} + +String +ASF::Attribute::parse(ASF::File &f, int kind) +{ + int size, nameLength; + String name; + + // extended content descriptor + if(kind == 0) { + nameLength = f.readWORD(); + name = f.readString(nameLength); + d->type = ASF::Attribute::AttributeTypes(f.readWORD()); + size = f.readWORD(); + } + // metadata & metadata library + else { + int temp = f.readWORD(); + // metadata library + if(kind == 2) { + d->language = temp; + } + d->stream = f.readWORD(); + nameLength = f.readWORD(); + d->type = ASF::Attribute::AttributeTypes(f.readWORD()); + size = f.readDWORD(); + name = f.readString(nameLength); + } + + switch(d->type) { + case WordType: + d->shortValue = f.readWORD(); + break; + + case BoolType: + if(kind == 0) { + d->boolValue = f.readDWORD() == 1; + } + else { + d->boolValue = f.readWORD() == 1; + } + break; + + case DWordType: + d->intValue = f.readDWORD(); + break; + + case QWordType: + d->longLongValue = f.readQWORD(); + break; + + case UnicodeType: + d->stringValue = f.readString(size); + break; + + case BytesType: + case GuidType: + d->byteVectorValue = f.readBlock(size); + break; + } + + return name; +} + +ByteVector +ASF::Attribute::render(const String &name, int kind) const +{ + ByteVector data; + + switch (d->type) { + case WordType: + data.append(ByteVector::fromShort(d->shortValue, false)); + break; + + case BoolType: + if(kind == 0) { + data.append(ByteVector::fromUInt(d->boolValue ? 1 : 0, false)); + } + else { + data.append(ByteVector::fromShort(d->boolValue ? 1 : 0, false)); + } + break; + + case DWordType: + data.append(ByteVector::fromUInt(d->intValue, false)); + break; + + case QWordType: + data.append(ByteVector::fromLongLong(d->longLongValue, false)); + break; + + case UnicodeType: + data.append(File::renderString(d->stringValue)); + break; + + case BytesType: + case GuidType: + data.append(d->byteVectorValue); + break; + } + + if(kind == 0) { + data = File::renderString(name, true) + + ByteVector::fromShort((int)d->type, false) + + ByteVector::fromShort(data.size(), false) + + data; + } + else { + ByteVector nameData = File::renderString(name); + data = ByteVector::fromShort(kind == 2 ? d->language : 0, false) + + ByteVector::fromShort(d->stream, false) + + ByteVector::fromShort(nameData.size(), false) + + ByteVector::fromShort((int)d->type, false) + + ByteVector::fromUInt(data.size(), false) + + nameData + + data; + } + + return data; +} + +int +ASF::Attribute::language() const +{ + return d->language; +} + +void +ASF::Attribute::setLanguage(int value) +{ + d->language = value; +} + +int +ASF::Attribute::stream() const +{ + return d->stream; +} + +void +ASF::Attribute::setStream(int value) +{ + d->stream = value; +} diff --git a/src/metadata/asf/asfattribute.h b/src/metadata/asf/asfattribute.h new file mode 100644 index 0000000..9a8e3c9 --- /dev/null +++ b/src/metadata/asf/asfattribute.h @@ -0,0 +1,176 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * + * USA * + ***************************************************************************/ + +#ifndef TAGLIB_ASFATTRIBUTE_H +#define TAGLIB_ASFATTRIBUTE_H + +#include +#include + +namespace TagLib +{ + + namespace ASF + { + + class File; + + class Attribute + { + public: + + /*! + * Enum of types an Attribute can have. + */ + enum AttributeTypes { + UnicodeType = 0, + BytesType = 1, + BoolType = 2, + DWordType = 3, + QWordType = 4, + WordType = 5, + GuidType = 6 + }; + + /*! + * Constructs an empty attribute. + */ + Attribute(); + + /*! + * Constructs an attribute with \a key and a UnicodeType \a value. + */ + Attribute(const String &value); + + /*! + * Constructs an attribute with \a key and a BytesType \a value. + */ + Attribute(const ByteVector &value); + + /*! + * Constructs an attribute with \a key and a DWordType \a value. + */ + Attribute(unsigned int value); + + /*! + * Constructs an attribute with \a key and a QWordType \a value. + */ + Attribute(unsigned long long value); + + /*! + * Constructs an attribute with \a key and a WordType \a value. + */ + Attribute(unsigned short value); + + /*! + * Constructs an attribute with \a key and a BoolType \a value. + */ + Attribute(bool value); + + /*! + * Construct an attribute as a copy of \a other. + */ + Attribute(const Attribute &item); + + /*! + * Copies the contents of \a other into this item. + */ + ASF::Attribute &operator=(const Attribute &other); + + /*! + * Destroys the attribute. + */ + virtual ~Attribute(); + + /*! + * Returns type of the value. + */ + AttributeTypes type() const; + + /*! + * Returns the BoolType \a value. + */ + unsigned short toBool() const; + + /*! + * Returns the WordType \a value. + */ + unsigned short toUShort() const; + + /*! + * Returns the DWordType \a value. + */ + unsigned int toUInt() const; + + /*! + * Returns the QWordType \a value. + */ + unsigned long long toULongLong() const; + + /*! + * Returns the UnicodeType \a value. + */ + String toString() const; + + /*! + * Returns the BytesType \a value. + */ + ByteVector toByteVector() const; + + /*! + * Returns the language number, or 0 is no stream number was set. + */ + int language() const; + + /*! + * Sets the language number. + */ + void setLanguage(int value); + + /*! + * Returns the stream number, or 0 is no stream number was set. + */ + int stream() const; + + /*! + * Sets the stream number. + */ + void setStream(int value); + +#ifndef DO_NOT_DOCUMENT + /* THIS IS PRIVATE, DON'T TOUCH IT! */ + String parse(ASF::File &file, int kind = 0); +#endif + + private: + friend class File; + + ByteVector render(const String &name, int kind = 0) const; + + class AttributePrivate; + AttributePrivate *d; + }; + + } + +} + +#endif diff --git a/src/metadata/asf/asffile.cpp b/src/metadata/asf/asffile.cpp new file mode 100644 index 0000000..55a12cc --- /dev/null +++ b/src/metadata/asf/asffile.cpp @@ -0,0 +1,547 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * + * USA * + ***************************************************************************/ + +#include +#include +#include "asffile.h" +#include "asftag.h" +#include "asfproperties.h" + +using namespace TagLib; + +class ASF::File::FilePrivate +{ +public: + FilePrivate(): + size(0), + tag(0), + properties(0), + contentDescriptionObject(0), + extendedContentDescriptionObject(0), + headerExtensionObject(0), + metadataObject(0), + metadataLibraryObject(0) {} + unsigned long long size; + ASF::Tag *tag; + ASF::Properties *properties; + List objects; + ASF::File::ContentDescriptionObject *contentDescriptionObject; + ASF::File::ExtendedContentDescriptionObject *extendedContentDescriptionObject; + ASF::File::HeaderExtensionObject *headerExtensionObject; + ASF::File::MetadataObject *metadataObject; + ASF::File::MetadataLibraryObject *metadataLibraryObject; +}; + +static ByteVector headerGuid("\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C", 16); +static ByteVector filePropertiesGuid("\xA1\xDC\xAB\x8C\x47\xA9\xCF\x11\x8E\xE4\x00\xC0\x0C\x20\x53\x65", 16); +static ByteVector streamPropertiesGuid("\x91\x07\xDC\xB7\xB7\xA9\xCF\x11\x8E\xE6\x00\xC0\x0C\x20\x53\x65", 16); +static ByteVector contentDescriptionGuid("\x33\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C", 16); +static ByteVector extendedContentDescriptionGuid("\x40\xA4\xD0\xD2\x07\xE3\xD2\x11\x97\xF0\x00\xA0\xC9\x5E\xA8\x50", 16); +static ByteVector headerExtensionGuid("\xb5\x03\xbf_.\xa9\xcf\x11\x8e\xe3\x00\xc0\x0c Se", 16); +static ByteVector metadataGuid("\xEA\xCB\xF8\xC5\xAF[wH\204g\xAA\214D\xFAL\xCA", 16); +static ByteVector metadataLibraryGuid("\224\034#D\230\224\321I\241A\x1d\x13NEpT", 16); + +class ASF::File::BaseObject +{ +public: + ByteVector data; + virtual ~BaseObject() {} + virtual ByteVector guid() = 0; + virtual void parse(ASF::File *file, unsigned int size); + virtual ByteVector render(ASF::File *file); +}; + +class ASF::File::UnknownObject : public ASF::File::BaseObject +{ + ByteVector myGuid; +public: + UnknownObject(const ByteVector &guid); + ByteVector guid(); +}; + +class ASF::File::FilePropertiesObject : public ASF::File::BaseObject +{ +public: + ByteVector guid(); + void parse(ASF::File *file, uint size); +}; + +class ASF::File::StreamPropertiesObject : public ASF::File::BaseObject +{ +public: + ByteVector guid(); + void parse(ASF::File *file, uint size); +}; + +class ASF::File::ContentDescriptionObject : public ASF::File::BaseObject +{ +public: + ByteVector guid(); + void parse(ASF::File *file, uint size); + ByteVector render(ASF::File *file); +}; + +class ASF::File::ExtendedContentDescriptionObject : public ASF::File::BaseObject +{ +public: + ByteVectorList attributeData; + ByteVector guid(); + void parse(ASF::File *file, uint size); + ByteVector render(ASF::File *file); +}; + +class ASF::File::MetadataObject : public ASF::File::BaseObject +{ +public: + ByteVectorList attributeData; + ByteVector guid(); + void parse(ASF::File *file, uint size); + ByteVector render(ASF::File *file); +}; + +class ASF::File::MetadataLibraryObject : public ASF::File::BaseObject +{ +public: + ByteVectorList attributeData; + ByteVector guid(); + void parse(ASF::File *file, uint size); + ByteVector render(ASF::File *file); +}; + +class ASF::File::HeaderExtensionObject : public ASF::File::BaseObject +{ +public: + List objects; + ByteVector guid(); + void parse(ASF::File *file, uint size); + ByteVector render(ASF::File *file); +}; + +void +ASF::File::BaseObject::parse(ASF::File *file, unsigned int size) +{ + data = file->readBlock(size - 24); +} + +ByteVector +ASF::File::BaseObject::render(ASF::File * /*file*/) +{ + return guid() + ByteVector::fromLongLong(data.size() + 24, false) + data; +} + +ASF::File::UnknownObject::UnknownObject(const ByteVector &guid) : myGuid(guid) +{ +} + +ByteVector +ASF::File::UnknownObject::guid() +{ + return myGuid; +} + +ByteVector +ASF::File::FilePropertiesObject::guid() +{ + return filePropertiesGuid; +} + +void +ASF::File::FilePropertiesObject::parse(ASF::File *file, uint size) +{ + BaseObject::parse(file, size); + file->d->properties->setLength((int)(data.mid(40, 8).toLongLong(false) / 10000000L - data.mid(56, 8).toLongLong(false) / 1000L)); +} + +ByteVector +ASF::File::StreamPropertiesObject::guid() +{ + return streamPropertiesGuid; +} + +void +ASF::File::StreamPropertiesObject::parse(ASF::File *file, uint size) +{ + BaseObject::parse(file, size); + file->d->properties->setChannels(data.mid(56, 2).toShort(false)); + file->d->properties->setSampleRate(data.mid(58, 4).toUInt(false)); + file->d->properties->setBitrate(data.mid(62, 4).toUInt(false) * 8 / 1000); +} + +ByteVector +ASF::File::ContentDescriptionObject::guid() +{ + return contentDescriptionGuid; +} + +void +ASF::File::ContentDescriptionObject::parse(ASF::File *file, uint /*size*/) +{ + file->d->contentDescriptionObject = this; + int titleLength = file->readWORD(); + int artistLength = file->readWORD(); + int copyrightLength = file->readWORD(); + int commentLength = file->readWORD(); + int ratingLength = file->readWORD(); + file->d->tag->setTitle(file->readString(titleLength)); + file->d->tag->setArtist(file->readString(artistLength)); + file->d->tag->setCopyright(file->readString(copyrightLength)); + file->d->tag->setComment(file->readString(commentLength)); + file->d->tag->setRating(file->readString(ratingLength)); +} + +ByteVector +ASF::File::ContentDescriptionObject::render(ASF::File *file) +{ + ByteVector v1 = file->renderString(file->d->tag->title()); + ByteVector v2 = file->renderString(file->d->tag->artist()); + ByteVector v3 = file->renderString(file->d->tag->copyright()); + ByteVector v4 = file->renderString(file->d->tag->comment()); + ByteVector v5 = file->renderString(file->d->tag->rating()); + data.clear(); + data.append(ByteVector::fromShort(v1.size(), false)); + data.append(ByteVector::fromShort(v2.size(), false)); + data.append(ByteVector::fromShort(v3.size(), false)); + data.append(ByteVector::fromShort(v4.size(), false)); + data.append(ByteVector::fromShort(v5.size(), false)); + data.append(v1); + data.append(v2); + data.append(v3); + data.append(v4); + data.append(v5); + return BaseObject::render(file); +} + +ByteVector +ASF::File::ExtendedContentDescriptionObject::guid() +{ + return extendedContentDescriptionGuid; +} + +void +ASF::File::ExtendedContentDescriptionObject::parse(ASF::File *file, uint /*size*/) +{ + file->d->extendedContentDescriptionObject = this; + int count = file->readWORD(); + while(count--) { + ASF::Attribute attribute; + String name = attribute.parse(*file); + file->d->tag->addAttribute(name, attribute); + } +} + +ByteVector +ASF::File::ExtendedContentDescriptionObject::render(ASF::File *file) +{ + data.clear(); + data.append(ByteVector::fromShort(attributeData.size(), false)); + data.append(attributeData.toByteVector(ByteVector::null)); + return BaseObject::render(file); +} + +ByteVector +ASF::File::MetadataObject::guid() +{ + return metadataGuid; +} + +void +ASF::File::MetadataObject::parse(ASF::File *file, uint /*size*/) +{ + file->d->metadataObject = this; + int count = file->readWORD(); + while(count--) { + ASF::Attribute attribute; + String name = attribute.parse(*file, 1); + file->d->tag->addAttribute(name, attribute); + } +} + +ByteVector +ASF::File::MetadataObject::render(ASF::File *file) +{ + data.clear(); + data.append(ByteVector::fromShort(attributeData.size(), false)); + data.append(attributeData.toByteVector(ByteVector::null)); + return BaseObject::render(file); +} + +ByteVector +ASF::File::MetadataLibraryObject::guid() +{ + return metadataLibraryGuid; +} + +void +ASF::File::MetadataLibraryObject::parse(ASF::File *file, uint /*size*/) +{ + file->d->metadataLibraryObject = this; + int count = file->readWORD(); + while(count--) { + ASF::Attribute attribute; + String name = attribute.parse(*file, 2); + file->d->tag->addAttribute(name, attribute); + } +} + +ByteVector +ASF::File::MetadataLibraryObject::render(ASF::File *file) +{ + data.clear(); + data.append(ByteVector::fromShort(attributeData.size(), false)); + data.append(attributeData.toByteVector(ByteVector::null)); + return BaseObject::render(file); +} + +ByteVector +ASF::File::HeaderExtensionObject::guid() +{ + return headerExtensionGuid; +} + +void +ASF::File::HeaderExtensionObject::parse(ASF::File *file, uint /*size*/) +{ + file->d->headerExtensionObject = this; + file->seek(18, File::Current); + long long dataSize = file->readDWORD(); + long long dataPos = 0; + while(dataPos < dataSize) { + ByteVector guid = file->readBlock(16); + long long size = file->readQWORD(); + BaseObject *obj; + if(guid == metadataGuid) { + obj = new MetadataObject(); + } + else if(guid == metadataLibraryGuid) { + obj = new MetadataLibraryObject(); + } + else { + obj = new UnknownObject(guid); + } + obj->parse(file, size); + objects.append(obj); + dataPos += size; + } +} + +ByteVector +ASF::File::HeaderExtensionObject::render(ASF::File *file) +{ + data.clear(); + for(unsigned int i = 0; i < objects.size(); i++) { + data.append(objects[i]->render(file)); + } + data = ByteVector("\x11\xD2\xD3\xAB\xBA\xA9\xcf\x11\x8E\xE6\x00\xC0\x0C\x20\x53\x65\x06\x00", 18) + ByteVector::fromUInt(data.size(), false) + data; + return BaseObject::render(file); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +ASF::File::File(const char *file, bool readProperties, Properties::ReadStyle propertiesStyle) + : TagLib::File(file) +{ + d = new FilePrivate; + read(readProperties, propertiesStyle); +} + +ASF::File::~File() +{ + for(unsigned int i = 0; i < d->objects.size(); i++) { + delete d->objects[i]; + } + if(d->tag) { + delete d->tag; + } + if(d->properties) { + delete d->properties; + } + delete d; +} + +ASF::Tag *ASF::File::tag() const +{ + return d->tag; +} + +ASF::Properties *ASF::File::audioProperties() const +{ + return d->properties; +} + +void ASF::File::read(bool /*readProperties*/, Properties::ReadStyle /*propertiesStyle*/) +{ + if(!isValid()) + return; + + ByteVector guid = readBlock(16); + if(guid != headerGuid) { + return; + } + + d->tag = new ASF::Tag(); + d->properties = new ASF::Properties(); + + d->size = readQWORD(); + int numObjects = readDWORD(); + seek(2, Current); + + for(int i = 0; i < numObjects; i++) { + ByteVector guid = readBlock(16); + long size = (long)readQWORD(); + BaseObject *obj; + if(guid == filePropertiesGuid) { + obj = new FilePropertiesObject(); + } + else if(guid == streamPropertiesGuid) { + obj = new StreamPropertiesObject(); + } + else if(guid == contentDescriptionGuid) { + obj = new ContentDescriptionObject(); + } + else if(guid == extendedContentDescriptionGuid) { + obj = new ExtendedContentDescriptionObject(); + } + else if(guid == headerExtensionGuid) { + obj = new HeaderExtensionObject(); + } + else { + obj = new UnknownObject(guid); + } + obj->parse(this, size); + d->objects.append(obj); + } +} + +bool ASF::File::save() +{ + if(readOnly()) { + return false; + } + + if(!d->contentDescriptionObject) { + d->contentDescriptionObject = new ContentDescriptionObject(); + d->objects.append(d->contentDescriptionObject); + } + if(!d->extendedContentDescriptionObject) { + d->extendedContentDescriptionObject = new ExtendedContentDescriptionObject(); + d->objects.append(d->extendedContentDescriptionObject); + } + if(!d->headerExtensionObject) { + d->headerExtensionObject = new HeaderExtensionObject(); + d->objects.append(d->headerExtensionObject); + } + if(!d->metadataObject) { + d->metadataObject = new MetadataObject(); + d->headerExtensionObject->objects.append(d->metadataObject); + } + if(!d->metadataLibraryObject) { + d->metadataLibraryObject = new MetadataLibraryObject(); + d->headerExtensionObject->objects.append(d->metadataLibraryObject); + } + + ASF::AttributeListMap::ConstIterator it = d->tag->attributeListMap().begin(); + for(; it != d->tag->attributeListMap().end(); it++) { + const String &name = it->first; + const AttributeList &attributes = it->second; + bool inExtendedContentDescriptionObject = false; + bool inMetadataObject = false; + for(unsigned int j = 0; j < attributes.size(); j++) { + const Attribute &attribute = attributes[j]; + if(!inExtendedContentDescriptionObject && attribute.language() == 0 && attribute.stream() == 0) { + d->extendedContentDescriptionObject->attributeData.append(attribute.render(name)); + inExtendedContentDescriptionObject = true; + } + else if(!inMetadataObject && attribute.language() == 0 && attribute.stream() != 0) { + d->metadataObject->attributeData.append(attribute.render(name, 1)); + inMetadataObject = true; + } + else { + d->metadataLibraryObject->attributeData.append(attribute.render(name, 2)); + } + } + } + + ByteVector data; + for(unsigned int i = 0; i < d->objects.size(); i++) { + data.append(d->objects[i]->render(this)); + } + data = headerGuid + ByteVector::fromLongLong(data.size() + 30, false) + ByteVector::fromUInt(d->objects.size(), false) + ByteVector("\x01\x02", 2) + data; + insert(data, 0, d->size); + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +int ASF::File::readBYTE() +{ + ByteVector v = readBlock(1); + return v[0]; +} + +int ASF::File::readWORD() +{ + ByteVector v = readBlock(2); + return v.toShort(false); +} + +unsigned int ASF::File::readDWORD() +{ + ByteVector v = readBlock(4); + return v.toUInt(false); +} + +long long ASF::File::readQWORD() +{ + ByteVector v = readBlock(8); + return v.toLongLong(false); +} + +String +ASF::File::readString(int length) +{ + ByteVector data = readBlock(length); + unsigned int size = data.size(); + while (size >= 2) { + if(data[size - 1] != '\0' || data[size - 2] != '\0') { + break; + } + size -= 2; + } + if(size != data.size()) { + data.resize(size); + } + return String(data, String::UTF16LE); +} + +ByteVector +ASF::File::renderString(const String &str, bool includeLength) +{ + ByteVector data = str.data(String::UTF16LE) + ByteVector::fromShort(0, false); + if(includeLength) { + data = ByteVector::fromShort(data.size(), false) + data; + } + return data; +} diff --git a/src/metadata/asf/asffile.h b/src/metadata/asf/asffile.h new file mode 100644 index 0000000..db97331 --- /dev/null +++ b/src/metadata/asf/asffile.h @@ -0,0 +1,114 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * + * USA * + ***************************************************************************/ + +#ifndef TAGLIB_ASFFILE_H +#define TAGLIB_ASFFILE_H + +#include +#include +#include "asfproperties.h" +#include "asftag.h" + +namespace TagLib { + + //! An implementation of ASF (WMA) metadata + namespace ASF { + + /*! + * This implements and provides an interface for ASF files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to ASF files. + */ + class File : public TagLib::File + { + public: + + /*! + * Contructs an ASF file from \a file. If \a readProperties is true the + * file's audio properties will also be read using \a propertiesStyle. If + * false, \a propertiesStyle is ignored. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. + */ + File(const char *file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns a pointer to the ASF tag of the file. + * + * ASF::Tag implements the tag interface, so this serves as the + * reimplementation of TagLib::File::tag(). + * + * \note The Tag is still owned by the ASF::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + virtual Tag *tag() const; + + /*! + * Returns the ASF audio properties for this file. + */ + virtual Properties *audioProperties() const; + + /*! + * Save the file. + * + * This returns true if the save was successful. + */ + virtual bool save(); + + private: + + int readBYTE(); + int readWORD(); + unsigned int readDWORD(); + long long readQWORD(); + static ByteVector renderString(const String &str, bool includeLength = false); + String readString(int len); + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + + friend class Attribute; + + class BaseObject; + class UnknownObject; + class FilePropertiesObject; + class StreamPropertiesObject; + class ContentDescriptionObject; + class ExtendedContentDescriptionObject; + class HeaderExtensionObject; + class MetadataObject; + class MetadataLibraryObject; + + class FilePrivate; + FilePrivate *d; + }; + + } + +} + +#endif diff --git a/src/metadata/asf/asfproperties.cpp b/src/metadata/asf/asfproperties.cpp new file mode 100644 index 0000000..ca1d983 --- /dev/null +++ b/src/metadata/asf/asfproperties.cpp @@ -0,0 +1,95 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * + * USA * + ***************************************************************************/ + +#include +#include "asfproperties.h" + +using namespace TagLib; + +class ASF::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate(): length(0), bitrate(0), sampleRate(0), channels(0) {} + int length; + int bitrate; + int sampleRate; + int channels; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +ASF::Properties::Properties() : AudioProperties(AudioProperties::Average) +{ + d = new PropertiesPrivate; +} + +ASF::Properties::~Properties() +{ + if(d) + delete d; +} + +int ASF::Properties::length() const +{ + return d->length; +} + +int ASF::Properties::bitrate() const +{ + return d->bitrate; +} + +int ASF::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int ASF::Properties::channels() const +{ + return d->channels; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void ASF::Properties::setLength(int length) +{ + d->length = length; +} + +void ASF::Properties::setBitrate(int length) +{ + d->bitrate = length; +} + +void ASF::Properties::setSampleRate(int length) +{ + d->sampleRate = length; +} + +void ASF::Properties::setChannels(int length) +{ + d->channels = length; +} + diff --git a/src/metadata/asf/asfproperties.h b/src/metadata/asf/asfproperties.h new file mode 100644 index 0000000..150db8a --- /dev/null +++ b/src/metadata/asf/asfproperties.h @@ -0,0 +1,69 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * + * USA * + ***************************************************************************/ + +#ifndef TAGLIB_ASFPROPERTIES_H +#define TAGLIB_ASFPROPERTIES_H + +#include +#include + +namespace TagLib { + + namespace ASF { + + //! An implementation of ASF audio properties + class Properties : public AudioProperties + { + public: + + /*! + * Create an instance of ASF::Properties. + */ + Properties(); + + /*! + * Destroys this ASF::Properties instance. + */ + virtual ~Properties(); + + // Reimplementations. + virtual int length() const; + virtual int bitrate() const; + virtual int sampleRate() const; + virtual int channels() const; + +#ifndef DO_NOT_DOCUMENT + void setLength(int value); + void setBitrate(int value); + void setSampleRate(int value); + void setChannels(int value); +#endif + + private: + class PropertiesPrivate; + PropertiesPrivate *d; + }; + + } + +} + +#endif diff --git a/src/metadata/asf/asftag.cpp b/src/metadata/asf/asftag.cpp new file mode 100644 index 0000000..300887e --- /dev/null +++ b/src/metadata/asf/asftag.cpp @@ -0,0 +1,202 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * + * USA * + ***************************************************************************/ + +#include "asftag.h" + +using namespace TagLib; + +class ASF::Tag::TagPrivate +{ +public: + String title; + String artist; + String copyright; + String comment; + String rating; + AttributeListMap attributeListMap; +}; + +ASF::Tag::Tag() +: TagLib::Tag() +{ + d = new TagPrivate; +} + +ASF::Tag::~Tag() +{ + if(d) + delete d; +} + +String +ASF::Tag::title() const +{ + return d->title; +} + +String +ASF::Tag::artist() const +{ + return d->artist; +} + +String +ASF::Tag::album() const +{ + if(d->attributeListMap.contains("WM/AlbumTitle")) + return d->attributeListMap["WM/AlbumTitle"][0].toString(); + return String::null; +} + +String +ASF::Tag::copyright() const +{ + return d->copyright; +} + +String +ASF::Tag::comment() const +{ + return d->comment; +} + +String +ASF::Tag::rating() const +{ + return d->rating; +} + +unsigned int +ASF::Tag::year() const +{ + if(d->attributeListMap.contains("WM/Year")) + return d->attributeListMap["WM/Year"][0].toString().toInt(); + return 0; +} + +unsigned int +ASF::Tag::track() const +{ + if(d->attributeListMap.contains("WM/TrackNumber")) + return d->attributeListMap["WM/TrackNumber"][0].toString().toInt(); + if(d->attributeListMap.contains("WM/Track")) + return d->attributeListMap["WM/Track"][0].toUInt(); + return 0; +} + +String +ASF::Tag::genre() const +{ + if(d->attributeListMap.contains("WM/Genre")) + return d->attributeListMap["WM/Genre"][0].toString(); + return String::null; +} + +void +ASF::Tag::setTitle(const String &value) +{ + d->title = value; +} + +void +ASF::Tag::setArtist(const String &value) +{ + d->artist = value; +} + +void +ASF::Tag::setCopyright(const String &value) +{ + d->copyright = value; +} + +void +ASF::Tag::setComment(const String &value) +{ + d->comment = value; +} + +void +ASF::Tag::setRating(const String &value) +{ + d->rating = value; +} + +void +ASF::Tag::setAlbum(const String &value) +{ + setAttribute("WM/AlbumTitle", value); +} + +void +ASF::Tag::setGenre(const String &value) +{ + setAttribute("WM/Genre", value); +} + +void +ASF::Tag::setYear(uint value) +{ + setAttribute("WM/Year", String::number(value)); +} + +void +ASF::Tag::setTrack(uint value) +{ + setAttribute("WM/TrackNumber", String::number(value)); +} + +ASF::AttributeListMap& +ASF::Tag::attributeListMap() +{ + return d->attributeListMap; +} + +void ASF::Tag::removeItem(const String &key) +{ + AttributeListMap::Iterator it = d->attributeListMap.find(key); + if(it != d->attributeListMap.end()) + d->attributeListMap.erase(it); +} + +void ASF::Tag::setAttribute(const String &name, const Attribute &attribute) +{ + AttributeList value; + value.append(attribute); + d->attributeListMap.insert(name, value); +} + +void ASF::Tag::addAttribute(const String &name, const Attribute &attribute) +{ + if(d->attributeListMap.contains(name)) { + d->attributeListMap[name].append(attribute); + } + else { + setAttribute(name, attribute); + } +} + +bool ASF::Tag::isEmpty() const { + return TagLib::Tag::isEmpty() && + copyright().isEmpty() && + rating().isEmpty() && + d->attributeListMap.isEmpty(); +} diff --git a/src/metadata/asf/asftag.h b/src/metadata/asf/asftag.h new file mode 100644 index 0000000..f282dee --- /dev/null +++ b/src/metadata/asf/asftag.h @@ -0,0 +1,181 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : lalinsky@gmail.com + **************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * + * USA * + ***************************************************************************/ + +#ifndef TAGLIB_ASFTAG_H +#define TAGLIB_ASFTAG_H + +#include +#include +#include +#include "asfattribute.h" + +namespace TagLib { + + namespace ASF { + + typedef List AttributeList; + typedef Map AttributeListMap; + + class Tag : public TagLib::Tag { + + friend class File; + + public: + + Tag(); + + virtual ~Tag(); + + /*! + * Returns the track name. + */ + virtual String title() const; + + /*! + * Returns the artist name. + */ + virtual String artist() const; + + /*! + * Returns the album name; if no album name is present in the tag + * String::null will be returned. + */ + virtual String album() const; + + /*! + * Returns the track comment. + */ + virtual String comment() const; + + /*! + * Returns the genre name; if no genre is present in the tag String::null + * will be returned. + */ + virtual String genre() const; + + /*! + * Returns the rating. + */ + virtual String rating() const; + + /*! + * Returns the genre name; if no genre is present in the tag String::null + * will be returned. + */ + virtual String copyright() const; + + /*! + * Returns the year; if there is no year set, this will return 0. + */ + virtual uint year() const; + + /*! + * Returns the track number; if there is no track number set, this will + * return 0. + */ + virtual uint track() const; + + /*! + * Sets the title to \a s. + */ + virtual void setTitle(const String &s); + + /*! + * Sets the artist to \a s. + */ + virtual void setArtist(const String &s); + + /*! + * Sets the album to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setAlbum(const String &s); + + /*! + * Sets the comment to \a s. + */ + virtual void setComment(const String &s); + + /*! + * Sets the rating to \a s. + */ + virtual void setRating(const String &s); + + /*! + * Sets the copyright to \a s. + */ + virtual void setCopyright(const String &s); + + /*! + * Sets the genre to \a s. + */ + virtual void setGenre(const String &s); + + /*! + * Sets the year to \a i. If \a s is 0 then this value will be cleared. + */ + virtual void setYear(uint i); + + /*! + * Sets the track to \a i. If \a s is 0 then this value will be cleared. + */ + virtual void setTrack(uint i); + + /*! + * Returns true if the tag does not contain any data. This should be + * reimplemented in subclasses that provide more than the basic tagging + * abilities in this class. + */ + virtual bool isEmpty() const; + + /*! + * Returns a reference to the item list map. This is an AttributeListMap of + * all of the items in the tag. + * + * This is the most powerfull structure for accessing the items of the tag. + */ + AttributeListMap &attributeListMap(); + + /*! + * Removes the \a key attribute from the tag + */ + void removeItem(const String &name); + + /*! + * Sets the \a key attribute to the value of \a attribute. If an attribute + * with the \a key is already present, it will be replaced. + */ + void setAttribute(const String &name, const Attribute &attribute); + + /*! + * Sets the \a key attribute to the value of \a attribute. If an attribute + * with the \a key is already present, it will be added to the list. + */ + void addAttribute(const String &name, const Attribute &attribute); + + private: + + class TagPrivate; + TagPrivate *d; + }; + } +} +#endif diff --git a/src/metadata/asf/taglib_asffiletyperesolver.cpp b/src/metadata/asf/taglib_asffiletyperesolver.cpp new file mode 100644 index 0000000..f9ed059 --- /dev/null +++ b/src/metadata/asf/taglib_asffiletyperesolver.cpp @@ -0,0 +1,47 @@ +/*************************************************************************** + copyright : (C) 2005 by Martin Aumueller + email : aumuell@reserv.at + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +// (c) 2005 Martin Aumueller +// See COPYING file for licensing information + +#include "taglib_asffiletyperesolver.h" +#include "asffile.h" + +#include + +TagLib::File *ASFFileTypeResolver::createFile(const char *fileName, + bool readProperties, + TagLib::AudioProperties::ReadStyle propertiesStyle) const +{ + const char *ext = strrchr(fileName, '.'); + if(ext && (!strcasecmp(ext, ".wma") || !strcasecmp(ext, ".asf"))) + { + TagLib::ASF::File *f = new TagLib::ASF::File(fileName, readProperties, propertiesStyle); + if(f->isValid()) + return f; + else + { + delete f; + } + } + + return 0; +} diff --git a/src/metadata/asf/taglib_asffiletyperesolver.h b/src/metadata/asf/taglib_asffiletyperesolver.h new file mode 100644 index 0000000..ab524b4 --- /dev/null +++ b/src/metadata/asf/taglib_asffiletyperesolver.h @@ -0,0 +1,42 @@ +/*************************************************************************** + copyright : (C) 2005 by Martin Aumueller + email : aumuell@reserv.at + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +// (c) 2005 Martin Aumueller +// See COPYING file for licensing information + +#ifndef TAGLIB_ASFFILETYPERESOLVER_H +#define TAGLIB_ASFFILETYPERESOLVER_H + +#include +#include + + +class ASFFileTypeResolver : public TagLib::FileRef::FileTypeResolver +{ + TagLib::File *createFile(const char *fileName, + bool readAudioProperties, + TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; + +public: + virtual ~ASFFileTypeResolver() {} +}; + +#endif diff --git a/src/metadata/audible/Makefile.am b/src/metadata/audible/Makefile.am new file mode 100644 index 0000000..dcade34 --- /dev/null +++ b/src/metadata/audible/Makefile.am @@ -0,0 +1,17 @@ +SUBDIRS = + +INCLUDES = $(all_includes) $(taglib_includes) +METASOURCES = AUTO +libtagaudible_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libtagaudible.la + +libtagaudible_la_SOURCES = audibleproperties.cpp \ + audibletag.cpp \ + taglib_audiblefile.cpp \ + taglib_audiblefiletyperesolver.cpp + +noinst_HEADERS = audibleproperties.h \ + audibletag.h \ + taglib_audiblefile.h \ + taglib_audiblefiletyperesolver.h + diff --git a/src/metadata/audible/audibleproperties.cpp b/src/metadata/audible/audibleproperties.cpp new file mode 100644 index 0000000..4f39322 --- /dev/null +++ b/src/metadata/audible/audibleproperties.cpp @@ -0,0 +1,86 @@ +/*************************************************************************** + copyright : (C) 2005 by Martin Aumueller + email : aumuell@reserv.at + + copyright : (C) 2005 by Andy Leadbetter + email : andrew.leadbetter@gmail.com + (original mp4 implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include + +#include "audibleproperties.h" + +#include + +#include "taglib_audiblefile.h" + +#include // ntohl + +using namespace TagLib; + + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Audible::Properties::Properties(Properties::ReadStyle style) : AudioProperties(style) +{ + m_length = 0; + m_bitrate = 0; + m_sampleRate = 0; + m_channels = 0; +} + +Audible::Properties::~Properties() +{ +} + +int Audible::Properties::length() const +{ + return m_length; +} + +int Audible::Properties::bitrate() const +{ + return m_bitrate; +} + +int Audible::Properties::sampleRate() const +{ + return m_sampleRate; +} + +int Audible::Properties::channels() const +{ + return m_channels; +} + +#define LENGTH_OFF 61 + +void Audible::Properties::readAudibleProperties( FILE *fp, int off ) +{ + fseek(fp, off+LENGTH_OFF, SEEK_SET ); + fread(&m_length, sizeof(m_length), 1, fp); + m_length = ntohl(m_length); + //fprintf(stderr, "len (sec): %d\n", m_length); + m_bitrate = 0; + m_sampleRate = 0; + m_channels = 1; +} diff --git a/src/metadata/audible/audibleproperties.h b/src/metadata/audible/audibleproperties.h new file mode 100644 index 0000000..948fc30 --- /dev/null +++ b/src/metadata/audible/audibleproperties.h @@ -0,0 +1,85 @@ +/*************************************************************************** + copyright : (C) 2005 by Martin Aumueller + email : aumuell@reserv.at + + copyright : (C) 2005 by Andy Leadbetter + email : andrew.leadbetter@gmail.com + (original mp4 implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_AUDIBLEPROPERTIES_H +#define TAGLIB_AUDIBLEPROPERTIES_H + +#include + +#include +#include + +namespace TagLib { + + namespace Audible { + + class File; + + /*! + * This reads the data from a Audible stream to support the + * AudioProperties API. + */ + + class Properties : public AudioProperties + { + public: + /*! + * Initialize this structure + */ + Properties(Properties::ReadStyle style); + + /*! + * Destroys this Audible Properties instance. + */ + virtual ~Properties(); + + // Reimplementations. + + virtual int length() const; + virtual int bitrate() const; + virtual int sampleRate() const; + virtual int channels() const; + + void readAudibleProperties(FILE *file, int off); + + + private: + void readAudioTrackProperties(FILE *file); + friend class Audible::File; + + int m_length; + int m_bitrate; + int m_sampleRate; + int m_channels; + + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(); + }; + } +} + +#endif diff --git a/src/metadata/audible/audibletag.cpp b/src/metadata/audible/audibletag.cpp new file mode 100644 index 0000000..0fe786f --- /dev/null +++ b/src/metadata/audible/audibletag.cpp @@ -0,0 +1,163 @@ +/*************************************************************************** + copyright : (C) 2005 by Martin Aumueller + email : aumuell@reserv.at + + copyright : (C) 2005 by Andy Leadbetter + email : andrew.leadbetter@gmail.com + (original mp4 implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include + +#include "audibletag.h" + +#include + +#include // ntohl +#include +#include + +using namespace TagLib; + +Audible::Tag::Tag() : TagLib::Tag::Tag() { + m_title = String::null; + m_artist = String::null; + m_album = String::null; + m_comment = String::null; + m_genre = String::null; + m_year = 0; + m_track = 0; + m_userID = 0; + m_tagsEndOffset = -1; +} + +Audible::Tag::~Tag() { +} + +bool Audible::Tag::isEmpty() const { + return m_title == String::null && + m_artist == String::null && + m_album == String::null && + m_comment == String::null && + m_genre == String::null && + m_year == 0 && + m_track == 0 && + m_userID == 0; +} + +void Audible::Tag::duplicate(const Tag *source, Tag *target, bool overwrite) { + // No nonstandard information stored yet + Tag::duplicate(source, target, overwrite); +} + +#define OFF_PRODUCT_ID 197 +#define OFF_TAGS 189 + +void Audible::Tag::readTags( FILE *fp ) +{ + char buf[1023]; + fseek(fp, OFF_PRODUCT_ID, SEEK_SET); + fread(buf, strlen("product_id"), 1, fp); + if(memcmp(buf, "product_id", strlen("product_id"))) + { + buf[20]='\0'; + fprintf(stderr, "no valid Audible aa file: %s\n", buf); + return; + } + + // Now parse tag. + + fseek(fp, OFF_TAGS, SEEK_SET); + char *name, *value; + + m_tagsEndOffset = OFF_TAGS; + + bool lasttag = false; + while(!lasttag) + { + lasttag = !readTag(fp, &name, &value); + if(!strcmp(name, "title")) + { + m_title = String(value, String::Latin1); + } + else if(!strcmp(name, "author")) + { + m_artist = String(value, String::Latin1); + } + else if(!strcmp(name, "long_description")) + { + m_comment = String(value, String::Latin1); + } + else if(!strcmp(name, "description")) + { + if( m_comment.isNull() ) + m_comment = String(value, String::Latin1); + } + else if(!strcmp(name, "pubdate")) + { + m_year = 0; + char *p = strrchr(value, '-'); + if(p) + m_year = strtol(p+1, NULL, 10); + } + else if(!strcmp(name, "user_id")) + { + m_userID = strtol(value, NULL, 10); + } + + delete[] name; + delete[] value; + } + + m_album = String("", String::Latin1); + m_track = 0; + m_genre = String("Audiobook", String::Latin1); +} + +bool Audible::Tag::readTag( FILE *fp, char **name, char **value) +{ + uint32_t nlen; + fread(&nlen, sizeof(nlen), 1, fp); + nlen = ntohl(nlen); + //fprintf(stderr, "tagname len=%x\n", (unsigned)nlen); + *name = new char[nlen+1]; + (*name)[nlen] = '\0'; + + uint32_t vlen; + fread(&vlen, sizeof(vlen), 1, fp); + vlen = ntohl(vlen); + //fprintf(stderr, "tag len=%x\n", (unsigned)vlen); + *value = new char[vlen+1]; + (*value)[vlen] = '\0'; + + fread(*name, nlen, 1, fp); + fread(*value, vlen, 1, fp); + char lasttag; + fread(&lasttag, 1, 1, fp); + //fprintf(stderr, "%s: \"%s\"\n", *name, *value); + + m_tagsEndOffset += 2 * 4 + nlen + vlen + 1; + + return !lasttag; +} + +int Audible::Tag::getTagsEndOffset() +{ + return m_tagsEndOffset; +} diff --git a/src/metadata/audible/audibletag.h b/src/metadata/audible/audibletag.h new file mode 100644 index 0000000..f03966f --- /dev/null +++ b/src/metadata/audible/audibletag.h @@ -0,0 +1,185 @@ +/*************************************************************************** + copyright : (C) 2005 by Martin Aumueller + email : aumuell@reserv.at + + copyright : (C) 2005 by Andy Leadbetter + email : andrew.leadbetter@gmail.com + (original mp4 implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_AUDIBLETAG_H +#define TAGLIB_AUDIBLETAG_H + +#include + +#include +#include "taglib_audiblefile.h" + +namespace TagLib { + + namespace Audible { + /*! + * This implements the generic TagLib::Tag API + */ + class Tag : public TagLib::Tag + { + public: + Tag(); + + /*! + * read tags from the aa file. + */ + void readTags( FILE *file ); + + /*! + * Destroys this AudibleTag instance. + */ + virtual ~Tag(); + + /*! + * Returns the track name; if no track name is present in the tag + * String::null will be returned. + */ + virtual String title() const { return m_title; } + + /*! + * Returns the artist name; if no artist name is present in the tag + * String::null will be returned. + */ + virtual String artist() const { return m_artist; } + + /*! + * Returns the album name; if no album name is present in the tag + * String::null will be returned. + */ + virtual String album() const { return m_album; } + + /*! + * Returns the track comment; if no comment is present in the tag + * String::null will be returned. + */ + virtual String comment() const { return m_comment; } + + /*! + * Returns the genre name; if no genre is present in the tag String::null + * will be returned. + */ + virtual String genre() const { return m_genre; } + + /*! + * Returns the year; if there is no year set, this will return 0. + */ + virtual uint year() const { return m_year; } + + /*! + * Returns the track number; if there is no track number set, this will + * return 0. + */ + virtual uint track() const { return m_track; } + + /*! + * Returns the user id for this file. + */ + virtual uint userID() const { return m_userID; } + + /*! + * Sets the title to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setTitle(const String &s) { m_title = s; } + + /*! + * Sets the artist to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setArtist(const String &s) { m_artist = s; } + + /*! + * Sets the album to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setAlbum(const String &s) { m_album = s; } + + /*! + * Sets the album to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setComment(const String &s) { m_comment = s; } + + /*! + * Sets the genre to \a s. If \a s is String::null then this value will be + * cleared. For tag formats that use a fixed set of genres, the appropriate + * value will be selected based on a string comparison. A list of available + * genres for those formats should be available in that type's + * implementation. + */ + virtual void setGenre(const String &s) { m_genre = s; } + + /*! + * Sets the year to \a i. If \a s is 0 then this value will be cleared. + */ + virtual void setYear(uint i) { m_year = i; } + + /*! + * Sets the track to \a i. If \a s is 0 then this value will be cleared. + */ + virtual void setTrack(uint i) { m_track = i; } + + /*! + * Returns true if the tag does not contain any data. This should be + * reimplemented in subclasses that provide more than the basic tagging + * abilities in this class. + */ + virtual bool isEmpty() const; + + /*! + * Copies the generic data from one tag to another. + * + * \note This will not affect any of the lower level details of the tag. For + * instance if any of the tag type specific data (maybe a URL for a band) is + * set, this will not modify or copy that. This just copies using the API + * in this class. + * + * If \a overwrite is true then the values will be unconditionally copied. + * If false only empty values will be overwritten. + */ + static void duplicate(const Tag *source, Tag *target, bool overwrite = true); + + virtual void setUserID(uint id) { m_userID = id; } + + int getTagsEndOffset(); + + + + protected: + String m_title; + String m_artist; + String m_album; + String m_comment; + String m_genre; + uint m_year; + uint m_track; + uint m_userID; + bool readTag( FILE *fp, char **name, char **value); + int m_tagsEndOffset; + }; + } +} + +#endif diff --git a/src/metadata/audible/taglib_audiblefile.cpp b/src/metadata/audible/taglib_audiblefile.cpp new file mode 100644 index 0000000..47f5182 --- /dev/null +++ b/src/metadata/audible/taglib_audiblefile.cpp @@ -0,0 +1,121 @@ +/*************************************************************************** + copyright : (C) 2005 by Martin Aumueller + email : aumuell@reserv.at + + copyright : (C) 2005 by Andy Leadbetter + email : andrew.leadbetter@gmail.com + (original mp4 implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include + +#include "taglib_audiblefile.h" + +#include "audibletag.h" +#include +#include + +namespace TagLib { +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Audible::File::File(const char *file, + bool readProperties, + Properties::ReadStyle propertiesStyle, + FILE *fp) + : TagLib::File(file) + , audibletag( NULL ) + , properties( NULL ) +{ + + // debug ("Audible::File: create new file object."); + //debug ( file ); + + /** + * Create the Audible file. + */ + + if(fp) + audiblefile = fp; + else + audiblefile = fopen(file, "rb"); + + if( isOpen() ) + { + read(readProperties, propertiesStyle ); + } +} + +Audible::File::~File() +{ + if(audiblefile) + fclose(audiblefile); + delete audibletag; + delete properties; +} + +TagLib::Tag *Audible::File::tag() const +{ + return audibletag; +} + +TagLib::Audible::Tag *Audible::File::getAudibleTag() const +{ + return audibletag; +} + +Audible::Properties *Audible::File::audioProperties() const +{ + return properties; +} + +bool Audible::File::save() +{ + return false; +} + +bool Audible::File::isOpen() +{ + return audiblefile != NULL; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void Audible::File::read(bool readProperties, Properties::ReadStyle propertiesStyle) +{ + properties = new Audible::Properties(propertiesStyle); + audibletag = new Audible::Tag(); + + if (audiblefile != NULL) { + audibletag->readTags( audiblefile ); + int off = audibletag->getTagsEndOffset(); + //fprintf(stderr, "off=%d\n", off); + + if(readProperties) + { + // Parse bitrate etc. + properties->readAudibleProperties( audiblefile, off ); + } + } +} + +} diff --git a/src/metadata/audible/taglib_audiblefile.h b/src/metadata/audible/taglib_audiblefile.h new file mode 100644 index 0000000..c1860ae --- /dev/null +++ b/src/metadata/audible/taglib_audiblefile.h @@ -0,0 +1,93 @@ +/*************************************************************************** + copyright : (C) 2005 by Martin Aumueller + email : aumuell@reserv.at + + copyright : (C) 2005 by Andy Leadbetter + email : andrew.leadbetter@gmail.com + (original mp4 implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_AUDIBLEFILE_H +#define TAGLIB_AUDIBLEFILE_H + +#include +#include "audibleproperties.h" +#include "audibletag.h" + +namespace TagLib { + + namespace Audible { + + class Tag; + + class File : public TagLib::File + { + public: + /*! + * Contructs a Audible file from \a file. If \a readProperties is true the + * file's audio properties will also be read using \a propertiesStyle. If + * false, \a propertiesStyle is ignored. + */ + File(const char *file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average, + FILE *fp=NULL); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + + virtual TagLib::Tag *tag() const; + + /*! + * Returns the Audible::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Audible::Properties *audioProperties() const; + + /*! + * Save the file. + * This is the same as calling save(AllTags); + * + * \note As of now, saving Audible tags is not supported. + */ + virtual bool save(); + + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + + Audible::Tag *getAudibleTag() const; + + bool isAudibleFile() const; + + protected: + File(const File &); + File &operator=(const File &); + bool isOpen(); + + + Audible::Tag *audibletag; + Audible::Properties *properties; + + FILE *audiblefile; + }; + } +} + +#endif diff --git a/src/metadata/audible/taglib_audiblefiletyperesolver.cpp b/src/metadata/audible/taglib_audiblefiletyperesolver.cpp new file mode 100644 index 0000000..152b17c --- /dev/null +++ b/src/metadata/audible/taglib_audiblefiletyperesolver.cpp @@ -0,0 +1,44 @@ +/*************************************************************************** + copyright : (C) 2005 by Martin Aumueller + email : aumuell@reserv.at + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include + +#include "taglib_audiblefiletyperesolver.h" +#include "taglib_audiblefile.h" + +#include + +TagLib::File *AudibleFileTypeResolver::createFile(const char *fileName, + bool readProperties, + TagLib::AudioProperties::ReadStyle propertiesStyle) const +{ + const char *ext = strrchr(fileName, '.'); + if(ext && !strcasecmp(ext, ".aa")) + { + FILE *fp = fopen(fileName, "rb"); + if(!fp) + return 0; + + return new TagLib::Audible::File(fileName, readProperties, propertiesStyle, fp); + } + + return 0; +} diff --git a/src/metadata/audible/taglib_audiblefiletyperesolver.h b/src/metadata/audible/taglib_audiblefiletyperesolver.h new file mode 100644 index 0000000..6f1e705 --- /dev/null +++ b/src/metadata/audible/taglib_audiblefiletyperesolver.h @@ -0,0 +1,36 @@ +/*************************************************************************** + copyright : (C) 2005 by Martin Aumueller + email : aumuell@reserv.at + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_AUDIBLEFILETYPERESOLVER_H +#define TAGLIB_AUDIBLEFILETYPERESOLVER_H + +#include +#include + + +class AudibleFileTypeResolver : public TagLib::FileRef::FileTypeResolver +{ + TagLib::File *createFile(const char *fileName, + bool readAudioProperties, + TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; +}; + +#endif diff --git a/src/metadata/m4a/Makefile.am b/src/metadata/m4a/Makefile.am new file mode 100644 index 0000000..34d9af4 --- /dev/null +++ b/src/metadata/m4a/Makefile.am @@ -0,0 +1,84 @@ +SUBDIRS = +METASOURCES = AUTO +INCLUDES = $(all_includes) $(taglib_includes) + +libtagm4a_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libtagm4a.la + +libtagm4a_la_SOURCES = \ + taglib_mp4filetyperesolver.cpp \ + mp4file.cpp \ + mp4itunestag.cpp \ + mp4isobox.cpp \ + mp4isofullbox.cpp \ + mp4skipbox.cpp \ + mp4moovbox.cpp \ + mp4mvhdbox.cpp \ + mp4ilstbox.cpp \ + boxfactory.cpp \ + mp4fourcc.cpp \ + mp4udtabox.cpp \ + mp4metabox.cpp \ + mp4tagsproxy.cpp \ + mp4mdiabox.cpp \ + mp4minfbox.cpp \ + mp4audioproperties.cpp \ + mp4hdlrbox.cpp \ + mp4stblbox.cpp \ + mp4audiosampleentry.cpp \ + mp4stsdbox.cpp \ + mp4sampleentry.cpp \ + mp4trakbox.cpp \ + mp4propsproxy.cpp \ + itunesnambox.cpp \ + itunesartbox.cpp \ + itunesalbbox.cpp \ + itunescvrbox.cpp \ + itunesgenbox.cpp \ + itunestrknbox.cpp \ + itunesdaybox.cpp \ + itunescmtbox.cpp \ + itunesgrpbox.cpp \ + ituneswrtbox.cpp \ + itunesdiskbox.cpp \ + itunestmpobox.cpp \ + itunesdatabox.cpp + +noinst_HEADERS = \ + taglib_mp4filetyperesolver.h \ + mp4file.h \ + mp4itunestag.h \ + mp4isobox.h \ + mp4isofullbox.h \ + mp4skipbox.h \ + mp4moovbox.h \ + mp4mvhdbox.h \ + mp4ilstbox.h \ + boxfactory.h \ + mp4fourcc.h \ + mp4udtabox.h \ + mp4metabox.h \ + mp4tagsproxy.h \ + mp4audioproperties.h \ + mp4hdlrbox.h \ + mp4propsproxy.h \ + mp4mdiabox.h \ + mp4stsdbox.h \ + mp4trakbox.h \ + mp4stblbox.h \ + mp4audiosampleentry.h \ + mp4minfbox.h \ + mp4sampleentry.h \ + itunesnambox.h \ + itunesartbox.h \ + itunesalbbox.h \ + itunesgenbox.h \ + itunestrknbox.h \ + itunesdaybox.h \ + itunescmtbox.h \ + itunescvrbox.h \ + itunesgrpbox.h \ + ituneswrtbox.h \ + itunesdiskbox.h \ + itunestmpobox.h \ + itunesdatabox.h diff --git a/src/metadata/m4a/boxfactory.cpp b/src/metadata/m4a/boxfactory.cpp new file mode 100644 index 0000000..0fc8eb4 --- /dev/null +++ b/src/metadata/m4a/boxfactory.cpp @@ -0,0 +1,150 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +#include "tstring.h" +#include "boxfactory.h" +#include "mp4skipbox.h" +#include "mp4moovbox.h" +#include "mp4mvhdbox.h" +#include "mp4trakbox.h" +#include "mp4mdiabox.h" +#include "mp4minfbox.h" +#include "mp4stblbox.h" +#include "mp4stsdbox.h" +#include "mp4hdlrbox.h" +#include "mp4udtabox.h" +#include "mp4metabox.h" +#include "mp4ilstbox.h" +#include "itunesnambox.h" +#include "itunesartbox.h" +#include "itunesalbbox.h" +#include "itunesgenbox.h" +#include "itunesdaybox.h" +#include "itunestrknbox.h" +#include "itunescmtbox.h" +#include "itunesgrpbox.h" +#include "ituneswrtbox.h" +#include "itunesdiskbox.h" +#include "itunestmpobox.h" +#include "itunescvrbox.h" +#include "itunesdatabox.h" + +using namespace TagLib; + +MP4::BoxFactory::BoxFactory() +{ +} + +MP4::BoxFactory::~BoxFactory() +{ +} + +//! factory function +MP4::Mp4IsoBox* MP4::BoxFactory::createInstance( TagLib::File* anyfile, MP4::Fourcc fourcc, uint size, long offset ) const +{ + MP4::File * file = dynamic_cast(anyfile); + if(!file) + return 0; + + //std::cout << "creating box for: " << fourcc.toString() << std::endl; + + switch( fourcc ) + { + case 0x6d6f6f76: // 'moov' + return new MP4::Mp4MoovBox( file, fourcc, size, offset ); + break; + case 0x6d766864: // 'mvhd' + return new MP4::Mp4MvhdBox( file, fourcc, size, offset ); + break; + case 0x7472616b: // 'trak' + return new MP4::Mp4TrakBox( file, fourcc, size, offset ); + break; + case 0x6d646961: // 'mdia' + return new MP4::Mp4MdiaBox( file, fourcc, size, offset ); + break; + case 0x6d696e66: // 'minf' + return new MP4::Mp4MinfBox( file, fourcc, size, offset ); + break; + case 0x7374626c: // 'stbl' + return new MP4::Mp4StblBox( file, fourcc, size, offset ); + break; + case 0x73747364: // 'stsd' + return new MP4::Mp4StsdBox( file, fourcc, size, offset ); + break; + case 0x68646c72: // 'hdlr' + return new MP4::Mp4HdlrBox( file, fourcc, size, offset ); + break; + case 0x75647461: // 'udta' + return new MP4::Mp4UdtaBox( file, fourcc, size, offset ); + break; + case 0x6d657461: // 'meta' + return new MP4::Mp4MetaBox( file, fourcc, size, offset ); + break; + case 0x696c7374: // 'ilst' + return new MP4::Mp4IlstBox( file, fourcc, size, offset ); + break; + case 0xa96e616d: // '_nam' + return new MP4::ITunesNamBox( file, fourcc, size, offset ); + break; + case 0xa9415254: // '_ART' + return new MP4::ITunesArtBox( file, fourcc, size, offset ); + break; + case 0xa9616c62: // '_alb' + return new MP4::ITunesAlbBox( file, fourcc, size, offset ); + break; + case 0xa967656e: // '_gen' + return new MP4::ITunesGenBox( file, fourcc, size, offset ); + break; + case 0x676e7265: // 'gnre' + return new MP4::ITunesGenBox( file, fourcc, size, offset ); + break; + case 0xa9646179: // '_day' + return new MP4::ITunesDayBox( file, fourcc, size, offset ); + break; + case 0x74726b6e: // 'trkn' + return new MP4::ITunesTrknBox( file, fourcc, size, offset ); + break; + case 0xa9636d74: // '_cmt' + return new MP4::ITunesCmtBox( file, fourcc, size, offset ); + break; + case 0xa9677270: // '_grp' + return new MP4::ITunesGrpBox( file, fourcc, size, offset ); + break; + case 0xa9777274: // '_wrt' + return new MP4::ITunesWrtBox( file, fourcc, size, offset ); + break; + case 0x6469736b: // 'disk' + return new MP4::ITunesDiskBox( file, fourcc, size, offset ); + break; + case 0x746d706f: // 'tmpo' + return new MP4::ITunesTmpoBox( file, fourcc, size, offset ); + break; + case 0x636f7672: // 'covr' + return new MP4::ITunesCvrBox( file, fourcc, size, offset ); + break; + case 0x64616461: // 'data' + return new MP4::ITunesDataBox( file, fourcc, size, offset ); + break; + default: + return new MP4::Mp4SkipBox( file, fourcc, size, offset ); + } +} diff --git a/src/metadata/m4a/boxfactory.h b/src/metadata/m4a/boxfactory.h new file mode 100644 index 0000000..7edcd6c --- /dev/null +++ b/src/metadata/m4a/boxfactory.h @@ -0,0 +1,45 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef BOXFACTORY_H +#define BOXFACTORY_H + +#include "taglib.h" +#include "mp4isobox.h" + +namespace TagLib +{ + namespace MP4 + { + class BoxFactory + { + public: + BoxFactory(); + ~BoxFactory(); + + //! factory function + Mp4IsoBox* createInstance( TagLib::File* anyfile, MP4::Fourcc fourcc, uint size, long offset ) const; + }; // class BoxFactory + + } // namepace MP4 +} // namepace TagLib + +#endif // BOXFACTORY_H diff --git a/src/metadata/m4a/itunesalbbox.cpp b/src/metadata/m4a/itunesalbbox.cpp new file mode 100644 index 0000000..5832fa0 --- /dev/null +++ b/src/metadata/m4a/itunesalbbox.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +#include "itunesalbbox.h" +#include "itunesdatabox.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "tfile.h" +#include "mp4tagsproxy.h" + +using namespace TagLib; + +class MP4::ITunesAlbBox::ITunesAlbBoxPrivate +{ +public: + ITunesDataBox* dataBox; +}; + +MP4::ITunesAlbBox::ITunesAlbBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesAlbBox::ITunesAlbBoxPrivate(); + d->dataBox = 0; +} + +MP4::ITunesAlbBox::~ITunesAlbBox() +{ + if( d->dataBox != 0 ) + delete d->dataBox; + delete d; +} + +//! parse the content of the box +void MP4::ITunesAlbBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast( file() ); + + // parse data box + TagLib::uint size; + MP4::Fourcc fourcc; + + if(mp4file->readSizeAndType( size, fourcc ) == true) + { + // check for type - must be 'data' + if( fourcc != MP4::Fourcc("data") ) + { + std::cerr << "bad atom in itunes tag - skipping it." << std::endl; + // jump over data tag + mp4file->seek( size-8, TagLib::File::Current ); + return; + } + d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() ); + d->dataBox->parsebox(); + } + else + { + // reading unsuccessful - serious error! + std::cerr << "Error in parsing ITunesAlbBox - serious Error in taglib!" << std::endl; + return; + } + // register data box + mp4file->tagProxy()->registerBox( Mp4TagsProxy::album, d->dataBox ); + +#if 0 + // get data pointer - just for debugging... + TagLib::String dataString( d->dataBox->data() ); + std::cout << "Content of album box: " << dataString << std::endl; +#endif +} + diff --git a/src/metadata/m4a/itunesalbbox.h b/src/metadata/m4a/itunesalbbox.h new file mode 100644 index 0000000..f2462c2 --- /dev/null +++ b/src/metadata/m4a/itunesalbbox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESALBBOX_H +#define ITUNESALBBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesAlbBox: public Mp4IsoBox + { + public: + ITunesAlbBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesAlbBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesAlbBoxPrivate; + ITunesAlbBoxPrivate* d; + }; // class ITunesAlbBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESALBBOX_H diff --git a/src/metadata/m4a/itunesartbox.cpp b/src/metadata/m4a/itunesartbox.cpp new file mode 100644 index 0000000..19e717d --- /dev/null +++ b/src/metadata/m4a/itunesartbox.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +#include "itunesartbox.h" +#include "itunesdatabox.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "tfile.h" +#include "mp4tagsproxy.h" + +using namespace TagLib; + +class MP4::ITunesArtBox::ITunesArtBoxPrivate +{ +public: + ITunesDataBox* dataBox; +}; + +MP4::ITunesArtBox::ITunesArtBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesArtBox::ITunesArtBoxPrivate(); + d->dataBox = 0; +} + +MP4::ITunesArtBox::~ITunesArtBox() +{ + if( d->dataBox != 0 ) + delete d->dataBox; + delete d; +} + +//! parse the content of the box +void MP4::ITunesArtBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast( file() ); + + // parse data box + TagLib::uint size; + MP4::Fourcc fourcc; + + if(mp4file->readSizeAndType( size, fourcc ) == true) + { + // check for type - must be 'data' + if( fourcc != MP4::Fourcc("data") ) + { + std::cerr << "bad atom in itunes tag - skipping it." << std::endl; + // jump over data tag + mp4file->seek( size-8, TagLib::File::Current ); + return; + } + d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() ); + d->dataBox->parsebox(); + } + else + { + // reading unsuccessful - serious error! + std::cerr << "Error in parsing ITunesArtBox - serious Error in taglib!" << std::endl; + return; + } + // register data box + mp4file->tagProxy()->registerBox( Mp4TagsProxy::artist, d->dataBox ); + +#if 0 + // get data pointer - just for debugging... + TagLib::String dataString( d->dataBox->data() ); + std::cout << "Content of artist box: " << dataString << std::endl; +#endif +} + diff --git a/src/metadata/m4a/itunesartbox.h b/src/metadata/m4a/itunesartbox.h new file mode 100644 index 0000000..5d197aa --- /dev/null +++ b/src/metadata/m4a/itunesartbox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESARTBOX_H +#define ITUNESARTBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesArtBox: public Mp4IsoBox + { + public: + ITunesArtBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesArtBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesArtBoxPrivate; + ITunesArtBoxPrivate* d; + }; // class ITunesArtBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESARTBOX_H diff --git a/src/metadata/m4a/itunescmtbox.cpp b/src/metadata/m4a/itunescmtbox.cpp new file mode 100644 index 0000000..c79f0f7 --- /dev/null +++ b/src/metadata/m4a/itunescmtbox.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +#include "itunescmtbox.h" +#include "itunesdatabox.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "tfile.h" +#include "mp4tagsproxy.h" + +using namespace TagLib; + +class MP4::ITunesCmtBox::ITunesCmtBoxPrivate +{ +public: + ITunesDataBox* dataBox; +}; + +MP4::ITunesCmtBox::ITunesCmtBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesCmtBox::ITunesCmtBoxPrivate(); + d->dataBox = 0; +} + +MP4::ITunesCmtBox::~ITunesCmtBox() +{ + if( d->dataBox != 0 ) + delete d->dataBox; + delete d; +} + +//! parse the content of the box +void MP4::ITunesCmtBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast( file() ); + + // parse data box + TagLib::uint size; + MP4::Fourcc fourcc; + + if(mp4file->readSizeAndType( size, fourcc ) == true) + { + // check for type - must be 'data' + if( fourcc != MP4::Fourcc("data") ) + { + std::cerr << "bad atom in itunes tag - skipping it." << std::endl; + // jump over data tag + mp4file->seek( size-8, TagLib::File::Current ); + return; + } + d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() ); + d->dataBox->parsebox(); + } + else + { + // reading unsuccessful - serious error! + std::cerr << "Error in parsing ITunesCmtBox - serious Error in taglib!" << std::endl; + return; + } + // register data box + mp4file->tagProxy()->registerBox( Mp4TagsProxy::comment, d->dataBox ); + +#if 0 + // get data pointer - just for debugging... + TagLib::String dataString( d->dataBox->data() ); + std::cout << "Content of title box: " << dataString << std::endl; +#endif +} + diff --git a/src/metadata/m4a/itunescmtbox.h b/src/metadata/m4a/itunescmtbox.h new file mode 100644 index 0000000..83ad65d --- /dev/null +++ b/src/metadata/m4a/itunescmtbox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESCMTBOX_H +#define ITUNESCMTBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesCmtBox: public Mp4IsoBox + { + public: + ITunesCmtBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesCmtBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesCmtBoxPrivate; + ITunesCmtBoxPrivate* d; + }; // class ITunesCmtBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESCMTBOX_H diff --git a/src/metadata/m4a/itunescvrbox.cpp b/src/metadata/m4a/itunescvrbox.cpp new file mode 100644 index 0000000..4a7b3db --- /dev/null +++ b/src/metadata/m4a/itunescvrbox.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +#include "itunescvrbox.h" +#include "itunesdatabox.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "tfile.h" +#include "mp4tagsproxy.h" + +using namespace TagLib; + +class MP4::ITunesCvrBox::ITunesCvrBoxPrivate +{ +public: + ITunesDataBox* dataBox; +}; + +MP4::ITunesCvrBox::ITunesCvrBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesCvrBox::ITunesCvrBoxPrivate(); + d->dataBox = 0; +} + +MP4::ITunesCvrBox::~ITunesCvrBox() +{ + if( d->dataBox != 0 ) + delete d->dataBox; + delete d; +} + +//! parse the content of the box +void MP4::ITunesCvrBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast( file() ); + + // parse data box + TagLib::uint size; + MP4::Fourcc fourcc; + + if(mp4file->readSizeAndType( size, fourcc ) == true) + { + // check for type - must be 'data' + if( fourcc != MP4::Fourcc("data") ) + { + std::cerr << "bad atom in itunes tag - skipping it." << std::endl; + // jump over data tag + mp4file->seek( size-8, TagLib::File::Current ); + return; + } + d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() ); + d->dataBox->parsebox(); + } + else + { + // reading unsuccessful - serious error! + std::cerr << "Error in parsing ITunesCvrBox - serious Error in taglib!" << std::endl; + return; + } + // register data box + mp4file->tagProxy()->registerBox( Mp4TagsProxy::cover, d->dataBox ); + +#if 0 + // get data pointer - just for debugging... + TagLib::String dataString( d->dataBox->data() ); + std::cout << "Content of album box: " << dataString << std::endl; +#endif +} + diff --git a/src/metadata/m4a/itunescvrbox.h b/src/metadata/m4a/itunescvrbox.h new file mode 100644 index 0000000..a2693c2 --- /dev/null +++ b/src/metadata/m4a/itunescvrbox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESCVRBOX_H +#define ITUNESCVRBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesCvrBox: public Mp4IsoBox + { + public: + ITunesCvrBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesCvrBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesCvrBoxPrivate; + ITunesCvrBoxPrivate* d; + }; // class ITunesCvrBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESCVRBOX_H diff --git a/src/metadata/m4a/itunesdatabox.cpp b/src/metadata/m4a/itunesdatabox.cpp new file mode 100644 index 0000000..7565a42 --- /dev/null +++ b/src/metadata/m4a/itunesdatabox.cpp @@ -0,0 +1,63 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +#include "itunesdatabox.h" +#include "tbytevector.h" +#include "mp4isobox.h" +#include "tfile.h" + +using namespace TagLib; + +class MP4::ITunesDataBox::ITunesDataBoxPrivate +{ +public: + ByteVector data; +}; + +MP4::ITunesDataBox::ITunesDataBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoFullBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesDataBox::ITunesDataBoxPrivate(); +} + +MP4::ITunesDataBox::~ITunesDataBox() +{ + delete d; +} + +ByteVector MP4::ITunesDataBox::data() const +{ + return d->data; +} + +//! parse the content of the box +void MP4::ITunesDataBox::parse() +{ + // skip first 4 byte - don't know what they are supposed to be for - simply 4 zeros + file()->seek( 4, TagLib::File::Current ); + // read contents - remaining size is box_size-12-4 (12:fullbox header, 4:starting zeros of data box) +#if 0 + std::cout << " reading data box with data length: " << size()-16 << std::endl; +#endif + d->data = file()->readBlock( size()-12-4 ); +} + diff --git a/src/metadata/m4a/itunesdatabox.h b/src/metadata/m4a/itunesdatabox.h new file mode 100644 index 0000000..d0c802c --- /dev/null +++ b/src/metadata/m4a/itunesdatabox.h @@ -0,0 +1,53 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESDATABOX_H +#define ITUNESDATABOX_H + +#include "mp4isofullbox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesDataBox: public Mp4IsoFullBox + { + public: + ITunesDataBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesDataBox(); + + //! get the internal data, which can be txt or binary data as well + ByteVector data() const; + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesDataBoxPrivate; + ITunesDataBoxPrivate* d; + }; // class ITunesDataBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESDATABOX_H diff --git a/src/metadata/m4a/itunesdaybox.cpp b/src/metadata/m4a/itunesdaybox.cpp new file mode 100644 index 0000000..16568d7 --- /dev/null +++ b/src/metadata/m4a/itunesdaybox.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +#include "itunesdaybox.h" +#include "itunesdatabox.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "tfile.h" +#include "mp4tagsproxy.h" + +using namespace TagLib; + +class MP4::ITunesDayBox::ITunesDayBoxPrivate +{ +public: + ITunesDataBox* dataBox; +}; + +MP4::ITunesDayBox::ITunesDayBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesDayBox::ITunesDayBoxPrivate(); + d->dataBox = 0; +} + +MP4::ITunesDayBox::~ITunesDayBox() +{ + if( d->dataBox != 0 ) + delete d->dataBox; + delete d; +} + +//! parse the content of the box +void MP4::ITunesDayBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast( file() ); + + // parse data box + TagLib::uint size; + MP4::Fourcc fourcc; + + if(mp4file->readSizeAndType( size, fourcc ) == true) + { + // check for type - must be 'data' + if( fourcc != MP4::Fourcc("data") ) + { + std::cerr << "bad atom in itunes tag - skipping it." << std::endl; + // jump over data tag + mp4file->seek( size-8, TagLib::File::Current ); + return; + } + d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() ); + d->dataBox->parsebox(); + } + else + { + // reading unsuccessful - serious error! + std::cerr << "Error in parsing ITunesDayBox - serious Error in taglib!" << std::endl; + return; + } + // register data box + mp4file->tagProxy()->registerBox( Mp4TagsProxy::year, d->dataBox ); + +#if 0 + // get data pointer - just for debugging... + TagLib::String dataString( d->dataBox->data() ); + std::cout << "Content of day box: " << dataString.substr(0,4) << std::endl; +#endif +} + diff --git a/src/metadata/m4a/itunesdaybox.h b/src/metadata/m4a/itunesdaybox.h new file mode 100644 index 0000000..7291363 --- /dev/null +++ b/src/metadata/m4a/itunesdaybox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESDAYBOX_H +#define ITUNESDAYBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesDayBox: public Mp4IsoBox + { + public: + ITunesDayBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesDayBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesDayBoxPrivate; + ITunesDayBoxPrivate* d; + }; // class ITunesDayBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESDAYBOX_H diff --git a/src/metadata/m4a/itunesdiskbox.cpp b/src/metadata/m4a/itunesdiskbox.cpp new file mode 100644 index 0000000..93c47f2 --- /dev/null +++ b/src/metadata/m4a/itunesdiskbox.cpp @@ -0,0 +1,93 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +#include "itunesdiskbox.h" +#include "itunesdatabox.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "tfile.h" +#include "mp4tagsproxy.h" + +using namespace TagLib; + +class MP4::ITunesDiskBox::ITunesDiskBoxPrivate +{ +public: + ITunesDataBox* dataBox; +}; + +MP4::ITunesDiskBox::ITunesDiskBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesDiskBox::ITunesDiskBoxPrivate(); + d->dataBox = 0; +} + +MP4::ITunesDiskBox::~ITunesDiskBox() +{ + if( d->dataBox != 0 ) + delete d->dataBox; + delete d; +} + +//! parse the content of the box +void MP4::ITunesDiskBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast( file() ); + + // parse data box + TagLib::uint size; + MP4::Fourcc fourcc; + + if(mp4file->readSizeAndType( size, fourcc ) == true) + { + // check for type - must be 'data' + if( fourcc != MP4::Fourcc("data") ) + { + std::cerr << "bad atom in itunes tag - skipping it." << std::endl; + // jump over data tag + mp4file->seek( size-8, TagLib::File::Current ); + return; + } + d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() ); + d->dataBox->parsebox(); + } + else + { + // reading unsuccessful - serious error! + std::cerr << "Error in parsing ITunesDiskBox - serious Error in taglib!" << std::endl; + return; + } + // register data box + mp4file->tagProxy()->registerBox( Mp4TagsProxy::disk, d->dataBox ); + +#if 0 + // get data pointer - just for debugging... + TagLib::ByteVector trknData = d->dataBox->data(); + TagLib::String trknumber = TagLib::String::number( static_cast( static_cast(trknData[0]) << 24 | + static_cast(trknData[1]) << 16 | + static_cast(trknData[2]) << 8 | + static_cast(trknData[3]) ) ); + std::cout << "Content of tracknumber box: " << trknumber << std::endl; +#endif +} + diff --git a/src/metadata/m4a/itunesdiskbox.h b/src/metadata/m4a/itunesdiskbox.h new file mode 100644 index 0000000..bad73da --- /dev/null +++ b/src/metadata/m4a/itunesdiskbox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESDISKBOX_H +#define ITUNESDISKBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesDiskBox: public Mp4IsoBox + { + public: + ITunesDiskBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesDiskBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesDiskBoxPrivate; + ITunesDiskBoxPrivate* d; + }; // class ITunesDiskBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESDISKBOX_H diff --git a/src/metadata/m4a/itunesgenbox.cpp b/src/metadata/m4a/itunesgenbox.cpp new file mode 100644 index 0000000..08708bc --- /dev/null +++ b/src/metadata/m4a/itunesgenbox.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +#include "itunesgenbox.h" +#include "itunesdatabox.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "tfile.h" +#include "mp4tagsproxy.h" + +using namespace TagLib; + +class MP4::ITunesGenBox::ITunesGenBoxPrivate +{ +public: + ITunesDataBox* dataBox; +}; + +MP4::ITunesGenBox::ITunesGenBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesGenBox::ITunesGenBoxPrivate(); + d->dataBox = 0; +} + +MP4::ITunesGenBox::~ITunesGenBox() +{ + if( d->dataBox != 0 ) + delete d->dataBox; + delete d; +} + +//! parse the content of the box +void MP4::ITunesGenBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast( file() ); + + // parse data box + TagLib::uint size; + MP4::Fourcc fourcc; + + if(mp4file->readSizeAndType( size, fourcc ) == true) + { + // check for type - must be 'data' + if( fourcc != MP4::Fourcc("data") ) + { + std::cerr << "bad atom in itunes tag - skipping it." << std::endl; + // jump over data tag + mp4file->seek( size-8, TagLib::File::Current ); + return; + } + d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() ); + d->dataBox->parsebox(); + } + else + { + // reading unsuccessful - serious error! + std::cerr << "Error in parsing ITunesGenBox - serious Error in taglib!" << std::endl; + return; + } + // register data box + mp4file->tagProxy()->registerBox( Mp4TagsProxy::genre, d->dataBox ); + +#if 0 + // get data pointer - just for debugging... + TagLib::String dataString( d->dataBox->data() ); + std::cout << "Content of genre box: " << dataString << std::endl; +#endif +} + diff --git a/src/metadata/m4a/itunesgenbox.h b/src/metadata/m4a/itunesgenbox.h new file mode 100644 index 0000000..deb7fe3 --- /dev/null +++ b/src/metadata/m4a/itunesgenbox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESGENBOX_H +#define ITUNESGENBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesGenBox: public Mp4IsoBox + { + public: + ITunesGenBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesGenBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesGenBoxPrivate; + ITunesGenBoxPrivate* d; + }; // class ITunesGenBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESGENBOX_H diff --git a/src/metadata/m4a/itunesgrpbox.cpp b/src/metadata/m4a/itunesgrpbox.cpp new file mode 100644 index 0000000..061b6bd --- /dev/null +++ b/src/metadata/m4a/itunesgrpbox.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +#include "itunesgrpbox.h" +#include "itunesdatabox.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "tfile.h" +#include "mp4tagsproxy.h" + +using namespace TagLib; + +class MP4::ITunesGrpBox::ITunesGrpBoxPrivate +{ +public: + ITunesDataBox* dataBox; +}; + +MP4::ITunesGrpBox::ITunesGrpBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesGrpBox::ITunesGrpBoxPrivate(); + d->dataBox = 0; +} + +MP4::ITunesGrpBox::~ITunesGrpBox() +{ + if( d->dataBox != 0 ) + delete d->dataBox; + delete d; +} + +//! parse the content of the box +void MP4::ITunesGrpBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast( file() ); + + // parse data box + TagLib::uint size; + MP4::Fourcc fourcc; + + if(mp4file->readSizeAndType( size, fourcc ) == true) + { + // check for type - must be 'data' + if( fourcc != MP4::Fourcc("data") ) + { + std::cerr << "bad atom in itunes tag - skipping it." << std::endl; + // jump over data tag + mp4file->seek( size-8, TagLib::File::Current ); + return; + } + d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() ); + d->dataBox->parsebox(); + } + else + { + // reading unsuccessful - serious error! + std::cerr << "Error in parsing ITunesGrpBox - serious Error in taglib!" << std::endl; + return; + } + // register data box + mp4file->tagProxy()->registerBox( Mp4TagsProxy::grouping, d->dataBox ); + +#if 0 + // get data pointer - just for debugging... + TagLib::String dataString( d->dataBox->data() ); + std::cout << "Content of title box: " << dataString << std::endl; +#endif +} + diff --git a/src/metadata/m4a/itunesgrpbox.h b/src/metadata/m4a/itunesgrpbox.h new file mode 100644 index 0000000..62922f0 --- /dev/null +++ b/src/metadata/m4a/itunesgrpbox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESGRPBOX_H +#define ITUNESGRPBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesGrpBox: public Mp4IsoBox + { + public: + ITunesGrpBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesGrpBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesGrpBoxPrivate; + ITunesGrpBoxPrivate* d; + }; // class ITunesGrpBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESGRPBOX_H diff --git a/src/metadata/m4a/itunesnambox.cpp b/src/metadata/m4a/itunesnambox.cpp new file mode 100644 index 0000000..6cc954b --- /dev/null +++ b/src/metadata/m4a/itunesnambox.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +#include "itunesnambox.h" +#include "itunesdatabox.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "tfile.h" +#include "mp4tagsproxy.h" + +using namespace TagLib; + +class MP4::ITunesNamBox::ITunesNamBoxPrivate +{ +public: + ITunesDataBox* dataBox; +}; + +MP4::ITunesNamBox::ITunesNamBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesNamBox::ITunesNamBoxPrivate(); + d->dataBox = 0; +} + +MP4::ITunesNamBox::~ITunesNamBox() +{ + if( d->dataBox != 0 ) + delete d->dataBox; + delete d; +} + +//! parse the content of the box +void MP4::ITunesNamBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast( file() ); + + // parse data box + TagLib::uint size; + MP4::Fourcc fourcc; + + if(mp4file->readSizeAndType( size, fourcc ) == true) + { + // check for type - must be 'data' + if( fourcc != MP4::Fourcc("data") ) + { + std::cerr << "bad atom in itunes tag - skipping it." << std::endl; + // jump over data tag + mp4file->seek( size-8, TagLib::File::Current ); + return; + } + d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() ); + d->dataBox->parsebox(); + } + else + { + // reading unsuccessful - serious error! + std::cerr << "Error in parsing ITunesNamBox - serious Error in taglib!" << std::endl; + return; + } + // register data box + mp4file->tagProxy()->registerBox( Mp4TagsProxy::title, d->dataBox ); + +#if 0 + // get data pointer - just for debugging... + TagLib::String dataString( d->dataBox->data() ); + std::cout << "Content of title box: " << dataString << std::endl; +#endif +} + diff --git a/src/metadata/m4a/itunesnambox.h b/src/metadata/m4a/itunesnambox.h new file mode 100644 index 0000000..434fd84 --- /dev/null +++ b/src/metadata/m4a/itunesnambox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESNAMBOX_H +#define ITUNESNAMBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesNamBox: public Mp4IsoBox + { + public: + ITunesNamBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesNamBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesNamBoxPrivate; + ITunesNamBoxPrivate* d; + }; // class ITunesNamBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESNAMBOX_H diff --git a/src/metadata/m4a/itunestmpobox.cpp b/src/metadata/m4a/itunestmpobox.cpp new file mode 100644 index 0000000..3d0ad2d --- /dev/null +++ b/src/metadata/m4a/itunestmpobox.cpp @@ -0,0 +1,93 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +#include "itunestmpobox.h" +#include "itunesdatabox.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "tfile.h" +#include "mp4tagsproxy.h" + +using namespace TagLib; + +class MP4::ITunesTmpoBox::ITunesTmpoBoxPrivate +{ +public: + ITunesDataBox* dataBox; +}; + +MP4::ITunesTmpoBox::ITunesTmpoBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesTmpoBox::ITunesTmpoBoxPrivate(); + d->dataBox = 0; +} + +MP4::ITunesTmpoBox::~ITunesTmpoBox() +{ + if( d->dataBox != 0 ) + delete d->dataBox; + delete d; +} + +//! parse the content of the box +void MP4::ITunesTmpoBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast( file() ); + + // parse data box + TagLib::uint size; + MP4::Fourcc fourcc; + + if(mp4file->readSizeAndType( size, fourcc ) == true) + { + // check for type - must be 'data' + if( fourcc != MP4::Fourcc("data") ) + { + std::cerr << "bad atom in itunes tag - skipping it." << std::endl; + // jump over data tag + mp4file->seek( size-8, TagLib::File::Current ); + return; + } + d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() ); + d->dataBox->parsebox(); + } + else + { + // reading unsuccessful - serious error! + std::cerr << "Error in parsing ITunesTmpoBox - serious Error in taglib!" << std::endl; + return; + } + // register data box + mp4file->tagProxy()->registerBox( Mp4TagsProxy::bpm, d->dataBox ); + +#if 0 + // get data pointer - just for debugging... + TagLib::ByteVector trknData = d->dataBox->data(); + TagLib::String trknumber = TagLib::String::number( static_cast( static_cast(trknData[0]) << 24 | + static_cast(trknData[1]) << 16 | + static_cast(trknData[2]) << 8 | + static_cast(trknData[3]) ) ); + std::cout << "Content of tracknumber box: " << trknumber << std::endl; +#endif +} + diff --git a/src/metadata/m4a/itunestmpobox.h b/src/metadata/m4a/itunestmpobox.h new file mode 100644 index 0000000..981f938 --- /dev/null +++ b/src/metadata/m4a/itunestmpobox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESTMPOBOX_H +#define ITUNESTMPOBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesTmpoBox: public Mp4IsoBox + { + public: + ITunesTmpoBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesTmpoBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesTmpoBoxPrivate; + ITunesTmpoBoxPrivate* d; + }; // class ITunesTmpoBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESTMPOBOX_H diff --git a/src/metadata/m4a/itunestrknbox.cpp b/src/metadata/m4a/itunestrknbox.cpp new file mode 100644 index 0000000..f8d36cb --- /dev/null +++ b/src/metadata/m4a/itunestrknbox.cpp @@ -0,0 +1,93 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +#include "itunestrknbox.h" +#include "itunesdatabox.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "tfile.h" +#include "mp4tagsproxy.h" + +using namespace TagLib; + +class MP4::ITunesTrknBox::ITunesTrknBoxPrivate +{ +public: + ITunesDataBox* dataBox; +}; + +MP4::ITunesTrknBox::ITunesTrknBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesTrknBox::ITunesTrknBoxPrivate(); + d->dataBox = 0; +} + +MP4::ITunesTrknBox::~ITunesTrknBox() +{ + if( d->dataBox != 0 ) + delete d->dataBox; + delete d; +} + +//! parse the content of the box +void MP4::ITunesTrknBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast( file() ); + + // parse data box + TagLib::uint size; + MP4::Fourcc fourcc; + + if(mp4file->readSizeAndType( size, fourcc ) == true) + { + // check for type - must be 'data' + if( fourcc != MP4::Fourcc("data") ) + { + std::cerr << "bad atom in itunes tag - skipping it." << std::endl; + // jump over data tag + mp4file->seek( size-8, TagLib::File::Current ); + return; + } + d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() ); + d->dataBox->parsebox(); + } + else + { + // reading unsuccessful - serious error! + std::cerr << "Error in parsing ITunesTrknBox - serious Error in taglib!" << std::endl; + return; + } + // register data box + mp4file->tagProxy()->registerBox( Mp4TagsProxy::trackno, d->dataBox ); + +#if 0 + // get data pointer - just for debugging... + TagLib::ByteVector trknData = d->dataBox->data(); + TagLib::String trknumber = TagLib::String::number( static_cast( static_cast(trknData[0]) << 24 | + static_cast(trknData[1]) << 16 | + static_cast(trknData[2]) << 8 | + static_cast(trknData[3]) ) ); + std::cout << "Content of tracknumber box: " << trknumber << std::endl; +#endif +} + diff --git a/src/metadata/m4a/itunestrknbox.h b/src/metadata/m4a/itunestrknbox.h new file mode 100644 index 0000000..f603e1f --- /dev/null +++ b/src/metadata/m4a/itunestrknbox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESTRKNBOX_H +#define ITUNESTRKNBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesTrknBox: public Mp4IsoBox + { + public: + ITunesTrknBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesTrknBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesTrknBoxPrivate; + ITunesTrknBoxPrivate* d; + }; // class ITunesTrknBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESTRKNBOX_H diff --git a/src/metadata/m4a/ituneswrtbox.cpp b/src/metadata/m4a/ituneswrtbox.cpp new file mode 100644 index 0000000..ecf3c43 --- /dev/null +++ b/src/metadata/m4a/ituneswrtbox.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +#include "ituneswrtbox.h" +#include "itunesdatabox.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "tfile.h" +#include "mp4tagsproxy.h" + +using namespace TagLib; + +class MP4::ITunesWrtBox::ITunesWrtBoxPrivate +{ +public: + ITunesDataBox* dataBox; +}; + +MP4::ITunesWrtBox::ITunesWrtBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesWrtBox::ITunesWrtBoxPrivate(); + d->dataBox = 0; +} + +MP4::ITunesWrtBox::~ITunesWrtBox() +{ + if( d->dataBox != 0 ) + delete d->dataBox; + delete d; +} + +//! parse the content of the box +void MP4::ITunesWrtBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast( file() ); + + // parse data box + TagLib::uint size; + MP4::Fourcc fourcc; + + if(mp4file->readSizeAndType( size, fourcc ) == true) + { + // check for type - must be 'data' + if( fourcc != MP4::Fourcc("data") ) + { + std::cerr << "bad atom in itunes tag - skipping it." << std::endl; + // jump over data tag + mp4file->seek( size-8, TagLib::File::Current ); + return; + } + d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() ); + d->dataBox->parsebox(); + } + else + { + // reading unsuccessful - serious error! + std::cerr << "Error in parsing ITunesWrtBox - serious Error in taglib!" << std::endl; + return; + } + // register data box + mp4file->tagProxy()->registerBox( Mp4TagsProxy::composer, d->dataBox ); + +#if 0 + // get data pointer - just for debugging... + TagLib::String dataString( d->dataBox->data() ); + std::cout << "Content of title box: " << dataString << std::endl; +#endif +} + diff --git a/src/metadata/m4a/ituneswrtbox.h b/src/metadata/m4a/ituneswrtbox.h new file mode 100644 index 0000000..740d94c --- /dev/null +++ b/src/metadata/m4a/ituneswrtbox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESWRTBOX_H +#define ITUNESWRTBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesWrtBox: public Mp4IsoBox + { + public: + ITunesWrtBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesWrtBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesWrtBoxPrivate; + ITunesWrtBoxPrivate* d; + }; // class ITunesWrtBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESWRTBOX_H diff --git a/src/metadata/m4a/mp4audioproperties.cpp b/src/metadata/m4a/mp4audioproperties.cpp new file mode 100644 index 0000000..77afab1 --- /dev/null +++ b/src/metadata/m4a/mp4audioproperties.cpp @@ -0,0 +1,75 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "mp4audioproperties.h" +#include "mp4propsproxy.h" + +using namespace TagLib; + +class MP4::AudioProperties::AudioPropertiesPrivate +{ +public: + MP4::Mp4PropsProxy* propsproxy; +}; // AudioPropertiesPrivate + +MP4::AudioProperties::AudioProperties():TagLib::AudioProperties(TagLib::AudioProperties::Average) +{ + d = new MP4::AudioProperties::AudioPropertiesPrivate(); +} + +MP4::AudioProperties::~AudioProperties() +{ + delete d; +} + +void MP4::AudioProperties::setProxy( Mp4PropsProxy* proxy ) +{ + d->propsproxy = proxy; +} + +int MP4::AudioProperties::length() const +{ + if( d->propsproxy == 0 ) + return 0; + return d->propsproxy->seconds(); +} + +int MP4::AudioProperties::bitrate() const +{ + if( d->propsproxy == 0 ) + return 0; + return d->propsproxy->bitRate()/1000; +} + +int MP4::AudioProperties::sampleRate() const +{ + if( d->propsproxy == 0 ) + return 0; + return d->propsproxy->sampleRate(); +} + +int MP4::AudioProperties::channels() const +{ + if( d->propsproxy == 0 ) + return 0; + return d->propsproxy->channels(); +} + diff --git a/src/metadata/m4a/mp4audioproperties.h b/src/metadata/m4a/mp4audioproperties.h new file mode 100644 index 0000000..4e61790 --- /dev/null +++ b/src/metadata/m4a/mp4audioproperties.h @@ -0,0 +1,73 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4AUDIOPROPERTIES_H +#define MP4AUDIOPROPERTIES_H MP4AUDIOPROPERTIES_H + +#include "audioproperties.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4PropsProxy; + + class AudioProperties : public TagLib::AudioProperties + { + public: + //! constructor + AudioProperties(); + //! destructor + ~AudioProperties(); + + //! function to set the proxy + void setProxy( Mp4PropsProxy* proxy ); + + /*! + * Returns the length of the file in seconds. + */ + int length() const; + + /*! + * Returns the most appropriate bit rate for the file in kb/s. For constant + * bitrate formats this is simply the bitrate of the file. For variable + * bitrate formats this is either the average or nominal bitrate. + */ + int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + int channels() const; + + private: + class AudioPropertiesPrivate; + AudioPropertiesPrivate* d; + }; + } // namespace MP4 +} // namespace TagLib + +#endif // MP4AUDIOPROPERTIES_H diff --git a/src/metadata/m4a/mp4audiosampleentry.cpp b/src/metadata/m4a/mp4audiosampleentry.cpp new file mode 100644 index 0000000..fb87547 --- /dev/null +++ b/src/metadata/m4a/mp4audiosampleentry.cpp @@ -0,0 +1,146 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +#include "mp4audiosampleentry.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "mp4propsproxy.h" + +using namespace TagLib; + +class MP4::Mp4AudioSampleEntry::Mp4AudioSampleEntryPrivate +{ +public: + TagLib::uint channelcount; + TagLib::uint samplerate; + TagLib::uint bitrate; +}; + +MP4::Mp4AudioSampleEntry::Mp4AudioSampleEntry( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4SampleEntry(file, fourcc, size, offset) +{ + d = new MP4::Mp4AudioSampleEntry::Mp4AudioSampleEntryPrivate(); +} + +MP4::Mp4AudioSampleEntry::~Mp4AudioSampleEntry() +{ + delete d; +} + +TagLib::uint MP4::Mp4AudioSampleEntry::channels() const +{ + return d->channelcount; +} + +TagLib::uint MP4::Mp4AudioSampleEntry::samplerate() const +{ + return d->samplerate; +} + +TagLib::uint MP4::Mp4AudioSampleEntry::bitrate() const +{ + return d->bitrate; +} + +void MP4::Mp4AudioSampleEntry::parseEntry() +{ + TagLib::MP4::File* mp4file = dynamic_cast(file()); + if(!mp4file) + return; + + // read 8 reserved bytes + mp4file->seek( 8, TagLib::File::Current ); + // read channelcount + if(!mp4file->readShort( d->channelcount )) + return; + // seek over samplesize, pre_defined and reserved + mp4file->seek( 6, TagLib::File::Current ); + // read samplerate + if(!mp4file->readInt( d->samplerate )) + return; + + // register box at proxy + mp4file->propProxy()->registerAudioSampleEntry( this ); + + + //std::cout << "fourcc of audio sample entry: " << fourcc().toString() << std::endl; + // check for both mp4a (plain files) and drms (encrypted files) + if( (fourcc() == MP4::Fourcc("mp4a")) || + (fourcc() == MP4::Fourcc("drms")) ) + { + TagLib::MP4::Fourcc fourcc; + TagLib::uint esds_size; + + if (!mp4file->readSizeAndType( esds_size, fourcc )) + return; + + // read esds' main parts + if( size()-48 > 0 ) + ByteVector flags_version = mp4file->readBlock(4); + else + return; + + ByteVector EsDescrTag = mp4file->readBlock(1); + // first 4 bytes contain full box specifics (version & flags) + // upcoming byte must be ESDescrTag (0x03) + if( EsDescrTag[0] == 0x03 ) + { + TagLib::uint descr_len = mp4file->readSystemsLen(); + TagLib::uint EsId; + if( !mp4file->readShort( EsId ) ) + return; + ByteVector priority = mp4file->readBlock(1); + if( descr_len < 20 ) + return; + } + else + { + TagLib::uint EsId; + if( !mp4file->readShort( EsId ) ) + return; + } + // read decoder configuration tag (0x04) + ByteVector DecCfgTag = mp4file->readBlock(1); + if( DecCfgTag[0] != 0x04 ) + return; + // read decoder configuration length + // TagLib::uint deccfg_len = mp4file->readSystemsLen(); + // read object type Id + ByteVector objId = mp4file->readBlock(1); + // read stream type id + ByteVector strId = mp4file->readBlock(1); + // read buffer Size DB + ByteVector bufferSizeDB = mp4file->readBlock(3); + // read max bitrate + TagLib::uint max_bitrate; + if( !mp4file->readInt( max_bitrate ) ) + return; + // read average bitrate + if( !mp4file->readInt( d->bitrate ) ) + return; + // skip the rest + mp4file->seek( offset()+size()-8, File::Beginning ); + } + else + mp4file->seek( size()-36, File::Current ); +} + diff --git a/src/metadata/m4a/mp4audiosampleentry.h b/src/metadata/m4a/mp4audiosampleentry.h new file mode 100644 index 0000000..c39c5e3 --- /dev/null +++ b/src/metadata/m4a/mp4audiosampleentry.h @@ -0,0 +1,57 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4AUDIOSAMPLEENTRY_H +#define MP4AUDIOSAMPLEENTRY_H + +#include "mp4sampleentry.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4AudioSampleEntry: public Mp4SampleEntry + { + public: + Mp4AudioSampleEntry( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~Mp4AudioSampleEntry(); + + //! function to get the number of channels + TagLib::uint channels() const; + //! function to get the sample rate + TagLib::uint samplerate() const; + //! function to get the average bitrate of the audio stream + TagLib::uint bitrate() const; + + private: + //! parse the content of the box + void parseEntry(); + + protected: + class Mp4AudioSampleEntryPrivate; + Mp4AudioSampleEntryPrivate* d; + }; // class Mp4AudioSampleEntry + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4AUDIOSAMPLEENTRY_H diff --git a/src/metadata/m4a/mp4file.cpp b/src/metadata/m4a/mp4file.cpp new file mode 100644 index 0000000..7d37d59 --- /dev/null +++ b/src/metadata/m4a/mp4file.cpp @@ -0,0 +1,377 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +#include +#include "tlist.h" + +#include "mp4itunestag.h" +#include "mp4file.h" +#include "boxfactory.h" +#include "mp4tagsproxy.h" +#include "mp4propsproxy.h" +#include "mp4audioproperties.h" +#include "itunesdatabox.h" + +using namespace TagLib; + +class MP4::File::FilePrivate +{ +public: + //! list for all boxes of the mp4 file + TagLib::List boxes; + //! the box factory - will create all boxes by tag and size + MP4::BoxFactory boxfactory; + //! proxy for the tags is filled after parsing + MP4::Mp4TagsProxy tagsProxy; + //! proxy for audio properties + MP4::Mp4PropsProxy propsProxy; + //! the tag returned by tag() function + MP4::Tag mp4tag; + //! container for the audio properties returned by properties() function + MP4::AudioProperties mp4audioproperties; + //! is set to valid after successfully parsing + bool isValid; +}; + +//! function to fill the tags with converted proxy data, which has been parsed out of the file previously +static void fillTagFromProxy( MP4::Mp4TagsProxy& proxy, MP4::Tag& mp4tag ); + +MP4::File::File(const char *file, bool , AudioProperties::ReadStyle ) + :TagLib::File( file ) +{ + // create member container + d = new MP4::File::FilePrivate(); + + + d->isValid = false; + TagLib::uint size; + MP4::Fourcc fourcc; + + while( readSizeAndType( size, fourcc ) == true ) + { + // create the appropriate subclass and parse it + MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( this, fourcc, size, tell() ); + curbox->parsebox(); + d->boxes.append( curbox ); + } + + for( TagLib::List::Iterator iter = d->boxes.begin(); + iter != d->boxes.end(); + iter++ ) + { + if( (*iter)->fourcc() == MP4::Fourcc("moov") ) + { + d->isValid = true; + break; + } + } + + //if( d->isValid ) + //debug( "file is valid" ); + //else + //debug( "file is NOT valid" ); + + // fill tags from proxy data + fillTagFromProxy( d->tagsProxy, d->mp4tag ); +} + +MP4::File::~File() +{ + TagLib::List::Iterator delIter; + for( delIter = d->boxes.begin(); + delIter != d->boxes.end(); + delIter++ ) + { + delete *delIter; + } + delete d; +} + +Tag *MP4::File::tag() const +{ + return &d->mp4tag; +} + +AudioProperties * MP4::File::audioProperties() const +{ + d->mp4audioproperties.setProxy( &d->propsProxy ); + return &d->mp4audioproperties; +} + +bool MP4::File::save() +{ + return false; +} + +void MP4::File::remove() +{ +} + +TagLib::uint MP4::File::readSystemsLen() +{ + TagLib::uint length = 0; + TagLib::uint nbytes = 0; + ByteVector input; + TagLib::uchar tmp_input; + + do + { + input = readBlock(1); + tmp_input = static_cast(input[0]); + nbytes++; + length = (length<<7) | (tmp_input&0x7F); + } while( (tmp_input&0x80) && (nbytes<4) ); + + return length; +} + +bool MP4::File::readSizeAndType( TagLib::uint& size, MP4::Fourcc& fourcc ) +{ + // read the two blocks from file + ByteVector readsize = readBlock(4); + ByteVector readtype = readBlock(4); + + if( (readsize.size() != 4) || (readtype.size() != 4) ) + return false; + + // set size + size = static_cast(readsize[0]) << 24 | + static_cast(readsize[1]) << 16 | + static_cast(readsize[2]) << 8 | + static_cast(readsize[3]); + + // type and size seem to be part of the stored size + if( size < 8 ) + return false; + + // set fourcc + fourcc = readtype.data(); + + return true; +} + +bool MP4::File::readInt( TagLib::uint& toRead ) +{ + ByteVector readbuffer = readBlock(4); + if( readbuffer.size() != 4 ) + return false; + + toRead = static_cast(readbuffer[0]) << 24 | + static_cast(readbuffer[1]) << 16 | + static_cast(readbuffer[2]) << 8 | + static_cast(readbuffer[3]); + return true; +} + +bool MP4::File::readShort( TagLib::uint& toRead ) +{ + ByteVector readbuffer = readBlock(2); + if( readbuffer.size() != 2 ) + return false; + + toRead = static_cast(readbuffer[0]) << 8 | + static_cast(readbuffer[1]); + return true; +} + +bool MP4::File::readLongLong( TagLib::ulonglong& toRead ) +{ + ByteVector readbuffer = readBlock(8); + if( readbuffer.size() != 8 ) + return false; + + toRead = static_cast(static_cast(readbuffer[0])) << 56 | + static_cast(static_cast(readbuffer[1])) << 48 | + static_cast(static_cast(readbuffer[2])) << 40 | + static_cast(static_cast(readbuffer[3])) << 32 | + static_cast(static_cast(readbuffer[4])) << 24 | + static_cast(static_cast(readbuffer[5])) << 16 | + static_cast(static_cast(readbuffer[6])) << 8 | + static_cast(static_cast(readbuffer[7])); + return true; +} + +bool MP4::File::readFourcc( TagLib::MP4::Fourcc& fourcc ) +{ + ByteVector readtype = readBlock(4); + + if( readtype.size() != 4) + return false; + + // set fourcc + fourcc = readtype.data(); + + return true; +} + +MP4::Mp4TagsProxy* MP4::File::tagProxy() const +{ + return &d->tagsProxy; +} + +MP4::Mp4PropsProxy* MP4::File::propProxy() const +{ + return &d->propsProxy; +} + +void fillTagFromProxy( MP4::Mp4TagsProxy& proxy, MP4::Tag& mp4tag ) +{ + // tmp buffer for each tag + MP4::ITunesDataBox* databox; + + databox = proxy.titleData(); + if( databox != 0 ) + { + // convert data to string + TagLib::String datastring( databox->data(), String::UTF8 ); + // check if string was set + if( !datastring.isEmpty() ) + mp4tag.setTitle( datastring ); + } + + databox = proxy.artistData(); + if( databox != 0 ) + { + // convert data to string + TagLib::String datastring( databox->data(), String::UTF8 ); + // check if string was set + if( !datastring.isEmpty() ) + mp4tag.setArtist( datastring ); + } + + databox = proxy.albumData(); + if( databox != 0 ) + { + // convert data to string + TagLib::String datastring( databox->data(), String::UTF8 ); + // check if string was set + if( !datastring.isEmpty() ) + mp4tag.setAlbum( datastring ); + } + + databox = proxy.genreData(); + if( databox != 0 ) + { + // convert data to string + TagLib::String datastring( databox->data(), String::UTF8 ); + // check if string was set + if( !datastring.isEmpty() ) + mp4tag.setGenre( datastring ); + } + + databox = proxy.yearData(); + if( databox != 0 ) + { + // convert data to string + TagLib::String datastring( databox->data(), String::UTF8 ); + // check if string was set + if( !datastring.isEmpty() ) + mp4tag.setYear( datastring.toInt() ); + } + + databox = proxy.trknData(); + if( databox != 0 ) + { + // convert data to uint + TagLib::ByteVector datavec = databox->data(); + if( datavec.size() >= 4 ) + { + TagLib::uint trackno = static_cast( static_cast(datavec[0]) << 24 | + static_cast(datavec[1]) << 16 | + static_cast(datavec[2]) << 8 | + static_cast(datavec[3]) ); + mp4tag.setTrack( trackno ); + } + else + mp4tag.setTrack( 0 ); + } + + databox = proxy.commentData(); + if( databox != 0 ) + { + // convert data to string + TagLib::String datastring( databox->data(), String::UTF8 ); + // check if string was set + if( !datastring.isEmpty() ) + mp4tag.setComment( datastring ); + } + + databox = proxy.groupingData(); + if( databox != 0 ) + { + // convert data to string + TagLib::String datastring( databox->data(), String::UTF8 ); + // check if string was set + if( !datastring.isEmpty() ) + mp4tag.setGrouping( datastring ); + } + + databox = proxy.composerData(); + if( databox != 0 ) + { + // convert data to string + TagLib::String datastring( databox->data(), String::UTF8 ); + // check if string was set + if( !datastring.isEmpty() ) + mp4tag.setComposer( datastring ); + } + + databox = proxy.diskData(); + if( databox != 0 ) + { + // convert data to uint + TagLib::ByteVector datavec = databox->data(); + if( datavec.size() >= 4 ) + { + TagLib::uint discno = static_cast( static_cast(datavec[0]) << 24 | + static_cast(datavec[1]) << 16 | + static_cast(datavec[2]) << 8 | + static_cast(datavec[3]) ); + mp4tag.setDisk( discno ); + } + else + mp4tag.setDisk( 0 ); + } + + databox = proxy.bpmData(); + if( databox != 0 ) + { + // convert data to uint + TagLib::ByteVector datavec = databox->data(); + + if( datavec.size() >= 2 ) + { + TagLib::uint bpm = static_cast( static_cast(datavec[0]) << 8 | + static_cast(datavec[1]) ); + mp4tag.setBpm( bpm ); + } + else + mp4tag.setBpm( 0 ); + } + + databox = proxy.coverData(); + if( databox != 0 ) + { + // get byte vector + mp4tag.setCover( databox->data() ); + } +} diff --git a/src/metadata/m4a/mp4file.h b/src/metadata/m4a/mp4file.h new file mode 100644 index 0000000..9e40dbc --- /dev/null +++ b/src/metadata/m4a/mp4file.h @@ -0,0 +1,169 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +/*************************************************************************** + copyright : (C) 2002, 2003 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * + * USA * + ***************************************************************************/ + +#ifndef TAGLIB_MP4FILE_H +#define TAGLIB_MP4FILE_H + +#include +#include + +#include "mp4fourcc.h" + +namespace TagLib { + + typedef unsigned long long ulonglong; + + class Tag; + + namespace MP4 + { + class Mp4TagsProxy; + class Mp4PropsProxy; + + //! An implementation of TagLib::File with mp4 itunes specific methods + + /*! + * This implements and provides an interface for mp4 itunes files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to mp4 itunes files. (TODO) + */ + + class File : public TagLib::File + { + public: + /*! + * Contructs an mp4 itunes file from \a file. If \a readProperties is true the + * file's audio properties will also be read using \a propertiesStyle. If + * false, \a propertiesStyle is ignored. + */ + File(const char *file, bool readProperties = true, + AudioProperties::ReadStyle propertiesStyle = AudioProperties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. This will be an APE tag, an ID3v1 tag + * or a combination of the two. + */ + virtual TagLib::Tag *tag() const; + + /*! + * Returns the mp4 itunes::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual AudioProperties *audioProperties() const; + + /*! + * Saves the file. + */ + virtual bool save(); + + /*! + * This will remove all tags. + * + * \note This will also invalidate pointers to the tags + * as their memory will be freed. + * \note In order to make the removal permanent save() still needs to be called + */ + void remove(); + + /*! + * Helper function for parsing the MP4 file - reads the size and type of the next box. + * Returns true if read succeeded - not at EOF + */ + bool readSizeAndType( TagLib::uint& size, MP4::Fourcc& fourcc ); + + /*! + * Helper function to read the length of an descriptor in systems manner + */ + TagLib::uint readSystemsLen(); + + /*! + * Helper function for reading an unsigned int out of the file (big endian method) + */ + bool readInt( TagLib::uint& toRead ); + + /*! + * Helper function for reading an unsigned short out of the file (big endian method) + */ + bool readShort( TagLib::uint& toRead ); + + /*! + * Helper function for reading an unsigned long long (64bit) out of the file (big endian method) + */ + bool readLongLong( TagLib::ulonglong& toRead ); + + /*! + * Helper function to read a fourcc code + */ + bool readFourcc( TagLib::MP4::Fourcc& fourcc ); + + /*! + * Function to get the tags proxy for registration of the tags boxes. + * The proxy provides direct access to the data boxes of the certain tags - normally + * covered by several levels of subboxes + */ + Mp4TagsProxy* tagProxy() const; + + /*! + * Function to get the properties proxy for registration of the properties boxes. + * The proxy provides direct access to the needed boxes describing audio properties. + */ + Mp4PropsProxy* propProxy() const; + + private: + File(const File &); + File &operator=(const File &); + + class FilePrivate; + FilePrivate *d; + }; + + } // namespace MP4 + +} // namespace TagLib + +#endif // TAGLIB_MP4FILE_H diff --git a/src/metadata/m4a/mp4fourcc.cpp b/src/metadata/m4a/mp4fourcc.cpp new file mode 100644 index 0000000..dac0f99 --- /dev/null +++ b/src/metadata/m4a/mp4fourcc.cpp @@ -0,0 +1,84 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "mp4fourcc.h" + +using namespace TagLib; + +MP4::Fourcc::Fourcc() +{ + m_fourcc = 0U; +} + +MP4::Fourcc::Fourcc( TagLib::String fourcc ) +{ + m_fourcc = 0U; + + if( fourcc.size() >= 4 ) + m_fourcc = static_cast(fourcc[0]) << 24 | + static_cast(fourcc[1]) << 16 | + static_cast(fourcc[2]) << 8 | + static_cast(fourcc[3]); +} + +MP4::Fourcc::~Fourcc() +{} + +TagLib::String MP4::Fourcc::toString() const +{ + TagLib::String fourcc; + fourcc.append(static_cast(m_fourcc >> 24 & 0xFF)); + fourcc.append(static_cast(m_fourcc >> 16 & 0xFF)); + fourcc.append(static_cast(m_fourcc >> 8 & 0xFF)); + fourcc.append(static_cast(m_fourcc & 0xFF)); + + return fourcc; +} + +MP4::Fourcc::operator unsigned int() const +{ + return m_fourcc; +} + +bool MP4::Fourcc::operator == (unsigned int fourccB ) const +{ + return (m_fourcc==fourccB); +} + +bool MP4::Fourcc::operator != (unsigned int fourccB ) const +{ + return (m_fourcc!=fourccB); +} + +MP4::Fourcc& MP4::Fourcc::operator = (unsigned int fourcc ) +{ + m_fourcc = fourcc; + return *this; +} + +MP4::Fourcc& MP4::Fourcc::operator = (char fourcc[4]) +{ + m_fourcc = static_cast(fourcc[0]) << 24 | + static_cast(fourcc[1]) << 16 | + static_cast(fourcc[2]) << 8 | + static_cast(fourcc[3]); + return *this; +} diff --git a/src/metadata/m4a/mp4fourcc.h b/src/metadata/m4a/mp4fourcc.h new file mode 100644 index 0000000..90e498a --- /dev/null +++ b/src/metadata/m4a/mp4fourcc.h @@ -0,0 +1,63 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4FOURCC_H +#define MP4FOURCC_H + +#include "tstring.h" + +namespace TagLib +{ + namespace MP4 + { + /*! union for easy fourcc / type handling */ + class Fourcc + { + public: + //! std constructor + Fourcc(); + //! string constructor + Fourcc(TagLib::String fourcc); + + //! destructor + ~Fourcc(); + + //! function to get a string version of the fourcc + TagLib::String toString() const; + //! cast operator to unsigned int + operator unsigned int() const; + //! comparison operator + bool operator == (unsigned int fourccB ) const; + //! comparison operator + bool operator != (unsigned int fourccB ) const; + //! assigment operator for unsigned int + Fourcc& operator = (unsigned int fourcc ); + //! assigment operator for character string + Fourcc& operator = (char fourcc[4]); + + private: + uint m_fourcc; /*!< integer code of the fourcc */ + }; + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4FOURCC_H diff --git a/src/metadata/m4a/mp4hdlrbox.cpp b/src/metadata/m4a/mp4hdlrbox.cpp new file mode 100644 index 0000000..a3ec5f7 --- /dev/null +++ b/src/metadata/m4a/mp4hdlrbox.cpp @@ -0,0 +1,75 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +#include +#include "mp4hdlrbox.h" +#include "boxfactory.h" +#include "mp4file.h" + +using namespace TagLib; + +class MP4::Mp4HdlrBox::Mp4HdlrBoxPrivate +{ +public: + TagLib::uint pre_defined; + MP4::Fourcc handler_type; + TagLib::String hdlr_string; +}; // class Mp4HdlrBoxPrivate + +MP4::Mp4HdlrBox::Mp4HdlrBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ) + : Mp4IsoFullBox( file, fourcc, size, offset ) +{ + d = new MP4::Mp4HdlrBox::Mp4HdlrBoxPrivate(); +} + +MP4::Mp4HdlrBox::~Mp4HdlrBox() +{ + delete d; +} + +MP4::Fourcc MP4::Mp4HdlrBox::hdlr_type() const +{ + return d->handler_type; +} + +TagLib::String MP4::Mp4HdlrBox::hdlr_string() const +{ + return d->hdlr_string; +} + +void MP4::Mp4HdlrBox::parse() +{ + TagLib::uint totalread = 12+20; + + TagLib::MP4::File* mp4file = static_cast( file() ); + if( mp4file->readInt( d->pre_defined ) == false ) + return; + if( mp4file->readFourcc( d->handler_type ) == false ) + return; + + // read reserved into trash + mp4file->seek( 3*4, TagLib::File::Current ); + + // check if there are bytes remaining - used for hdlr string + if( size() - totalread != 0 ) + d->hdlr_string = mp4file->readBlock( size()-totalread ); +} diff --git a/src/metadata/m4a/mp4hdlrbox.h b/src/metadata/m4a/mp4hdlrbox.h new file mode 100644 index 0000000..0a6bf54 --- /dev/null +++ b/src/metadata/m4a/mp4hdlrbox.h @@ -0,0 +1,53 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4HDLRBOX_H +#define MP4HDLRBOX_H + +#include "mp4isofullbox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4HdlrBox: public Mp4IsoFullBox + { + public: + Mp4HdlrBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ); + ~Mp4HdlrBox(); + + //! parse hdlr contents + void parse(); + //! get the handler type + MP4::Fourcc hdlr_type() const; + //! get the hdlr string + TagLib::String hdlr_string() const; + + private: + class Mp4HdlrBoxPrivate; + Mp4HdlrBoxPrivate* d; + }; // Mp4HdlrBox + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4HDLRBOX_H diff --git a/src/metadata/m4a/mp4ilstbox.cpp b/src/metadata/m4a/mp4ilstbox.cpp new file mode 100644 index 0000000..1d5ae9a --- /dev/null +++ b/src/metadata/m4a/mp4ilstbox.cpp @@ -0,0 +1,97 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "tlist.h" +#include +#include "mp4ilstbox.h" +#include "boxfactory.h" +#include "mp4file.h" + +using namespace TagLib; + +class MP4::Mp4IlstBox::Mp4IlstBoxPrivate +{ +public: + //! container for all boxes in ilst box + TagLib::List ilstBoxes; + //! a box factory for creating the appropriate boxes + MP4::BoxFactory boxfactory; +}; // class Mp4IlstBoxPrivate + +MP4::Mp4IlstBox::Mp4IlstBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ) + : Mp4IsoBox( file, fourcc, size, offset ) +{ + d = new MP4::Mp4IlstBox::Mp4IlstBoxPrivate(); +} + +MP4::Mp4IlstBox::~Mp4IlstBox() +{ + TagLib::List::Iterator delIter; + for( delIter = d->ilstBoxes.begin(); + delIter != d->ilstBoxes.end(); + delIter++ ) + { + delete *delIter; + } + delete d; +} + +void MP4::Mp4IlstBox::parse() +{ +#if 0 + std::cout << " parsing ilst box" << std::endl; +#endif + + TagLib::MP4::File* mp4file = static_cast( file() ); + + TagLib::uint totalsize = 8; + // parse all contained boxes + TagLib::uint size; + MP4::Fourcc fourcc; + +#if 0 + std::cout << " "; +#endif + while( (mp4file->readSizeAndType( size, fourcc ) == true) ) + { + totalsize += size; + + // check for errors + if( totalsize > MP4::Mp4IsoBox::size() ) + { + std::cerr << "Error in mp4 file " << mp4file->name() << " ilst box contains bad box with name: " << fourcc.toString() << std::endl; + return; + } + + // create the appropriate subclass and parse it + MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( mp4file, fourcc, size, mp4file->tell() ); + curbox->parsebox(); + d->ilstBoxes.append( curbox ); + + // check for end of ilst box + if( totalsize == MP4::Mp4IsoBox::size() ) + break; + +#if 0 + std::cout << " "; +#endif + } +} diff --git a/src/metadata/m4a/mp4ilstbox.h b/src/metadata/m4a/mp4ilstbox.h new file mode 100644 index 0000000..9e7ad1c --- /dev/null +++ b/src/metadata/m4a/mp4ilstbox.h @@ -0,0 +1,49 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4ILSTBOX_H +#define MP4ILSTBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4IlstBox: public Mp4IsoBox + { + public: + Mp4IlstBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ); + ~Mp4IlstBox(); + + //! parse ilst contents + void parse(); + + private: + class Mp4IlstBoxPrivate; + Mp4IlstBoxPrivate* d; + }; // Mp4IlstBox + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4ILSTBOX_H diff --git a/src/metadata/m4a/mp4isobox.cpp b/src/metadata/m4a/mp4isobox.cpp new file mode 100644 index 0000000..7f08924 --- /dev/null +++ b/src/metadata/m4a/mp4isobox.cpp @@ -0,0 +1,76 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "mp4isobox.h" +#include "tfile.h" + +using namespace TagLib; + +class MP4::Mp4IsoBox::Mp4IsoBoxPrivate +{ +public: + MP4::Fourcc fourcc; + TagLib::uint size; + long offset; + TagLib::File* file; +}; + +MP4::Mp4IsoBox::Mp4IsoBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ) +{ + d = new MP4::Mp4IsoBox::Mp4IsoBoxPrivate(); + d->file = file; + d->fourcc = fourcc; + d->size = size; + d->offset = offset; +} + +MP4::Mp4IsoBox::~Mp4IsoBox() +{ + delete d; +} + +void MP4::Mp4IsoBox::parsebox() +{ + // seek to offset + file()->seek( offset(), File::Beginning ); + // simply call parse method of sub class + parse(); +} + +MP4::Fourcc MP4::Mp4IsoBox::fourcc() const +{ + return d->fourcc; +} + +TagLib::uint MP4::Mp4IsoBox::size() const +{ + return d->size; +} + +long MP4::Mp4IsoBox::offset() const +{ + return d->offset; +} + +TagLib::File* MP4::Mp4IsoBox::file() const +{ + return d->file; +} diff --git a/src/metadata/m4a/mp4isobox.h b/src/metadata/m4a/mp4isobox.h new file mode 100644 index 0000000..4d4edc9 --- /dev/null +++ b/src/metadata/m4a/mp4isobox.h @@ -0,0 +1,67 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4ISOBOX_H +#define MP4ISOBOX_H + +#include "taglib.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + class File; + + namespace MP4 + { + class Mp4IsoBox + { + public: + //! constructor for base class + Mp4IsoBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + //! destructor - simply freeing private ptr + virtual ~Mp4IsoBox(); + + //! function to get the fourcc code + MP4::Fourcc fourcc() const; + //! function to get the size of tha atom/box + uint size() const; + //! function to get the offset of the atom in the mp4 file + long offset() const; + + //! parse wrapper to get common interface for both box and fullbox + virtual void parsebox(); + //! pure virtual function for all subclasses to implement + virtual void parse() = 0; + + protected: + //! function to get the file pointer + TagLib::File* file() const; + + protected: + class Mp4IsoBoxPrivate; + Mp4IsoBoxPrivate* d; + }; + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4ISOBOX_H + diff --git a/src/metadata/m4a/mp4isofullbox.cpp b/src/metadata/m4a/mp4isofullbox.cpp new file mode 100644 index 0000000..f938ad4 --- /dev/null +++ b/src/metadata/m4a/mp4isofullbox.cpp @@ -0,0 +1,67 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "mp4isofullbox.h" +#include "tfile.h" + +using namespace TagLib; + +class MP4::Mp4IsoFullBox::Mp4IsoFullBoxPrivate +{ +public: + uchar version; + uint flags; +}; // Mp4IsoFullBoxPrivate + + +MP4::Mp4IsoFullBox::Mp4IsoFullBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) +: Mp4IsoBox( file, fourcc, size, offset ) +{ + d = new MP4::Mp4IsoFullBox::Mp4IsoFullBoxPrivate(); +} + +MP4::Mp4IsoFullBox::~Mp4IsoFullBox() +{ + delete d; +} + +void MP4::Mp4IsoFullBox::parsebox() +{ + // seek to offset + Mp4IsoBox::file()->seek(Mp4IsoBox::offset(), File::Beginning ); + // parse version and flags + ByteVector version_flags = Mp4IsoBox::file()->readBlock(4); + d->version = version_flags[0]; + d->flags = version_flags[1] << 16 || version_flags[2] << 8 || version_flags[3]; + // call parse method of subclass + parse(); +} + +TagLib::uchar MP4::Mp4IsoFullBox::version() +{ + return d->version; +} + +TagLib::uint MP4::Mp4IsoFullBox::flags() +{ + return d->flags; +} + diff --git a/src/metadata/m4a/mp4isofullbox.h b/src/metadata/m4a/mp4isofullbox.h new file mode 100644 index 0000000..bc01b61 --- /dev/null +++ b/src/metadata/m4a/mp4isofullbox.h @@ -0,0 +1,57 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4ISOFULLBOX_H +#define MP4ISOFULLBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4IsoFullBox : public Mp4IsoBox + { + public: + //! constructor for full box + Mp4IsoFullBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + //! destructor for mp4 iso full box + virtual ~Mp4IsoFullBox(); + + //! function to get the version of box + uchar version(); + //! function to get the flag map + uint flags(); + + //! parse wrapper to get common interface for both box and fullbox + virtual void parsebox(); + + protected: + class Mp4IsoFullBoxPrivate; + Mp4IsoFullBoxPrivate* d; + }; + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4ISOFULLBOX_H + diff --git a/src/metadata/m4a/mp4itunestag.cpp b/src/metadata/m4a/mp4itunestag.cpp new file mode 100644 index 0000000..aabd644 --- /dev/null +++ b/src/metadata/m4a/mp4itunestag.cpp @@ -0,0 +1,197 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "mp4itunestag.h" + +using namespace TagLib; + +class MP4::Tag::TagPrivate +{ +public: + MP4::File* mp4file; + TagLib::String title; + TagLib::String artist; + TagLib::String album; + TagLib::String genre; + TagLib::uint year; + TagLib::uint track; + TagLib::String comment; + TagLib::String grouping; + TagLib::String composer; + TagLib::uint disk; + TagLib::uint bpm; + bool isEmpty; + TagLib::ByteVector cover; +}; + + +MP4::Tag::Tag( ) +{ + d = new TagPrivate(); + d->year = 0; + d->track = 0; + d->disk = 0; + d->bpm = 0; + d->isEmpty = true; +} + +MP4::Tag::~Tag() +{ + delete d; +} + +String MP4::Tag::title() const +{ + return d->title; +} + +String MP4::Tag::artist() const +{ + return d->artist; +} + +String MP4::Tag::album() const +{ + return d->album; +} + +String MP4::Tag::comment() const +{ + return d->comment; +} + +String MP4::Tag::genre() const +{ + return d->genre; +} + +TagLib::uint MP4::Tag::year() const +{ + return d->year; +} + +TagLib::uint MP4::Tag::track() const +{ + return d->track; +} + +String MP4::Tag::grouping() const +{ + return d->grouping; +} + +String MP4::Tag::composer() const +{ + return d->composer; +} + +TagLib::uint MP4::Tag::disk() const +{ + return d->disk; +} + +TagLib::uint MP4::Tag::bpm() const +{ + return d->bpm; +} + +TagLib::ByteVector MP4::Tag::cover() const +{ + return d->cover; +} + +void MP4::Tag::setTitle(const String &s) +{ + d->title = s; + d->isEmpty = false; +} + +void MP4::Tag::setArtist(const String &s) +{ + d->artist = s; + d->isEmpty = false; +} + +void MP4::Tag::setAlbum(const String &s) +{ + d->album = s; + d->isEmpty = false; +} + +void MP4::Tag::setComment(const String &s) +{ + d->comment = s; + d->isEmpty = false; +} + +void MP4::Tag::setGenre(const String &s) +{ + d->genre = s; + d->isEmpty = false; +} + +void MP4::Tag::setYear(const TagLib::uint i) +{ + d->year = i; + d->isEmpty = false; +} + +void MP4::Tag::setTrack(const TagLib::uint i) +{ + d->track = i; + d->isEmpty = false; +} + +void MP4::Tag::setGrouping(const String &s) +{ + d->grouping = s; + d->isEmpty = false; +} + +void MP4::Tag::setComposer(const String &s) +{ + d->composer = s; + d->isEmpty = false; +} + +void MP4::Tag::setDisk(const TagLib::uint i) +{ + d->disk = i; + d->isEmpty = false; +} + +void MP4::Tag::setBpm(const TagLib::uint i) +{ + d->bpm = i; + d->isEmpty = false; +} + +void MP4::Tag::setCover(const TagLib::ByteVector& c) +{ + d->cover = c; + d->isEmpty = false; +} + +bool MP4::Tag::isEmpty() const +{ + return d->isEmpty; +} + diff --git a/src/metadata/m4a/mp4itunestag.h b/src/metadata/m4a/mp4itunestag.h new file mode 100644 index 0000000..9e572a7 --- /dev/null +++ b/src/metadata/m4a/mp4itunestag.h @@ -0,0 +1,95 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4ITUNESTAG_H +#define MP4ITUNESTAG_H + +#include "taglib.h" +#include "tstring.h" +#include "tag.h" + +namespace TagLib +{ + namespace MP4 + { + class File; + + class Tag : public TagLib::Tag + { + public: + /*! + * Constructs an empty MP4 iTunes tag. + */ + Tag( ); + + /*! + * Destroys this Tag instance. + */ + virtual ~Tag(); + + // Reimplementations. + + virtual String title() const; + virtual String artist() const; + virtual String album() const; + virtual String comment() const; + virtual String genre() const; + virtual uint year() const; + virtual uint track() const; + + virtual void setTitle(const String &s); + virtual void setArtist(const String &s); + virtual void setAlbum(const String &s); + virtual void setComment(const String &s); + virtual void setGenre(const String &s); + virtual void setYear(const uint i); + virtual void setTrack(const uint i); + + // MP4 specific fields + + String grouping() const; + String composer() const; + uint disk() const; + uint bpm() const; + ByteVector cover() const; + int compilation() const { return -1; } + + void setGrouping(const String &s); + void setComposer(const String &s); + void setDisk(const uint i); + void setBpm(const uint i); + void setCover( const ByteVector& cover ); + void setCompilation( bool /*isCompilation*/ ) {} + + virtual bool isEmpty() const; + + private: + Tag(const Tag &); + Tag &operator=(const Tag &); + + class TagPrivate; + TagPrivate *d; + }; + } // namespace MP4 + +} // namespace TagLib + +#endif // MP4ITUNESTAG_H diff --git a/src/metadata/m4a/mp4mdiabox.cpp b/src/metadata/m4a/mp4mdiabox.cpp new file mode 100644 index 0000000..c3b30ad --- /dev/null +++ b/src/metadata/m4a/mp4mdiabox.cpp @@ -0,0 +1,111 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "tlist.h" +#include +#include "mp4mdiabox.h" +#include "mp4hdlrbox.h" +#include "mp4minfbox.h" +#include "boxfactory.h" +#include "mp4file.h" + +using namespace TagLib; + +class MP4::Mp4MdiaBox::Mp4MdiaBoxPrivate +{ +public: + //! container for all boxes in mdia box + TagLib::List mdiaBoxes; + //! a box factory for creating the appropriate boxes + MP4::BoxFactory boxfactory; +}; // class Mp4MdiaBoxPrivate + +MP4::Mp4MdiaBox::Mp4MdiaBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ) + : Mp4IsoBox( file, fourcc, size, offset ) +{ + d = new MP4::Mp4MdiaBox::Mp4MdiaBoxPrivate(); +} + +MP4::Mp4MdiaBox::~Mp4MdiaBox() +{ + TagLib::List::Iterator delIter; + for( delIter = d->mdiaBoxes.begin(); + delIter != d->mdiaBoxes.end(); + delIter++ ) + { + delete *delIter; + } + delete d; +} + +void MP4::Mp4MdiaBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast( file() ); + + TagLib::uint totalsize = 8; + // parse all contained boxes + TagLib::uint size; + MP4::Fourcc fourcc; + + // stores the current handler type + TagLib::MP4::Fourcc hdlrtype; + + while( (mp4file->readSizeAndType( size, fourcc ) == true) ) + { + totalsize += size; + + // check for errors + if( totalsize > MP4::Mp4IsoBox::size() ) + { + std::cerr << "Error in mp4 file " << mp4file->name() << " mdia box contains bad box with name: " << fourcc.toString() << std::endl; + return; + } + + // create the appropriate subclass and parse it + MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( mp4file, fourcc, size, mp4file->tell() ); + if( static_cast( fourcc ) == 0x6d696e66 /*"minf"*/ ) + { + // cast to minf + Mp4MinfBox* minfbox = dynamic_cast( curbox ); + if(!minfbox) + return; + // set handler type + minfbox->setHandlerType( hdlrtype ); + } + + curbox->parsebox(); + d->mdiaBoxes.append( curbox ); + + if(static_cast( fourcc ) == 0x68646c72 /*"hdlr"*/ ) + { + // cast to hdlr box + Mp4HdlrBox* hdlrbox = dynamic_cast( curbox ); + if(!hdlrbox) + return; + // get handler type + hdlrtype = hdlrbox->hdlr_type(); + } + // check for end of mdia box + if( totalsize == MP4::Mp4IsoBox::size() ) + break; + + } +} diff --git a/src/metadata/m4a/mp4mdiabox.h b/src/metadata/m4a/mp4mdiabox.h new file mode 100644 index 0000000..16503bd --- /dev/null +++ b/src/metadata/m4a/mp4mdiabox.h @@ -0,0 +1,49 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4MDIABOX_H +#define MP4MDIABOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4MdiaBox: public Mp4IsoBox + { + public: + Mp4MdiaBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ); + ~Mp4MdiaBox(); + + //! parse mdia contents + void parse(); + + private: + class Mp4MdiaBoxPrivate; + Mp4MdiaBoxPrivate* d; + }; // Mp4MdiaBox + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4MDIABOX_H diff --git a/src/metadata/m4a/mp4metabox.cpp b/src/metadata/m4a/mp4metabox.cpp new file mode 100644 index 0000000..30eebf2 --- /dev/null +++ b/src/metadata/m4a/mp4metabox.cpp @@ -0,0 +1,86 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +#include +#include "mp4metabox.h" +#include "boxfactory.h" +#include "mp4file.h" + +using namespace TagLib; + +class MP4::Mp4MetaBox::Mp4MetaBoxPrivate +{ +public: + //! container for all boxes in meta box + TagLib::List metaBoxes; + //! a box factory for creating the appropriate boxes + MP4::BoxFactory boxfactory; +}; // class Mp4MetaBoxPrivate + +MP4::Mp4MetaBox::Mp4MetaBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ) + : Mp4IsoFullBox( file, fourcc, size, offset ) +{ + d = new MP4::Mp4MetaBox::Mp4MetaBoxPrivate(); +} + +MP4::Mp4MetaBox::~Mp4MetaBox() +{ + TagLib::List::Iterator delIter; + for( delIter = d->metaBoxes.begin(); + delIter != d->metaBoxes.end(); + delIter++ ) + { + delete *delIter; + } + delete d; +} + +void MP4::Mp4MetaBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast( file() ); + + TagLib::uint totalsize = 12; // initial size of box + // parse all contained boxes + TagLib::uint size; + MP4::Fourcc fourcc; + + while( (mp4file->readSizeAndType( size, fourcc ) == true) ) + { + totalsize += size; + + // check for errors + if( totalsize > MP4::Mp4IsoBox::size() ) + { + std::cerr << "Error in mp4 file " << mp4file->name() << " meta box contains bad box with name: " << fourcc.toString() << std::endl; + return; + } + + // create the appropriate subclass and parse it + MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( mp4file, fourcc, size, mp4file->tell() ); + curbox->parsebox(); + d->metaBoxes.append( curbox ); + + // check for end of meta box + if( totalsize == MP4::Mp4IsoBox::size() ) + break; + } +} diff --git a/src/metadata/m4a/mp4metabox.h b/src/metadata/m4a/mp4metabox.h new file mode 100644 index 0000000..58d9667 --- /dev/null +++ b/src/metadata/m4a/mp4metabox.h @@ -0,0 +1,49 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4METABOX_H +#define MP4METABOX_H + +#include "mp4isofullbox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4MetaBox: public Mp4IsoFullBox + { + public: + Mp4MetaBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ); + ~Mp4MetaBox(); + + //! parse meta contents + void parse(); + + private: + class Mp4MetaBoxPrivate; + Mp4MetaBoxPrivate* d; + }; // Mp4MetaBox + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4METABOX_H diff --git a/src/metadata/m4a/mp4minfbox.cpp b/src/metadata/m4a/mp4minfbox.cpp new file mode 100644 index 0000000..0081dda --- /dev/null +++ b/src/metadata/m4a/mp4minfbox.cpp @@ -0,0 +1,104 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "tlist.h" +#include +#include "mp4minfbox.h" +#include "mp4stblbox.h" +#include "boxfactory.h" +#include "mp4file.h" + +using namespace TagLib; + +class MP4::Mp4MinfBox::Mp4MinfBoxPrivate +{ +public: + //! container for all boxes in minf box + TagLib::List minfBoxes; + //! a box factory for creating the appropriate boxes + MP4::BoxFactory boxfactory; + //! stores the handler type of the current trak + MP4::Fourcc handler_type; +}; // class Mp4MinfBoxPrivate + +MP4::Mp4MinfBox::Mp4MinfBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ) + : Mp4IsoBox( file, fourcc, size, offset ) +{ + d = new MP4::Mp4MinfBox::Mp4MinfBoxPrivate(); +} + +MP4::Mp4MinfBox::~Mp4MinfBox() +{ + TagLib::List::Iterator delIter; + for( delIter = d->minfBoxes.begin(); + delIter != d->minfBoxes.end(); + delIter++ ) + { + delete *delIter; + } + delete d; +} + +void MP4::Mp4MinfBox::setHandlerType( MP4::Fourcc fourcc ) +{ + d->handler_type = fourcc; +} + +void MP4::Mp4MinfBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast( file() ); + + TagLib::uint totalsize = 8; + // parse all contained boxes + TagLib::uint size; + MP4::Fourcc fourcc; + + while( (mp4file->readSizeAndType( size, fourcc ) == true) ) + { + totalsize += size; + + // check for errors + if( totalsize > MP4::Mp4IsoBox::size() ) + { + std::cerr << "Error in mp4 file " << mp4file->name() << " minf box contains bad box with name: " << fourcc.toString() << std::endl; + return; + } + + // create the appropriate subclass and parse it + MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( mp4file, fourcc, size, mp4file->tell() ); + if(static_cast( fourcc ) == 0x7374626c /*stbl*/ ) + { + // cast to hdlr box + Mp4StblBox* stblbox = dynamic_cast( curbox ); + if(!stblbox) + return; + // set handler type + stblbox->setHandlerType( d->handler_type ); + } + + curbox->parsebox(); + d->minfBoxes.append( curbox ); + + // check for end of minf box + if( totalsize == MP4::Mp4IsoBox::size() ) + break; + } +} diff --git a/src/metadata/m4a/mp4minfbox.h b/src/metadata/m4a/mp4minfbox.h new file mode 100644 index 0000000..9195d30 --- /dev/null +++ b/src/metadata/m4a/mp4minfbox.h @@ -0,0 +1,51 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4MINFBOX_H +#define MP4MINFBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4MinfBox: public Mp4IsoBox + { + public: + Mp4MinfBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ); + ~Mp4MinfBox(); + + //! parse minf contents + void parse(); + //! set the handler type - needed for stsd + void setHandlerType( MP4::Fourcc fourcc ); + + private: + class Mp4MinfBoxPrivate; + Mp4MinfBoxPrivate* d; + }; // Mp4MinfBox + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4MINFBOX_H diff --git a/src/metadata/m4a/mp4moovbox.cpp b/src/metadata/m4a/mp4moovbox.cpp new file mode 100644 index 0000000..24826ec --- /dev/null +++ b/src/metadata/m4a/mp4moovbox.cpp @@ -0,0 +1,86 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "tlist.h" +#include +#include "mp4moovbox.h" +#include "boxfactory.h" +#include "mp4file.h" + +using namespace TagLib; + +class MP4::Mp4MoovBox::Mp4MoovBoxPrivate +{ +public: + //! container for all boxes in moov box + TagLib::List moovBoxes; + //! a box factory for creating the appropriate boxes + MP4::BoxFactory boxfactory; +}; // class Mp4MoovBoxPrivate + +MP4::Mp4MoovBox::Mp4MoovBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ) + : Mp4IsoBox( file, fourcc, size, offset ) +{ + d = new MP4::Mp4MoovBox::Mp4MoovBoxPrivate(); +} + +MP4::Mp4MoovBox::~Mp4MoovBox() +{ + TagLib::List::Iterator delIter; + for( delIter = d->moovBoxes.begin(); + delIter != d->moovBoxes.end(); + delIter++ ) + { + delete *delIter; + } + delete d; +} + +void MP4::Mp4MoovBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast( file() ); + + TagLib::uint totalsize = 8; + // parse all contained boxes + TagLib::uint size; + MP4::Fourcc fourcc; + + while( (mp4file->readSizeAndType( size, fourcc ) == true) ) + { + totalsize += size; + + // check for errors + if( totalsize > MP4::Mp4IsoBox::size() ) + { + std::cerr << "Error in mp4 file " << mp4file->name() << " moov box contains bad box with name: " << fourcc.toString() << std::endl; + return; + } + + // create the appropriate subclass and parse it + MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( mp4file, fourcc, size, mp4file->tell() ); + curbox->parsebox(); + d->moovBoxes.append( curbox ); + + // check for end of moov box + if( totalsize == MP4::Mp4IsoBox::size() ) + break; + } +} diff --git a/src/metadata/m4a/mp4moovbox.h b/src/metadata/m4a/mp4moovbox.h new file mode 100644 index 0000000..390953f --- /dev/null +++ b/src/metadata/m4a/mp4moovbox.h @@ -0,0 +1,49 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4MOOVBOX_H +#define MP4MOOVBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4MoovBox: public Mp4IsoBox + { + public: + Mp4MoovBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ); + ~Mp4MoovBox(); + + //! parse moov contents + void parse(); + + private: + class Mp4MoovBoxPrivate; + Mp4MoovBoxPrivate* d; + }; // Mp4MoovBox + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4MOOVBOX_H diff --git a/src/metadata/m4a/mp4mvhdbox.cpp b/src/metadata/m4a/mp4mvhdbox.cpp new file mode 100644 index 0000000..36053e4 --- /dev/null +++ b/src/metadata/m4a/mp4mvhdbox.cpp @@ -0,0 +1,140 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +#include +#include "mp4mvhdbox.h" +#include "boxfactory.h" +#include "mp4file.h" +#include "mp4propsproxy.h" + +using namespace TagLib; + +class MP4::Mp4MvhdBox::Mp4MvhdBoxPrivate +{ +public: + //! creation time of the file + TagLib::ulonglong creationTime; + //! modification time of the file - since midnight, Jan. 1, 1904, UTC-time + TagLib::ulonglong modificationTime; + //! timescale for the file - referred by all time specifications in this box + TagLib::uint timescale; + //! duration of presentation + TagLib::ulonglong duration; + //! playout speed + TagLib::uint rate; + //! volume for entire presentation + TagLib::uint volume; + //! track ID for an additional track (next new track) + TagLib::uint nextTrackID; +}; // class Mp4MvhdBoxPrivate + +MP4::Mp4MvhdBox::Mp4MvhdBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ) + : Mp4IsoFullBox( file, fourcc, size, offset ) +{ + d = new MP4::Mp4MvhdBox::Mp4MvhdBoxPrivate(); +} + +MP4::Mp4MvhdBox::~Mp4MvhdBox() +{ + delete d; +} + +TagLib::ulonglong MP4::Mp4MvhdBox::creationTime() const +{ + return d->creationTime; +} + +TagLib::ulonglong MP4::Mp4MvhdBox::modificationTime() const +{ + return d->modificationTime; +} + +TagLib::uint MP4::Mp4MvhdBox::timescale() const +{ + return d->timescale; +} + +TagLib::ulonglong MP4::Mp4MvhdBox::duration() const +{ + return d->duration; +} + +TagLib::uint MP4::Mp4MvhdBox::rate() const +{ + return d->rate; +} + +TagLib::uint MP4::Mp4MvhdBox::volume() const +{ + return d->volume; +} + +TagLib::uint MP4::Mp4MvhdBox::nextTrackID() const +{ + return d->nextTrackID; +} + + +void MP4::Mp4MvhdBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast( file() ); + + if( version() == 1 ) + { + if( !mp4file->readLongLong( d->creationTime ) ) + return; + if( !mp4file->readLongLong( d->modificationTime ) ) + return; + if( !mp4file->readInt( d->timescale ) ) + return; + if( !mp4file->readLongLong( d->duration ) ) + return; + } + else + { + TagLib::uint creationTime_tmp, modificationTime_tmp, duration_tmp; + + if( !mp4file->readInt( creationTime_tmp ) ) + return; + if( !mp4file->readInt( modificationTime_tmp ) ) + return; + if( !mp4file->readInt( d->timescale ) ) + return; + if( !mp4file->readInt( duration_tmp ) ) + return; + + d->creationTime = creationTime_tmp; + d->modificationTime = modificationTime_tmp; + d->duration = duration_tmp; + } + if( !mp4file->readInt( d->rate ) ) + return; + if( !mp4file->readInt( d->volume ) ) + return; + // jump over unused fields + mp4file->seek( 68, File::Current ); + + if( !mp4file->readInt( d->nextTrackID ) ) + return; + // register at proxy + mp4file->propProxy()->registerMvhd( this ); +} diff --git a/src/metadata/m4a/mp4mvhdbox.h b/src/metadata/m4a/mp4mvhdbox.h new file mode 100644 index 0000000..b133485 --- /dev/null +++ b/src/metadata/m4a/mp4mvhdbox.h @@ -0,0 +1,65 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4MVHDBOX_H +#define MP4MVHDBOX_H + +#include "mp4isofullbox.h" +#include "mp4fourcc.h" +#include "mp4file.h" // ulonglong + +namespace TagLib +{ + namespace MP4 + { + class Mp4MvhdBox: public Mp4IsoFullBox + { + public: + Mp4MvhdBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ); + ~Mp4MvhdBox(); + + //! function to get the creation time of the mp4 file + ulonglong creationTime() const; + //! function to get the modification time of the mp4 file + ulonglong modificationTime() const; + //! function to get the timescale referenced by the above timestamps + uint timescale() const; + //! function to get the presentation duration in the mp4 file + ulonglong duration() const; + //! function to get the rate (playout speed) - typically 1.0; + uint rate() const; + //! function to get volume level for presentation - typically 1.0; + uint volume() const; + //! function to get the track ID for adding new tracks - useless for this lib + uint nextTrackID() const; + + //! parse mvhd contents + void parse(); + + private: + class Mp4MvhdBoxPrivate; + Mp4MvhdBoxPrivate* d; + }; // Mp4MvhdBox + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4MVHDBOX_H diff --git a/src/metadata/m4a/mp4propsproxy.cpp b/src/metadata/m4a/mp4propsproxy.cpp new file mode 100644 index 0000000..ebee9c2 --- /dev/null +++ b/src/metadata/m4a/mp4propsproxy.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "mp4propsproxy.h" + +using namespace TagLib; + +class MP4::Mp4PropsProxy::Mp4PropsProxyPrivate +{ +public: + //! the movie header box + MP4::Mp4MvhdBox* mvhdbox; + //! the sample table box + MP4::Mp4AudioSampleEntry* audiosampleentry; +}; + + +MP4::Mp4PropsProxy::Mp4PropsProxy() +{ + d = new MP4::Mp4PropsProxy::Mp4PropsProxyPrivate(); + d->mvhdbox = 0; + d->audiosampleentry = 0; +} + +MP4::Mp4PropsProxy::~Mp4PropsProxy() +{ + delete d; +} + +TagLib::uint MP4::Mp4PropsProxy::seconds() const +{ + if( d->mvhdbox ) + return static_cast( d->mvhdbox->duration() / d->mvhdbox->timescale() ); + else + return 0; +} + +TagLib::uint MP4::Mp4PropsProxy::channels() const +{ + if( d->audiosampleentry ) + return d->audiosampleentry->channels(); + else + return 0; +} + +TagLib::uint MP4::Mp4PropsProxy::sampleRate() const +{ + if( d->audiosampleentry ) + return (d->audiosampleentry->samplerate()>>16); + else + return 0; +} + +TagLib::uint MP4::Mp4PropsProxy::bitRate() const +{ + if( d->audiosampleentry ) + return (d->audiosampleentry->bitrate()); + else + return 0; +} + +void MP4::Mp4PropsProxy::registerMvhd( MP4::Mp4MvhdBox* mvhdbox ) +{ + d->mvhdbox = mvhdbox; +} + +void MP4::Mp4PropsProxy::registerAudioSampleEntry( MP4::Mp4AudioSampleEntry* audioSampleEntry ) +{ + d->audiosampleentry = audioSampleEntry; +} + diff --git a/src/metadata/m4a/mp4propsproxy.h b/src/metadata/m4a/mp4propsproxy.h new file mode 100644 index 0000000..0ea29e2 --- /dev/null +++ b/src/metadata/m4a/mp4propsproxy.h @@ -0,0 +1,65 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4PROPSPROXY_H +#define MP4PROPSPROXY_H MP4PROPSPROXY_H +#include "mp4mvhdbox.h" +#include "mp4audiosampleentry.h" + +namespace TagLib +{ + namespace MP4 + { + //! Mp4PropsProxy is used to access the stsd box and mvhd box directly + /*! this class works as a shortcut to avoid stepping through all parent boxes + * to access the boxes in question + */ + class Mp4PropsProxy + { + public: + //! constructor for properties proxy + Mp4PropsProxy(); + //! destructor + ~Mp4PropsProxy(); + + //! function to get length of media in seconds + TagLib::uint seconds() const; + //! function to get the nunmber of channels + TagLib::uint channels() const; + //! function to get the sample rate + TagLib::uint sampleRate() const; + //! function to get the bitrate rate + TagLib::uint bitRate() const; + + //! function to register the movie header box - mvhd + void registerMvhd( MP4::Mp4MvhdBox* mvhdbox ); + //! function to register the sample description box + void registerAudioSampleEntry( MP4::Mp4AudioSampleEntry* audiosampleentry ); + + private: + class Mp4PropsProxyPrivate; + Mp4PropsProxyPrivate* d; + + }; // Mp4PropsProxy + } // MP4 +} // TagLib + +#endif // MP4PROPSPROXY_H diff --git a/src/metadata/m4a/mp4sampleentry.cpp b/src/metadata/m4a/mp4sampleentry.cpp new file mode 100644 index 0000000..e5619ea --- /dev/null +++ b/src/metadata/m4a/mp4sampleentry.cpp @@ -0,0 +1,59 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "mp4sampleentry.h" +#include "mp4isobox.h" +#include "mp4file.h" + +using namespace TagLib; + +class MP4::Mp4SampleEntry::Mp4SampleEntryPrivate +{ +public: + TagLib::uint data_reference_index; +}; + +MP4::Mp4SampleEntry::Mp4SampleEntry( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::Mp4SampleEntry::Mp4SampleEntryPrivate(); +} + +MP4::Mp4SampleEntry::~Mp4SampleEntry() +{ + delete d; +} + +//! parse the content of the box +void MP4::Mp4SampleEntry::parse() +{ + TagLib::MP4::File* mp4file = dynamic_cast(file()); + if(!mp4file) + return; + + // skip the first 6 bytes + mp4file->seek( 6, TagLib::File::Current ); + // read data reference index + if(!mp4file->readShort( d->data_reference_index)) + return; + parseEntry(); +} + diff --git a/src/metadata/m4a/mp4sampleentry.h b/src/metadata/m4a/mp4sampleentry.h new file mode 100644 index 0000000..39475f7 --- /dev/null +++ b/src/metadata/m4a/mp4sampleentry.h @@ -0,0 +1,54 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4SAMPLEENTRY_H +#define MP4SAMPLEENTRY_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4SampleEntry: public Mp4IsoBox + { + public: + Mp4SampleEntry( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~Mp4SampleEntry(); + + public: + //! parse the content of the box + virtual void parse(); + + private: + //! function to be implemented in subclass + virtual void parseEntry() = 0; + + protected: + class Mp4SampleEntryPrivate; + Mp4SampleEntryPrivate* d; + }; // class Mp4SampleEntry + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4SAMPLEENTRY_H diff --git a/src/metadata/m4a/mp4skipbox.cpp b/src/metadata/m4a/mp4skipbox.cpp new file mode 100644 index 0000000..8cb5218 --- /dev/null +++ b/src/metadata/m4a/mp4skipbox.cpp @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "mp4skipbox.h" +#include "mp4isobox.h" +#include "tfile.h" + +using namespace TagLib; + +class MP4::Mp4SkipBox::Mp4SkipBoxPrivate +{ +public: +}; + +MP4::Mp4SkipBox::Mp4SkipBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::Mp4SkipBox::Mp4SkipBoxPrivate(); +} + +MP4::Mp4SkipBox::~Mp4SkipBox() +{ + delete d; +} + +//! parse the content of the box +void MP4::Mp4SkipBox::parse() +{ + // skip contents + file()->seek( size() - 8, TagLib::File::Current ); +} + diff --git a/src/metadata/m4a/mp4skipbox.h b/src/metadata/m4a/mp4skipbox.h new file mode 100644 index 0000000..896fcaa --- /dev/null +++ b/src/metadata/m4a/mp4skipbox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4SKIPBOX_H +#define MP4SKIPBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4SkipBox: public Mp4IsoBox + { + public: + Mp4SkipBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~Mp4SkipBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class Mp4SkipBoxPrivate; + Mp4SkipBoxPrivate* d; + }; // class Mp4SkipBox + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4SKIPBOX_H diff --git a/src/metadata/m4a/mp4stblbox.cpp b/src/metadata/m4a/mp4stblbox.cpp new file mode 100644 index 0000000..f67de59 --- /dev/null +++ b/src/metadata/m4a/mp4stblbox.cpp @@ -0,0 +1,105 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "tlist.h" +#include +#include "mp4stblbox.h" +#include "mp4stsdbox.h" +#include "boxfactory.h" +#include "mp4file.h" + +using namespace TagLib; + +class MP4::Mp4StblBox::Mp4StblBoxPrivate +{ +public: + //! container for all boxes in stbl box + TagLib::List stblBoxes; + //! a box factory for creating the appropriate boxes + MP4::BoxFactory boxfactory; + //! the handler type for the current trak + MP4::Fourcc handler_type; +}; // class Mp4StblBoxPrivate + +MP4::Mp4StblBox::Mp4StblBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ) + : Mp4IsoBox( file, fourcc, size, offset ) +{ + d = new MP4::Mp4StblBox::Mp4StblBoxPrivate(); +} + +MP4::Mp4StblBox::~Mp4StblBox() +{ + TagLib::List::Iterator delIter; + for( delIter = d->stblBoxes.begin(); + delIter != d->stblBoxes.end(); + delIter++ ) + { + delete *delIter; + } + delete d; +} + +void MP4::Mp4StblBox::setHandlerType( MP4::Fourcc fourcc ) +{ + d->handler_type = fourcc; +} + +void MP4::Mp4StblBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast( file() ); + + TagLib::uint totalsize = 8; + // parse all contained boxes + TagLib::uint size; + MP4::Fourcc fourcc; + + while( (mp4file->readSizeAndType( size, fourcc ) == true) ) + { + totalsize += size; + + // check for errors + if( totalsize > MP4::Mp4IsoBox::size() ) + { + std::cerr << "Error in mp4 file " << mp4file->name() << " stbl box contains bad box with name: " << fourcc.toString() << std::endl; + return; + } + + // create the appropriate subclass and parse it + MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( mp4file, fourcc, size, mp4file->tell() ); + + // check for stsd + if( static_cast(fourcc) == 0x73747364 /*'stsd'*/ ) + { + // cast to stsd box + MP4::Mp4StsdBox* stsdbox = dynamic_cast(curbox); + if(!stsdbox) + return; + // set the handler type + stsdbox->setHandlerType( d->handler_type ); + } + curbox->parsebox(); + d->stblBoxes.append( curbox ); + + // check for end of stbl box + if( totalsize == MP4::Mp4IsoBox::size() ) + break; + } +} diff --git a/src/metadata/m4a/mp4stblbox.h b/src/metadata/m4a/mp4stblbox.h new file mode 100644 index 0000000..39619a6 --- /dev/null +++ b/src/metadata/m4a/mp4stblbox.h @@ -0,0 +1,51 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4STBLBOX_H +#define MP4STBLBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4StblBox: public Mp4IsoBox + { + public: + Mp4StblBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ); + ~Mp4StblBox(); + + //! parse stbl contents + void parse(); + //! set the handler type - needed for stsd + void setHandlerType( MP4::Fourcc fourcc ); + + private: + class Mp4StblBoxPrivate; + Mp4StblBoxPrivate* d; + }; // Mp4StblBox + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4STBLBOX_H diff --git a/src/metadata/m4a/mp4stsdbox.cpp b/src/metadata/m4a/mp4stsdbox.cpp new file mode 100644 index 0000000..6bb8cbe --- /dev/null +++ b/src/metadata/m4a/mp4stsdbox.cpp @@ -0,0 +1,91 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "tlist.h" +#include +#include "mp4stsdbox.h" +#include "mp4audiosampleentry.h" +#include "mp4file.h" + +using namespace TagLib; + +class MP4::Mp4StsdBox::Mp4StsdBoxPrivate +{ +public: + //! the handler type for the current trak + MP4::Fourcc handler_type; + //! the audio sample entry + MP4::Mp4AudioSampleEntry* audioSampleEntry; +}; // class Mp4StsdBoxPrivate + +MP4::Mp4StsdBox::Mp4StsdBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ) + : Mp4IsoFullBox( file, fourcc, size, offset ) +{ + d = new MP4::Mp4StsdBox::Mp4StsdBoxPrivate(); +} + +MP4::Mp4StsdBox::~Mp4StsdBox() +{ + delete d; +} + +void MP4::Mp4StsdBox::setHandlerType( MP4::Fourcc fourcc ) +{ + d->handler_type = fourcc; +} + +void MP4::Mp4StsdBox::parse() +{ + MP4::File* mp4file = dynamic_cast( file() ); + if(!mp4file) + return; + + TagLib::uint totalsize = 12; // initial size of box + + // check for handler type - only parse if 'soun': + if( static_cast(d->handler_type) == 0x736f756e ) + { + // read entry count + TagLib::uint entry_count; + if(!mp4file->readInt( entry_count )) + return; + + // simply read first entry and skip all following + // read size and type + TagLib::uint cursize; + MP4::Fourcc fourcc; + if( !mp4file->readSizeAndType( cursize, fourcc )) + return; + + totalsize += 12; + // alocate an AudioSampleEntry + d->audioSampleEntry = new MP4::Mp4AudioSampleEntry( mp4file, fourcc, cursize, mp4file->tell() ); + // parse the AudioSampleEntry + d->audioSampleEntry->parse(); + totalsize += cursize-8; + // skip the remaining box contents + mp4file->seek( size()-totalsize, TagLib::File::Current ); + } + else + { + mp4file->seek( size()-totalsize, TagLib::File::Current ); + } +} diff --git a/src/metadata/m4a/mp4stsdbox.h b/src/metadata/m4a/mp4stsdbox.h new file mode 100644 index 0000000..90bc014 --- /dev/null +++ b/src/metadata/m4a/mp4stsdbox.h @@ -0,0 +1,51 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4STSDBOX_H +#define MP4STSDBOX_H + +#include "mp4isofullbox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4StsdBox: public Mp4IsoFullBox + { + public: + Mp4StsdBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ); + ~Mp4StsdBox(); + + //! parse stsd contents + void parse(); + //! set the handler type - needed for stsd + void setHandlerType( MP4::Fourcc fourcc ); + + private: + class Mp4StsdBoxPrivate; + Mp4StsdBoxPrivate* d; + }; // Mp4StsdBox + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4STSDBOX_H diff --git a/src/metadata/m4a/mp4tagsproxy.cpp b/src/metadata/m4a/mp4tagsproxy.cpp new file mode 100644 index 0000000..0a77427 --- /dev/null +++ b/src/metadata/m4a/mp4tagsproxy.cpp @@ -0,0 +1,168 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "mp4tagsproxy.h" +#include "itunesdatabox.h" + +using namespace TagLib; + +class MP4::Mp4TagsProxy::Mp4TagsProxyPrivate +{ +public: + ITunesDataBox* titleData; + ITunesDataBox* artistData; + ITunesDataBox* albumData; + ITunesDataBox* coverData; + ITunesDataBox* genreData; + ITunesDataBox* yearData; + ITunesDataBox* trknData; + ITunesDataBox* commentData; + ITunesDataBox* groupingData; + ITunesDataBox* composerData; + ITunesDataBox* diskData; + ITunesDataBox* bpmData; +}; + +MP4::Mp4TagsProxy::Mp4TagsProxy() +{ + d = new MP4::Mp4TagsProxy::Mp4TagsProxyPrivate(); + d->titleData = 0; + d->artistData = 0; + d->albumData = 0; + d->coverData = 0; + d->genreData = 0; + d->yearData = 0; + d->trknData = 0; + d->commentData = 0; + d->groupingData = 0; + d->composerData = 0; + d->diskData = 0; + d->bpmData = 0; +} + +MP4::Mp4TagsProxy::~Mp4TagsProxy() +{ + delete d; +} + +MP4::ITunesDataBox* MP4::Mp4TagsProxy::titleData() const +{ + return d->titleData; +} + +MP4::ITunesDataBox* MP4::Mp4TagsProxy::artistData() const +{ + return d->artistData; +} + +MP4::ITunesDataBox* MP4::Mp4TagsProxy::albumData() const +{ + return d->albumData; +} + +MP4::ITunesDataBox* MP4::Mp4TagsProxy::genreData() const +{ + return d->genreData; +} + +MP4::ITunesDataBox* MP4::Mp4TagsProxy::yearData() const +{ + return d->yearData; +} + +MP4::ITunesDataBox* MP4::Mp4TagsProxy::trknData() const +{ + return d->trknData; +} + +MP4::ITunesDataBox* MP4::Mp4TagsProxy::commentData() const +{ + return d->commentData; +} + +MP4::ITunesDataBox* MP4::Mp4TagsProxy::groupingData() const +{ + return d->groupingData; +} + +MP4::ITunesDataBox* MP4::Mp4TagsProxy::composerData() const +{ + return d->composerData; +} + +MP4::ITunesDataBox* MP4::Mp4TagsProxy::diskData() const +{ + return d->diskData; +} + +MP4::ITunesDataBox* MP4::Mp4TagsProxy::bpmData() const +{ + return d->bpmData; +} + +MP4::ITunesDataBox* MP4::Mp4TagsProxy::coverData() const +{ + return d->coverData; +} + +void MP4::Mp4TagsProxy::registerBox( EBoxType boxtype, ITunesDataBox* databox ) +{ + switch( boxtype ) + { + case title: + d->titleData = databox; + break; + case artist: + d->artistData = databox; + break; + case album: + d->albumData = databox; + break; + case cover: + d->coverData = databox; + break; + case genre: + d->genreData = databox; + break; + case year: + d->yearData = databox; + break; + case trackno: + d->trknData = databox; + break; + case comment: + d->commentData = databox; + break; + case grouping: + d->groupingData = databox; + break; + case composer: + d->composerData = databox; + break; + case disk: + d->diskData = databox; + break; + case bpm: + d->bpmData = databox; + break; + } +} + diff --git a/src/metadata/m4a/mp4tagsproxy.h b/src/metadata/m4a/mp4tagsproxy.h new file mode 100644 index 0000000..c8bcbf0 --- /dev/null +++ b/src/metadata/m4a/mp4tagsproxy.h @@ -0,0 +1,99 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4TAGSPROXY_H +#define MP4TAGSPROXY_H + +namespace TagLib +{ + namespace MP4 + { + // forward declaration(s) + class ITunesDataBox; + /*! proxy for mp4 itunes tag relevant boxes + * + * this class works as a proxy for the specific tag boxes + * in an mp4 itunes file. the boxes are mired in + * the mp4 file structure and stepping through all box layers + * is avoided by registration at the proxy object. + */ + class Mp4TagsProxy + { + public: + /*! enum for all supported box types */ + typedef enum + { + title = 0, + artist, + album, + cover, + genre, + year, + trackno, + comment, + grouping, + composer, + disk, + bpm + } EBoxType; + + //! constructor + Mp4TagsProxy(); + //! destructor + ~Mp4TagsProxy(); + + //! function to get the data box for the title + ITunesDataBox* titleData() const; + //! function to get the data box for the artist + ITunesDataBox* artistData() const; + //! function to get the data box for the album + ITunesDataBox* albumData() const; + //! function to get the data box for the genre + ITunesDataBox* genreData() const; + //! function to get the data box for the year + ITunesDataBox* yearData() const; + //! function to get the data box for the track number + ITunesDataBox* trknData() const; + //! function to get the data box for the comment + ITunesDataBox* commentData() const; + //! function to get the data box for the grouping + ITunesDataBox* groupingData() const; + //! function to get the data box for the composer + ITunesDataBox* composerData() const; + //! function to get the data box for the disk number + ITunesDataBox* diskData() const; + //! function to get the data box for the bpm + ITunesDataBox* bpmData() const; + //! function to get the data box for the cover + ITunesDataBox* coverData() const; + + //! function to register a data box for a certain box type + void registerBox( EBoxType boxtype, ITunesDataBox* databox ); + + private: + class Mp4TagsProxyPrivate; + //! private data of tags proxy + Mp4TagsProxyPrivate* d; + }; // class Mp4TagsProxy + } // namespace MP4 +} // namespace TagLib + +#endif // MP4TAGSPROXY_H diff --git a/src/metadata/m4a/mp4trakbox.cpp b/src/metadata/m4a/mp4trakbox.cpp new file mode 100644 index 0000000..c573ec7 --- /dev/null +++ b/src/metadata/m4a/mp4trakbox.cpp @@ -0,0 +1,86 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "tlist.h" +#include +#include "mp4trakbox.h" +#include "boxfactory.h" +#include "mp4file.h" + +using namespace TagLib; + +class MP4::Mp4TrakBox::Mp4TrakBoxPrivate +{ +public: + //! container for all boxes in trak box + TagLib::List trakBoxes; + //! a box factory for creating the appropriate boxes + MP4::BoxFactory boxfactory; +}; // class Mp4TrakBoxPrivate + +MP4::Mp4TrakBox::Mp4TrakBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ) + : Mp4IsoBox( file, fourcc, size, offset ) +{ + d = new MP4::Mp4TrakBox::Mp4TrakBoxPrivate(); +} + +MP4::Mp4TrakBox::~Mp4TrakBox() +{ + TagLib::List::Iterator delIter; + for( delIter = d->trakBoxes.begin(); + delIter != d->trakBoxes.end(); + delIter++ ) + { + delete *delIter; + } + delete d; +} + +void MP4::Mp4TrakBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast( file() ); + + TagLib::uint totalsize = 8; + // parse all contained boxes + TagLib::uint size; + MP4::Fourcc fourcc; + + while( (mp4file->readSizeAndType( size, fourcc ) == true) ) + { + totalsize += size; + + // check for errors + if( totalsize > MP4::Mp4IsoBox::size() ) + { + std::cerr << "Error in mp4 file " << mp4file->name() << " trak box contains bad box with name: " << fourcc.toString() << std::endl; + return; + } + + // create the appropriate subclass and parse it + MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( mp4file, fourcc, size, mp4file->tell() ); + curbox->parsebox(); + d->trakBoxes.append( curbox ); + + // check for end of trak box + if( totalsize == MP4::Mp4IsoBox::size() ) + break; + } +} diff --git a/src/metadata/m4a/mp4trakbox.h b/src/metadata/m4a/mp4trakbox.h new file mode 100644 index 0000000..b362fa3 --- /dev/null +++ b/src/metadata/m4a/mp4trakbox.h @@ -0,0 +1,49 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4TRAKBOX_H +#define MP4TRAKBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4TrakBox: public Mp4IsoBox + { + public: + Mp4TrakBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ); + ~Mp4TrakBox(); + + //! parse trak contents + void parse(); + + private: + class Mp4TrakBoxPrivate; + Mp4TrakBoxPrivate* d; + }; // Mp4TrakBox + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4TRAKBOX_H diff --git a/src/metadata/m4a/mp4udtabox.cpp b/src/metadata/m4a/mp4udtabox.cpp new file mode 100644 index 0000000..268d1c1 --- /dev/null +++ b/src/metadata/m4a/mp4udtabox.cpp @@ -0,0 +1,95 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "tlist.h" +#include +#include "mp4udtabox.h" +#include "boxfactory.h" +#include "mp4file.h" + +using namespace TagLib; + +class MP4::Mp4UdtaBox::Mp4UdtaBoxPrivate +{ +public: + //! container for all boxes in udta box + TagLib::List udtaBoxes; + //! a box factory for creating the appropriate boxes + MP4::BoxFactory boxfactory; +}; // class Mp4UdtaBoxPrivate + +MP4::Mp4UdtaBox::Mp4UdtaBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ) + : Mp4IsoBox( file, fourcc, size, offset ) +{ + d = new MP4::Mp4UdtaBox::Mp4UdtaBoxPrivate(); +} + +MP4::Mp4UdtaBox::~Mp4UdtaBox() +{ + TagLib::List::Iterator delIter; + for( delIter = d->udtaBoxes.begin(); + delIter != d->udtaBoxes.end(); + delIter++ ) + { + delete *delIter; + } + delete d; +} + +void MP4::Mp4UdtaBox::parse() +{ +#if 0 + std::cout << " parsing udta box" << std::endl; +#endif + TagLib::MP4::File* mp4file = static_cast( file() ); + + TagLib::uint totalsize = 8; + // parse all contained boxes + TagLib::uint size; + MP4::Fourcc fourcc; + +#if 0 + std::cout << " "; +#endif + while( (mp4file->readSizeAndType( size, fourcc ) == true) ) + { + totalsize += size; + + // check for errors + if( totalsize > MP4::Mp4IsoBox::size() ) + { + std::cerr << "Error in mp4 file " << mp4file->name() << " udta box contains bad box with name: " << fourcc.toString() << std::endl; + return; + } + + // create the appropriate subclass and parse it + MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( mp4file, fourcc, size, mp4file->tell() ); + curbox->parsebox(); + d->udtaBoxes.append( curbox ); + + // check for end of udta box + if( totalsize == MP4::Mp4IsoBox::size() ) + break; +#if 0 + std::cout << " "; +#endif + } +} diff --git a/src/metadata/m4a/mp4udtabox.h b/src/metadata/m4a/mp4udtabox.h new file mode 100644 index 0000000..4873e32 --- /dev/null +++ b/src/metadata/m4a/mp4udtabox.h @@ -0,0 +1,49 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : jochen.issing@isign-softart.de + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4UDTABOX_H +#define MP4UDTABOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4UdtaBox: public Mp4IsoBox + { + public: + Mp4UdtaBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ); + ~Mp4UdtaBox(); + + //! parse moov contents + void parse(); + + private: + class Mp4UdtaBoxPrivate; + Mp4UdtaBoxPrivate* d; + }; // Mp4UdtaBox + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4UDTABOX_H diff --git a/src/metadata/m4a/taglib_mp4filetyperesolver.cpp b/src/metadata/m4a/taglib_mp4filetyperesolver.cpp new file mode 100644 index 0000000..9566a93 --- /dev/null +++ b/src/metadata/m4a/taglib_mp4filetyperesolver.cpp @@ -0,0 +1,42 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : aumuell@reserv.at + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "taglib_mp4filetyperesolver.h" +#include "mp4file.h" + +#include + +TagLib::File *MP4FileTypeResolver::createFile(const char *fileName, + bool readProperties, + TagLib::AudioProperties::ReadStyle propertiesStyle) const +{ +// fprintf(stderr, "mp4?: %s\n", fileName); + const char *ext = strrchr(fileName, '.'); + if(ext && (!strcasecmp(ext, ".m4a") + || !strcasecmp(ext, ".m4b") || !strcasecmp(ext, ".m4p") + || !strcasecmp(ext, ".mp4") + || !strcasecmp(ext, ".m4v") || !strcasecmp(ext, ".mp4v"))) + { + return new TagLib::MP4::File(fileName, readProperties, propertiesStyle); + } + + return 0; +} diff --git a/src/metadata/m4a/taglib_mp4filetyperesolver.h b/src/metadata/m4a/taglib_mp4filetyperesolver.h new file mode 100644 index 0000000..fbc3dd4 --- /dev/null +++ b/src/metadata/m4a/taglib_mp4filetyperesolver.h @@ -0,0 +1,36 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : aumuell@reserv.at + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_MP4FILETYPERESOLVER_H +#define TAGLIB_MP4FILETYPERESOLVER_H + +#include +#include + + +class MP4FileTypeResolver : public TagLib::FileRef::FileTypeResolver +{ + TagLib::File *createFile(const char *fileName, + bool readAudioProperties, + TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; +}; + +#endif diff --git a/src/metadata/mp4/Makefile.am b/src/metadata/mp4/Makefile.am new file mode 100644 index 0000000..e0779c6 --- /dev/null +++ b/src/metadata/mp4/Makefile.am @@ -0,0 +1,18 @@ +SUBDIRS = + +INCLUDES = $(all_includes) $(MP4V2_INCLUDES) $(taglib_includes) +METASOURCES = AUTO +libtagmp4_la_LDFLAGS = $(all_libraries) $(MP4V2_LIBS) +noinst_LTLIBRARIES = libtagmp4.la + +libtagmp4_la_SOURCES = \ + mp4properties.cpp \ + mp4tag.cpp \ + mp4file.cpp \ + taglib_mp4filetyperesolver.cpp + +noinst_HEADERS = \ + mp4properties.h \ + mp4tag.h \ + mp4file.h \ + taglib_mp4filetyperesolver.h diff --git a/src/metadata/optimfrog/Makefile.am b/src/metadata/optimfrog/Makefile.am new file mode 100755 index 0000000..f2b7e6b --- /dev/null +++ b/src/metadata/optimfrog/Makefile.am @@ -0,0 +1,6 @@ +INCLUDES = $(all_includes) $(taglib_includes) +METASOURCES = AUTO +libtagoptimfrog_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libtagoptimfrog.la +noinst_HEADERS = taglib_optimfrogfiletyperesolver.h +libtagoptimfrog_la_SOURCES = taglib_optimfrogfiletyperesolver.cpp diff --git a/src/metadata/optimfrog/taglib_optimfrogfiletyperesolver.cpp b/src/metadata/optimfrog/taglib_optimfrogfiletyperesolver.cpp new file mode 100755 index 0000000..13cde6a --- /dev/null +++ b/src/metadata/optimfrog/taglib_optimfrogfiletyperesolver.cpp @@ -0,0 +1,21 @@ +// (c) 2006 Martin Aumueller +// modified 2006 Daniel Faust +// See COPYING file for licensing information + +#include "taglib_optimfrogfiletyperesolver.h" +#include + +#include + +TagLib::File *OptimFrogFileTypeResolver::createFile(const char *fileName, + bool readProperties, + TagLib::AudioProperties::ReadStyle propertiesStyle) const +{ + const char *ext = strrchr(fileName, '.'); + if(ext && !strcasecmp(ext, ".ofr")) + { + return new TagLib::MPC::File(fileName, readProperties, propertiesStyle); + } + + return 0; +} diff --git a/src/metadata/optimfrog/taglib_optimfrogfiletyperesolver.h b/src/metadata/optimfrog/taglib_optimfrogfiletyperesolver.h new file mode 100755 index 0000000..b277ed5 --- /dev/null +++ b/src/metadata/optimfrog/taglib_optimfrogfiletyperesolver.h @@ -0,0 +1,19 @@ +// (c) 2006 Martin Aumueller +// modified 2006 Daniel Faust +// See COPYING file for licensing information + +#ifndef TAGLIB_OPTIMFROGFILETYPERESOLVER_H +#define TAGLIB_OPTIMFROGFILETYPERESOLVER_H + +#include +#include + + +class OptimFrogFileTypeResolver : public TagLib::FileRef::FileTypeResolver +{ + TagLib::File *createFile(const char *fileName, + bool readAudioProperties, + TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; +}; + +#endif diff --git a/src/metadata/rmff/Makefile.am b/src/metadata/rmff/Makefile.am new file mode 100644 index 0000000..b493e66 --- /dev/null +++ b/src/metadata/rmff/Makefile.am @@ -0,0 +1,15 @@ +SUBDIRS = + +INCLUDES = $(all_includes) $(taglib_includes) +METASOURCES = AUTO +libtagrealmedia_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libtagrealmedia.la + +libtagrealmedia_la_SOURCES = rmff.cpp \ + taglib_realmediafile.cpp \ + taglib_realmediafiletyperesolver.cpp + +noinst_HEADERS = rmff.h \ + taglib_realmediafile.h \ + taglib_realmediafiletyperesolver.h + diff --git a/src/metadata/rmff/rmff.cpp b/src/metadata/rmff/rmff.cpp new file mode 100644 index 0000000..da0edd5 --- /dev/null +++ b/src/metadata/rmff/rmff.cpp @@ -0,0 +1,998 @@ +/*************************************************************************** + copyright : (C) 2005 by Paul Cifarelli + email : paulc2@optonline.net + ***************************************************************************/ + +/*************************************************************************** + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin St, 5th fl, Boston, MA 02110-1301, * + * USA, or check http://www.fsf.org/about/contact.html * + * * + * Note that no RealNetworks code appears or is duplicated, copied, or * + + used as a template in this code. The code was written from scratch * + * using the reference documentation found at: * + * * + * https://common.helixcommunity.org/nonav/2003/HCS_SDK_r5/helixsdk.htm * + * * + ***************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "rmff.h" + +#define UNPACK4(a, buf, i) memcpy((void *)&a, (void *) &buf[i], 4),i+=4,a=ntohl(a) +#define UNPACK2(a, buf, i) memcpy((void *)&a, (void *) &buf[i], 2),i+=2,a=ntohs(a) + +using namespace TagLib; +using namespace TagLib::RealMedia; + +RMFFile::RMFFile(const char *filename) : File(filename), m_id3tag(0) +{ + if (isOpen()) + m_id3tag = new ID3v1::Tag(this, length() - 128); +} + +RMFFile::~RMFFile() +{ + delete m_id3tag; +} + +bool RMFFile::save() +{ + ByteVector bv = m_id3tag->render(); //TODO finish this + return false; +} + + +String RealMediaFF::title () const +{ + return !m_err && m_id3v1tag ? m_id3v1tag->tag()->title() : ""; +} + +String RealMediaFF::artist () const +{ + return !m_err && m_id3v1tag ? m_id3v1tag->tag()->artist() : ""; +} + +String RealMediaFF::album () const +{ + return !m_err && m_id3v1tag ? m_id3v1tag->tag()->album() : ""; +} + +String RealMediaFF::comment() const +{ + return !m_err && m_id3v1tag ? m_id3v1tag->tag()->comment() : ""; +} + +String RealMediaFF::genre() const +{ + return !m_err && m_id3v1tag ? m_id3v1tag->tag()->genre() : ""; +} + +TagLib::uint RealMediaFF::year() const +{ + return !m_err && m_id3v1tag ? m_id3v1tag->tag()->year() : 0; +} + +TagLib::uint RealMediaFF::track() const +{ + return !m_err && m_id3v1tag ? m_id3v1tag->tag()->track() : 0; +} + +// properties +int RealMediaFF::length () const +{ + return m_readProperties && !m_err && m_props ? m_props->duration : 0; +} + +int RealMediaFF::bitrate () const +{ + return m_readProperties && !m_err && m_props ? m_props->avg_bit_rate : 0; +} + +int RealMediaFF::sampleRate () const +{ + return 0; +} + +int RealMediaFF::channels () const +{ + return 0; +} + + +RealMediaFF::RealMediaFF(const char *file, bool readProperties, AudioProperties::ReadStyle /*propertiesStyle*/) +: m_filename(0) +, m_head(0) +, m_tail(0) +, m_err(0) +, m_hdr(0) +, m_props(0) +, media_hdrs(0) +, m_contenthdr(0) +, m_md(0) +, m_title(0) +, m_author(0) +, m_copyright(0) +, m_comment(0) +, m_id3v1tag(0) +, m_flipYearInMetadataSection(0) +, m_readProperties(readProperties) +{ + m_filename = strdup(file); + + m_fd = open(m_filename, O_RDONLY); + if (m_fd < 0) + { + m_err = -1; + return; + } + + // ok, for RM files, the properties are embedded, so we ignore propertiesStyle + if (m_readProperties) + { + init(); + + // and now for the really complicated stuff... + if (initMetadataSection()) + std::cerr << "ERROR reading Metadata\n"; + } + + // now get the ID3v1 tag at the end of this file + m_id3v1tag = new RMFFile(m_filename); +} + + +RealMediaFF::RealMediaFF(RealMediaFF &src) +: m_filename(0) +, m_head(0) +, m_tail(0) +, m_err(0) +, m_hdr(0) +, m_props(0) +, media_hdrs(0) +, m_contenthdr(0) +, m_md(0) +, m_title(0) +, m_author(0) +, m_copyright(0) +, m_comment(0) +, m_id3v1tag(0) +, m_flipYearInMetadataSection(0) +, m_readProperties(src.m_readProperties) +{ + m_filename=strdup(src.m_filename); + + m_fd = open(m_filename, O_RDONLY); + if (m_fd < 0) + { + m_err = -1; + return; + } + + // ok, for RM files, the properties are embedded, so we ignore propertiesStyle + if (m_readProperties) + { + init(); + + // and now for the really complicated stuff... + if (initMetadataSection()) + std::cerr << "ERROR reading Metadata\n"; + } + + // now get the ID3v1 tag at the end of this file + m_id3v1tag = new RMFFile(m_filename); +} + +RealMediaFF::~RealMediaFF() +{ + ::free(m_filename); + + Collectable *hdr = m_head, *next; + while (hdr) + { + next = hdr->fwd; + delete hdr; + hdr = next; + } + + delete m_id3v1tag; + delete m_md; + + close(m_fd); +} + +bool RealMediaFF::isEmpty() const +{ + return m_id3v1tag->tag()->isEmpty(); +} + + +void RealMediaFF::saveHeader(Collectable *hdr) +{ + hdr->fwd = 0; + if (!m_head) + m_head = m_tail = hdr; + else + { + m_tail->fwd = hdr; + m_tail = hdr; + } +} + + +int RealMediaFF::init() +{ + int nbytes; + unsigned char buf[65536]; + UINT32 object_id; + UINT32 sz; + UINT32 consumed = 0; + + off_t s; + if ( (s = lseek(m_fd, 0, SEEK_SET)) ) + { + m_err = -1; + return m_err; + } + + m_hdr = new File_Header_v0_v1; + nbytes = getChunk(buf, 65536, m_hdr->s.object_id, m_hdr->s.size, consumed); + if (nbytes < 0 || m_hdr->s.size != consumed || memcmp((void *)&m_hdr->s.object_id, ".RMF", 4)) + { + //std::cerr << "SERIOUS ERROR - not likely a RealMedia file\n"; + m_err = -1; + return m_err; + } + if (!getRealFileHeader(m_hdr, buf, m_hdr->s.object_id, m_hdr->s.size)) + { + saveHeader(m_hdr); + consumed = 0; + nbytes = getChunk(buf, 65536, object_id, sz, consumed); + if (nbytes < 0 || sz != consumed) + { + m_err = -1; + return m_err; + } + + while (!m_err && memcmp((void *)&object_id, "DATA", 4)) + { + char oid[5]; + memcpy((void *)oid, (void *)&object_id, 4); + oid[4] = 0; + if (!memcmp((void *)&object_id, "PROP", 4)) + { + m_props = new RMProperties; + getRealPropertyHeader(m_props, buf, object_id, sz); + saveHeader(m_props); + } + + if (!memcmp((void *)&object_id, "MDPR", 4)) + { + media_hdrs = new MediaProperties; + getMediaPropHeader(media_hdrs, buf, object_id, sz); + saveHeader(media_hdrs); + } + + if (!memcmp((void *)&object_id, "CONT", 4)) + { + m_contenthdr = new ContentDescription; + getContentDescription(m_contenthdr, buf, object_id, sz); + saveHeader(m_contenthdr); + } + + consumed = 0; + do + { + nbytes = getChunk(buf, 65536, object_id, sz, consumed); + } while ( !m_err && memcmp((void *)&object_id, "DATA", 4) && (consumed < sz) ); + } + } + + return 0; +} + +int RealMediaFF::getHdr(unsigned char *buf, size_t sz, UINT32 &fourcc, UINT32 &csz) +{ + int nbytes = 0, i = 0; + + if (sz < (size_t)RMFF_HDR_SIZE) + return 0; + + if ( (nbytes = read(m_fd, (void *) buf, RMFF_HDR_SIZE)) != RMFF_HDR_SIZE ) + { + m_err = -1; + + return (nbytes); + } + + memcpy((void *)&fourcc, buf, 4); i+=4; + UNPACK4(csz,buf,i); + + return nbytes; +} + +int RealMediaFF::getChunk(unsigned char *buf, size_t sz, UINT32 &fourcc, UINT32 &csz, UINT32 &alreadyconsumed) +{ + int nbytes = 0, i = 0, readamount; + csz = 0; + + if (!alreadyconsumed) + { + if ( (nbytes = getHdr(buf, sz, fourcc, csz)) != RMFF_HDR_SIZE ) + { + m_err = -1; + alreadyconsumed += nbytes > 0 ? nbytes : 0; + return nbytes; + } + alreadyconsumed += RMFF_HDR_SIZE; + readamount = csz - RMFF_HDR_SIZE; + i = RMFF_HDR_SIZE; + } + else + readamount = csz - alreadyconsumed; + + if ( (nbytes = read(m_fd, (void *) &buf[i], readamount > (int)sz - i ? (int)sz - i : readamount )) != readamount ) + { + if (nbytes < 0) + { + m_err = -1; + } + else + alreadyconsumed += nbytes; + + return (nbytes<0 ? i : i + nbytes); + } + + alreadyconsumed += nbytes; + return (csz); +} + +int RealMediaFF::getRealFileHeader(File_Header_v0_v1 *hdr, const unsigned char *buf, UINT32 object_id, int sz) +{ + int i = 0; + + // RealMedia header + hdr->s.object_id = object_id; + hdr->s.size = sz; + + i = RMFF_HDR_SIZE; + UNPACK2(hdr->object_version, buf, i); + + if ( !strncmp((const char *) &hdr->s.object_id, ".RMF", 4) && + (hdr->object_version == 0 || hdr->object_version == 1) ) + { + UNPACK4(hdr->file_version, buf, i); + UNPACK4(hdr->num_headers, buf, i); + } + return 0; +} + +int RealMediaFF::getRealPropertyHeader(RMProperties *props, const unsigned char *buf, UINT32 object_id, int sz) +{ + int i = 0; + + // Properties + props->s.object_id = object_id; + props->s.size = sz; + + i = RMFF_HDR_SIZE; + UNPACK2(props->object_version, buf, i); + + if ( !strncmp((const char *)&props->s.object_id,"PROP",4) && (props->object_version == 0) ) + { + UNPACK4(props->max_bit_rate, buf, i); + UNPACK4(props->avg_bit_rate, buf, i); + UNPACK4(props->max_packet_size, buf, i); + UNPACK4(props->avg_packet_size, buf, i); + UNPACK4(props->num_packets, buf, i); + UNPACK4(props->duration, buf, i); + UNPACK4(props->preroll, buf, i); + UNPACK4(props->index_offset, buf, i); + UNPACK4(props->data_offset, buf, i); + UNPACK2(props->num_streams, buf, i); + UNPACK2(props->flags, buf, i); + } + return 0; +} + + +int RealMediaFF::getMediaPropHeader(MediaProperties *media_hdr, const unsigned char *buf, UINT32 object_id, int sz) +{ + int i = 0; + + // Properties + media_hdr->s.object_id = object_id; + media_hdr->s.size = sz; + + i = RMFF_HDR_SIZE; + UNPACK2(media_hdr->object_version, buf, i); + + if ( !strncmp((const char *)&media_hdr->s.object_id, "MDPR", 4) && media_hdr->object_version == 0) + { + UNPACK2(media_hdr->stream_number, buf, i); + UNPACK4(media_hdr->max_bit_rate, buf, i); + UNPACK4(media_hdr->avg_bit_rate, buf, i); + UNPACK4(media_hdr->max_packet_size, buf, i); + UNPACK4(media_hdr->avg_packet_size, buf, i); + UNPACK4(media_hdr->start_time, buf, i); + UNPACK4(media_hdr->preroll, buf, i); + UNPACK4(media_hdr->duration, buf, i); + media_hdr->stream_name_size = buf[i]; i++; + memcpy(media_hdr->stream_name, &buf[i], media_hdr->stream_name_size); + media_hdr->stream_name[media_hdr->stream_name_size] = 0; + i += media_hdr->stream_name_size; + media_hdr->mime_type_size = buf[i]; i++; + memcpy(media_hdr->mime_type, &buf[i], media_hdr->mime_type_size); + i += media_hdr->mime_type_size; + UNPACK4(media_hdr->type_specific_len, buf, i); + if (media_hdr->type_specific_len) + { + media_hdr->type_specific_data = new UINT8[media_hdr->type_specific_len]; + memcpy(media_hdr->type_specific_data, &buf[i], media_hdr->type_specific_len); + + if (!strncmp((const char *)media_hdr->mime_type, "logical-fileinfo", 16)) + { + media_hdr->lstr = new LogicalStream; + UNPACK4(media_hdr->lstr->size, buf, i); + UNPACK2(media_hdr->lstr->object_version, buf, i); + if (media_hdr->lstr->object_version == 0) + { + UNPACK2(media_hdr->lstr->num_physical_streams, buf, i); + if (media_hdr->lstr->num_physical_streams > 0) + { + media_hdr->lstr->physical_stream_numbers = new UINT16[ media_hdr->lstr->num_physical_streams ]; + media_hdr->lstr->data_offsets = new UINT32[ media_hdr->lstr->num_physical_streams ]; + for (int j=0; jlstr->num_physical_streams; j++) + { + UNPACK2(media_hdr->lstr->physical_stream_numbers[j], buf, i); + } + for (int j=0; jlstr->num_physical_streams; j++) + { + UNPACK4(media_hdr->lstr->data_offsets[j], buf, i); + } + } + + UNPACK2(media_hdr->lstr->num_rules, buf, i); + if (media_hdr->lstr->num_rules > 0) + { + media_hdr->lstr->rule_to_physical_stream_number_map = new UINT16[ media_hdr->lstr->num_rules ]; + for (int j=0; jlstr->num_rules; j++) + { + UNPACK2(media_hdr->lstr->rule_to_physical_stream_number_map[j], buf, i); + } + } + UNPACK2(media_hdr->lstr->num_properties, buf, i); + if (media_hdr->lstr->num_properties > 0) + { + media_hdr->lstr->properties = new NameValueProperty[ media_hdr->lstr->num_properties ]; + for (int j=0; jlstr->num_properties; j++) + { + UNPACK4(media_hdr->lstr->properties[j].size, buf, i); + UNPACK2(media_hdr->lstr->properties[j].object_version, buf, i); + if (media_hdr->lstr->properties[j].object_version == 0) + { + media_hdr->lstr->properties[j].name_length = buf[i]; i++; + if (media_hdr->lstr->properties[j].name_length) + { + media_hdr->lstr->properties[j].name = new UINT8[ media_hdr->lstr->properties[j].name_length + 1]; + memcpy((void *)media_hdr->lstr->properties[j].name, (void *)&buf[i], + media_hdr->lstr->properties[j].name_length); + media_hdr->lstr->properties[j].name[ media_hdr->lstr->properties[j].name_length ] = 0; + i+=media_hdr->lstr->properties[j].name_length; + } + + UNPACK4(media_hdr->lstr->properties[j].type, buf, i); + UNPACK2(media_hdr->lstr->properties[j].value_length, buf, i); + if (media_hdr->lstr->properties[j].value_length) + { + media_hdr->lstr->properties[j].value_data = new UINT8[ media_hdr->lstr->properties[j].value_length + 1]; + memcpy((void *)media_hdr->lstr->properties[j].value_data, (void *)&buf[i], + media_hdr->lstr->properties[j].value_length); + media_hdr->lstr->properties[j].value_data[ media_hdr->lstr->properties[j].value_length ] = 0; + i+=media_hdr->lstr->properties[j].value_length; + } + } + } + } + } + else + media_hdr->lstr = 0; + } + } + else + media_hdr->type_specific_data = 0; + } + else + { + m_err = -1; + return m_err; + } + + return 0; +} + + +int RealMediaFF::getContentDescription(ContentDescription *cont, const unsigned char *buf, UINT32 object_id, int sz) +{ + int i = 0; + + // Properties + cont->s.object_id = object_id; + cont->s.size = sz; + + i = RMFF_HDR_SIZE; + UNPACK2(cont->object_version, buf, i); + + if ( !strncmp((const char *)&cont->s.object_id, "CONT", 4) && cont->object_version == 0) + { + UNPACK2(cont->title_len, buf, i); + cont->title = new UINT8[cont->title_len + 1]; + memcpy((void *)cont->title, (void *)&buf[i], cont->title_len); i+=cont->title_len; + m_title = (char *)cont->title; + m_title[cont->title_len] = 0; + + UNPACK2(cont->author_len, buf, i); + cont->author = new UINT8[cont->author_len + 1]; + memcpy((void *)cont->author, (void *)&buf[i], cont->author_len); i+=cont->author_len; + m_author = (char *)cont->author; + m_author[cont->author_len] = 0; + + UNPACK2(cont->copyright_len, buf, i); + cont->copyright = new UINT8[cont->copyright_len + 1]; + memcpy((void *)cont->copyright, (void *)&buf[i], cont->copyright_len); i+=cont->copyright_len; + m_copyright = (char *)cont->copyright; + m_copyright[cont->copyright_len] = 0; + + UNPACK2(cont->comment_len, buf, i); + cont->comment = new UINT8[cont->comment_len + 1]; + memcpy((void *)cont->comment, (void *)&buf[i], cont->comment_len); i+=cont->comment_len; + m_comment = (char *)cont->comment; + m_comment[cont->comment_len] = 0; + } + else + { + m_err = -1; + return m_err; + } + + return 0; +} + + +int RealMediaFF::seekChunk(UINT32 object_id) +{ + if (!m_err) + { + off_t s, tot; + UINT32 oid = 0, sz = 0; + unsigned char buf[255]; + int nbytes = 0; + + if ( (s = lseek(m_fd, 0, SEEK_SET)) != 0) + return -1; + + tot = 0; + while( (nbytes = getHdr(buf, 255, oid, sz)) == RMFF_HDR_SIZE && memcmp((void *)&oid, (void *)&object_id, 4) ) + { + tot += sz; + if (sz > (unsigned) RMFF_HDR_SIZE) + { + if ( (s = lseek(m_fd, sz - RMFF_HDR_SIZE, SEEK_CUR)) != tot ) + return -1; + } + else + return -1; // bail in this case, since the chuck sz includes the header size + } + if ( (s = lseek(m_fd, -RMFF_HDR_SIZE, SEEK_CUR)) != tot ) + return -1; + + return s; + } + return -1; +} + +int RealMediaFF::getMDProperties(MDProperties *props, const unsigned char *buf) +{ + int i = 0; + + int start = i; + + UNPACK4(props->size, buf, i); + UNPACK4(props->type, buf, i); + UNPACK4(props->flags, buf, i); + UNPACK4(props->value_offset, buf, i); + UNPACK4(props->subproperties_offset, buf, i); + UNPACK4(props->num_subproperties, buf, i); + UNPACK4(props->name_length, buf, i); + props->name = new UINT8[ props->name_length + 1 ]; + memcpy((void *)props->name, (void *)&buf[i], props->name_length); + props->name[ props->name_length ] = 0; + i+=props->name_length; + + i = start + props->value_offset; + UNPACK4(props->value_length, buf, i); + props->value = new UINT8[ props->value_length ]; + memcpy( (void *) props->value, (void *)&buf[i], props->value_length ); + + if ( (props->type == MPT_ULONG) || (props->type == MPT_FLAG && props->value_length == 4) ) + { + // wOOt! the Year is a ULONG, and its stored little endian?! my guess is this is a bug in + // RealPlayer 10 for Windows (where I created my test files) + // This hack is intended to ensure that we at least interpret the Year properly. + if (!strcmp((char *)props->name, "Year")) + { + if ( *(unsigned long *)props->value > 65536 ) + { + *(unsigned long *)(props->value) = ntohl(*(unsigned long *)(props->value)); + m_flipYearInMetadataSection = true; + } + else + m_flipYearInMetadataSection = false; + } + else + *(unsigned long *)(props->value) = ntohl(*(unsigned long *)(props->value)); + } + + i += props->value_length; + + i = start + props->subproperties_offset; + props->subproperties_list = new PropListEntry[ props->num_subproperties ]; + for (int j=0; j<(int)props->num_subproperties; j++) + { + UNPACK4(props->subproperties_list[j].offset, buf, i); + UNPACK4(props->subproperties_list[j].num_props_for_name, buf, i); + } + + props->subproperties = new MDProperties[ props->num_subproperties ]; + for (int j=0; j<(int)props->num_subproperties; j++) + { + i = start + props->subproperties_list[j].offset; + getMDProperties(&props->subproperties[j], &buf[i]); + } + + return 0; +} + +int RealMediaFF::initMetadataSection() +{ + UINT32 object_id; + off_t s; + int nbytes; + unsigned char buf[65536]; + UINT32 consumed; + + memcpy((void *)&object_id, "RMMD", 4); + if ( (s = seekChunk(object_id)) < 0 ) + { + m_err = -1; + return m_err; + } + + m_md = new MetadataSection; + consumed = 0; + nbytes = getChunk(buf, 65536, m_md->s.object_id, m_md->s.size, consumed); + if (nbytes < 0 || m_md->s.size != consumed || memcmp((void *)&m_md->s.object_id, "RMMD", 4)) + { + //std::cerr << "SERIOUS ERROR - not able to find the chunk I just seek'd to!\n"; + m_err = -1; + return m_err; + } + // Properties + int i = RMFF_HDR_SIZE; + memcpy((void *)&m_md->object_id, (void *)&buf[i], 4); i+=4; + UNPACK4(m_md->object_version, buf, i); + if ( !strncmp((const char *)&m_md->s.object_id, "RMMD", 4) ) + { + if (!getMDProperties(&m_md->properties, &buf[i])) + saveHeader(m_md); + } + else + { + m_err = -1; + return m_err; + } + + return 0; +} + +#ifdef TESTING + +void RealMediaFF::printRealFileHeader(std::ostream &os) +{ + char object_id[5]; + + if (m_hdr) + { + strncpy(object_id, (const char *)&m_hdr->s.object_id, 4); + object_id[4]=0; + + os << "HDR object_id: " << object_id << std::endl; + os << "HDR size: " << m_hdr->s.size << std::endl; + os << "HDR object version: " << m_hdr->object_version << std::endl; + os << "HDR file version: " << m_hdr->file_version << std::endl; + os << "HDR num headers: " << m_hdr->num_headers << std::endl; + } +} + + +void RealMediaFF::printRealPropHeader(std::ostream &os) +{ + char object_id[5]; + + if (m_props) + { + strncpy(object_id, (const char *)&m_props->s.object_id, 4); + object_id[4]=0; + + os << "PROPS object_id: " << object_id << std::endl; + os << "PROPS size: " << m_props->s.size << std::endl; + os << "PROPS object_version: " << m_props->object_version << std::endl; + + os << "PROPS max_bit_rate: " << m_props->max_bit_rate << std::endl; + os << "PROPS avg_bit_rate: " << m_props->avg_bit_rate << std::endl; + os << "PROPS max_packet_size: " << m_props->max_packet_size << std::endl; + os << "PROPS avg_packet_size: " << m_props->avg_packet_size << std::endl; + os << "PROPS num_packets: " << m_props->num_packets << std::endl; + os << "PROPS duration: " << m_props->duration << std::endl; + os << "PROPS preroll: " << m_props->preroll << std::endl; + os << "PROPS index_offset: " << m_props->index_offset << std::endl; + os << "PROPS data_offset: " << m_props->data_offset << std::endl; + os << "PROPS num_streams: " << m_props->num_streams << std::endl; + os << "PROPS flags: " << m_props->flags << std::endl; + } +} + + +void RealMediaFF::printMediaPropHeaders(std::ostream &os) +{ + int i = 0; + char object_id[5]; + MediaProperties *media_hdr = (MediaProperties *)m_head; + + while (media_hdr) + { + strncpy(object_id, (const char *)&media_hdr->s.object_id, 4); + object_id[4]=0; + + if (!strncmp(object_id, "MDPR", 4)) + { + os << "MEDIA HDR" << i << " object_id: " << object_id << std::endl; + os << "MEDIA HDR" << i << " size: " << media_hdr->s.size << std::endl; + os << "MEDIA HDR" << i << " max_bit_rate: " << media_hdr->max_bit_rate << std::endl; + os << "MEDIA HDR" << i << " avg_bit_rate: " << media_hdr->avg_bit_rate << std::endl; + os << "MEDIA HDR" << i << " max_packet_size: " << media_hdr->max_packet_size << std::endl; + os << "MEDIA HDR" << i << " avg_packet_size: " << media_hdr->avg_packet_size << std::endl; + os << "MEDIA HDR" << i << " start_time: " << media_hdr->start_time << std::endl; + os << "MEDIA HDR" << i << " preroll: " << media_hdr->preroll << std::endl; + os << "MEDIA HDR" << i << " duration: " << media_hdr->duration << std::endl; + os << "MEDIA HDR" << i << " stream_name: " << media_hdr->stream_name << std::endl; + os << "MEDIA HDR" << i << " mime type: " << media_hdr->mime_type << std::endl; + + + if (media_hdr->lstr) + { + os << "MEDIA HDR" << i << " LOGSTR info size: " << media_hdr->lstr->size << std::endl; + os << "MEDIA HDR" << i << " LOGSTR info num_physical_streams: " << media_hdr->lstr->num_physical_streams << std::endl; + os << "MEDIA HDR" << i << " LOGSTR info num_rules: " << media_hdr->lstr->num_rules << std::endl; + os << "MEDIA HDR" << i << " LOGSTR info num_properties: " << media_hdr->lstr->num_properties << std::endl; + for (int j=0; media_hdr->lstr->properties && jlstr->num_properties; j++) + { + if (media_hdr->lstr->properties[j].name) + os << "MEDIA HDR" << i << " LOGSTR info prop name: " << media_hdr->lstr->properties[j].name << std::endl; + os << "MEDIA HDR" << i << " LOGSTR info prop type: " << media_hdr->lstr->properties[j].type << std::endl; + os << "MEDIA HDR" << i << " LOGSTR info prop value_length: " << media_hdr->lstr->properties[j].value_length << std::endl; + if (media_hdr->lstr->properties[j].value_data) + { + if (media_hdr->lstr->properties[j].type == 0) + os << "MEDIA HDR" << i << " LOGSTR info prop value: " << + *(unsigned long *)media_hdr->lstr->properties[j].value_data << std::endl; + else if (media_hdr->lstr->properties[j].type == 2) + os << "MEDIA HDR" << i << " LOGSTR info prop value: " << media_hdr->lstr->properties[j].value_data << std::endl; + else + os << "MEDIA HDR" << i << " LOGSTR info prop value: \n"; + } + } + } + + i++; + } + media_hdr = (MediaProperties *)media_hdr->fwd; + } +} + + +void RealMediaFF::printContentDescription(std::ostream &os) +{ + char object_id[5]; + + if (m_contenthdr) + { + strncpy(object_id, (const char *)&m_contenthdr->s.object_id, 4); + object_id[4]=0; + + os << "CONT object_id: " << object_id << std::endl; + os << "CONT title(" << m_contenthdr->title_len << "):\t\t<" << m_contenthdr->title << ">" << std::endl; + os << "CONT author(" << m_contenthdr->author_len << "):\t\t<" << m_contenthdr->author << ">" << std::endl; + os << "CONT copyright(" << m_contenthdr->copyright_len << "):\t\t<" << m_contenthdr->copyright << ">" << std::endl; + os << "CONT comment(" << m_contenthdr->comment_len << "):\t\t<" << m_contenthdr->comment << ">" << std::endl; + } +} + +void RealMediaFF::printID3v1Tag(std::ostream &os) +{ + if (m_id3v1tag) + { + os << "ID3 tag : " << ID3v1::Tag::fileIdentifier() << std::endl; + os << "ID3 title : " << m_id3v1tag->tag()->title() << std::endl; + os << "ID3 artist : " << m_id3v1tag->tag()->artist() << std::endl; + os << "ID3 album : " << m_id3v1tag->tag()->album() << std::endl; + os << "ID3 year : " << m_id3v1tag->tag()->year() << std::endl; + os << "ID3 comment : " << m_id3v1tag->tag()->comment() << std::endl; + os << "ID3 track : " << m_id3v1tag->tag()->track() << std::endl; + os << "ID3 genre : " << m_id3v1tag->tag()->genre() << std::endl; + } +} + + +void RealMediaFF::printMDProperties(std::ostream &os, char *nam, MDProperties *props) +{ + char name[8192]; + + strcpy(name, nam); + os << "MDP subproperties for: " << name << std::endl; + + os << "MD properties.size: " << props->size << std::endl; + os << "MD properties.type: " << props->type << std::endl; + os << "MD properties.flags: " << props->flags << std::endl; + os << "MD properties.value_offset: " << props->value_offset << std::endl; + os << "MD properties.subproperties_offset: " << props->subproperties_offset << std::endl; + os << "MD properties.num_subproperties: " << props->num_subproperties << std::endl; + os << "MD properties.name_length: " << props->name_length << std::endl; + os << "MD properties.name: " << (char *)props->name << std::endl; + + os << "MD properties.value_length: " << props->value_length << std::endl; + + switch (props->type) + { + case MPT_TEXT: + case MPT_TEXTLIST: + case MPT_URL: + case MPT_DATE: + case MPT_FILENAME: + os << "MD properties.value: " << (char *)props->value << std::endl; + break; + case MPT_FLAG: + if (props->value_length == 4) + os << "MD properties.value: " << *(unsigned long *)props->value << std::endl; + else + os << "MD properties.value: " << *props->value << std::endl; + break; + case MPT_ULONG: + os << "MD properties.value: " << *(unsigned long *)props->value << std::endl; + break; + case MPT_BINARY: + os << "MD properties.value: " << std::endl; + break; + case MPT_GROUPING: + os << "MD properties.value: " << std::endl; + break; + case MPT_REFERENCE: + os << "MD properties.value: " << std::endl; + break; + } + + if (props->num_subproperties) + { + strcat(name, (char *)props->name); + strcat(name, "/"); + } + for (int j=0; jnum_subproperties; j++) + { + os << "MD properties.sub_properties_list[" << j << "].offset: " << + props->subproperties_list[j].offset << std::endl; + os << "MD properties.sub_properties_list[" << j << "].num_props_for_name: " << + props->subproperties_list[j].num_props_for_name << std::endl; + + os << std::endl; + + printMDProperties(os, name, &props->subproperties[j]); + } +} + + +void RealMediaFF::printMetadataSection(std::ostream &os) +{ + char name[8192]; + char oid[5]; + + memcpy((void *)oid, (void *)&m_md->s.object_id, 4); + oid[4] = 0; + + os << "MetadataSection: "; + os << "MS object_id: " << oid << std::endl; + os << "MS SIZE: " << m_md->s.size << std::endl; + os << "MD object_id: " << (char *)&m_md->object_id << std::endl; + os << "MD object_version: " << m_md->object_version << std::endl; + os << std::endl; + + strcpy(name, ""); + printMDProperties(os, name, &m_md->properties); +} + + +std::ostream &RealMediaFF::operator<<(std::ostream &os) +{ + if (m_readProperties) + { + printRealFileHeader(os); + printRealPropHeader(os); + printMediaPropHeaders(os); + printContentDescription(os); + printMetadataSection(os); + } + printID3v1Tag(os); + + return os; +} + +std::ostream &operator<<(std::ostream &os, RealMediaFF &rmff) +{ + rmff.operator<<(os); + + return os; +} + + +int main(int argc, char *argv[]) +{ + char *m_filen; + + if (argc > 1) + m_filen = argv[1]; + else + m_filen = "./Drown.ra"; + + RealMediaFF rmff(m_filen); + + if (!rmff.err()) + std::cout << rmff; + + /* + UINT32 oid = 0; + memcpy( (void *)&oid, (void *) ".RMF", 4); + off_t pos = rmff.seekChunk(oid); + std::cout << "POS=" << pos << std::endl; + + memcpy( (void *)&oid, (void *) "MDPR", 4); + pos = rmff.seekChunk(oid); + std::cout << "POS=" << pos << std::endl; + + memcpy( (void *)&oid, (void *) "RMMD", 4); + pos = rmff.seekChunk(oid); + std::cout << "POS=" << pos << std::endl; + */ +} +#endif diff --git a/src/metadata/rmff/rmff.h b/src/metadata/rmff/rmff.h new file mode 100644 index 0000000..326b8ae --- /dev/null +++ b/src/metadata/rmff/rmff.h @@ -0,0 +1,348 @@ +/*************************************************************************** + copyright : (C) 2005 by Paul Cifarelli + email : paulc2@optonline.net + ***************************************************************************/ + +/*************************************************************************** + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin St, 5th fl, Boston, MA 02110-1301, * + * USA, or check http://www.fsf.org/about/contact.html * + * * + * Note that no RealNetworks code appears or is duplicated, copied, or * + + used as a template in this code. The code was written from scratch * + * using the reference documentation found at: * + * * + * https://common.helixcommunity.org/nonav/2003/HCS_SDK_r5/helixsdk.htm * + * * + ***************************************************************************/ +#ifndef _RMFF_H_INCLUDED_ +#define _RMFF_H_INCLUDED_ + +#include + +namespace TagLib +{ + namespace RealMedia + { +#if SIZEOF_LONG == 4 + typedef unsigned long UINT32; +#elif SIZEOF_INT == 4 + typedef unsigned int UINT32; +#else +#error At least 1 builtin type needs to be 4 bytes!! +#endif + typedef unsigned short UINT16; + typedef unsigned char UINT8; + + static const int RMFF_HDR_SIZE = 8; // packed hdr size + + // some assumptions on these 2 enum defs, based solely on the order they are listed on the website + enum PROPERTY_TYPES + { + MPT_TEXT = 1, // The value is string data. + MPT_TEXTLIST, // The value is a separated list of strings, + // separator specified as sub-property/type descriptor. + MPT_FLAG, // The value is a boolean flag-either 1 byte or 4 bytes, check size value. + MPT_ULONG, // The value is a four-byte integer. + MPT_BINARY, // The value is a byte stream. + MPT_URL, // The value is string data. + MPT_DATE, // The value is a string representation of the date in the form: + // YYYYmmDDHHMMSS (m = month, M = minutes). + MPT_FILENAME, // The value is string data. + MPT_GROUPING, // This property has subproperties, but its own value is empty. + MPT_REFERENCE // The value is a large buffer of data, use sub-properties/type + // descriptors to identify mime-type. + }; + + enum PROPERTY_FLAGS + { + MPT_READONLY = 1, // Read only, cannot be modified. + MPT_PRIVATE = 2, // Private, do not expose to users. + MPT_TYPE_DESCRIPTOR = 4 // Type descriptor used to further define type of value. + }; + + struct Collectable + { + Collectable() : fwd(0) {} + virtual ~Collectable() {} + Collectable *fwd; + }; + + struct File_Header_Start + { + UINT32 object_id; + UINT32 size; + }; + + struct File_Header_v0_v1 : public Collectable + { + File_Header_Start s; + UINT16 object_version; + + UINT32 file_version; + UINT32 num_headers; + }; + + struct RMProperties : public Collectable + { + File_Header_Start s; + UINT16 object_version; + + UINT32 max_bit_rate; + UINT32 avg_bit_rate; + UINT32 max_packet_size; + UINT32 avg_packet_size; + UINT32 num_packets; + UINT32 duration; + UINT32 preroll; + UINT32 index_offset; + UINT32 data_offset; + UINT16 num_streams; + UINT16 flags; + }; + + + struct NameValueProperty + { + NameValueProperty() : name(0), value_data(0) {} + virtual ~NameValueProperty() { delete [] name; delete [] value_data; } + + UINT32 size; + UINT16 object_version; + + UINT8 name_length; + UINT8 *name; + UINT32 type; + UINT16 value_length; + UINT8 *value_data; + }; + + + struct LogicalStream + { + LogicalStream() : physical_stream_numbers(0), data_offsets(0), rule_to_physical_stream_number_map(0), properties(0) {} + virtual ~LogicalStream() + { delete [] physical_stream_numbers; delete [] data_offsets; + delete [] rule_to_physical_stream_number_map; delete [] properties; } + + UINT32 size; + UINT16 object_version; + + UINT16 num_physical_streams; + UINT16 *physical_stream_numbers; + UINT32 *data_offsets; + UINT16 num_rules; + UINT16 *rule_to_physical_stream_number_map; + UINT16 num_properties; + NameValueProperty *properties; + }; + + struct MediaProperties : public Collectable + { + MediaProperties() : type_specific_data(0), lstr(0) {} + virtual ~MediaProperties() { delete lstr; delete [] type_specific_data; } + + File_Header_Start s; + UINT16 object_version; + + UINT16 stream_number; + UINT32 max_bit_rate; + UINT32 avg_bit_rate; + UINT32 max_packet_size; + UINT32 avg_packet_size; + UINT32 start_time; + UINT32 preroll; + UINT32 duration; + UINT8 stream_name_size; + UINT8 stream_name[256]; + UINT8 mime_type_size; + UINT8 mime_type[256]; + UINT32 type_specific_len; + UINT8 *type_specific_data; + + LogicalStream *lstr; // only one of these + }; + + + struct ContentDescription : public Collectable + { + ContentDescription() : title(0), author(0), copyright(0), comment(0) {} + virtual ~ContentDescription() { delete [] title; delete [] author; delete [] copyright; delete [] comment; } + + File_Header_Start s; + UINT16 object_version; + + UINT16 title_len; + UINT8 *title; + UINT16 author_len; + UINT8 *author; + UINT16 copyright_len; + UINT8 *copyright; + UINT16 comment_len; + UINT8 *comment; + }; + + + struct PropListEntry + { + UINT32 offset; + UINT32 num_props_for_name; + }; + + struct MDProperties + { + MDProperties() : name(0), value(0), subproperties(0) {} + virtual ~MDProperties() + { delete [] name; delete [] value; delete [] subproperties_list; delete [] subproperties; } + + UINT32 size; + UINT32 type; + UINT32 flags; + UINT32 value_offset; + UINT32 subproperties_offset; + UINT32 num_subproperties; + UINT32 name_length; + UINT8 *name; + UINT32 value_length; + UINT8 *value; + PropListEntry *subproperties_list; // num_subproperties + MDProperties *subproperties; // num_subproperties + }; + + struct MetadataSection : public Collectable + { + File_Header_Start s; + + UINT32 object_id; + UINT32 object_version; + + // this is the 1 "unnamed root property" + MDProperties properties; + }; + + class Tag; + class File; + + // RealMedia File Format contains a normal ID3v1 Tag at the end of the file + // no sense reinventing the wheel, so this class is just so we can use TagLib + // to manage it + class RMFFile : public TagLib::File + { + public: + RMFFile(const char *filename); + virtual ~RMFFile(); + bool save(); + TagLib::Tag *tag() const { return m_id3tag; } + TagLib::AudioProperties *audioProperties() const { return 0; } + + private: + TagLib::ID3v1::Tag *m_id3tag; + }; + + class TagLib::AudioProperties; + + class RealMediaFF + { + public: + RealMediaFF(const char *file, bool readProperties = true, + TagLib::AudioProperties::ReadStyle propertiesStyle = TagLib::AudioProperties::Average); + RealMediaFF(RealMediaFF &src); + ~RealMediaFF(); + + int err() const { return m_err; } + bool isEmpty() const; + + // tag + TagLib::String title () const; + TagLib::String artist () const; + TagLib::String album () const; + TagLib::String comment () const; + TagLib::String genre () const; + TagLib::uint year () const; + TagLib::uint track () const; + // TODO write support + //void setTitle (const String &s); + //void setArtist (const String &s); + //void setAlbum (const String &s); + //void setComment (const String &s); + //void setGenre (const String &s); + //void setYear (uint i); + //void setTrack (uint i); + + // properties + int length () const; + int bitrate () const; + int sampleRate () const; + int channels () const; + +#ifdef TESTING + std::ostream &operator<<(std::ostream &os); +#endif + + private: + RealMediaFF(); + char *m_filename; + Collectable *m_head; + Collectable *m_tail; + int m_fd; + int m_err; + + File_Header_v0_v1 *m_hdr; + RMProperties *m_props; + MediaProperties *media_hdrs; + ContentDescription *m_contenthdr; + MetadataSection *m_md; + + char *m_title; + char *m_author; + char *m_copyright; + char *m_comment; + + RMFFile *m_id3v1tag; + + bool m_flipYearInMetadataSection; + bool m_readProperties; + + int init(); + int initMetadataSection(); + void saveHeader(Collectable *hdr); + int seekChunk(UINT32 object_id); + + int getHdr(unsigned char *buf, size_t sz, UINT32 &fourcc, UINT32 &csz); + int getChunk(unsigned char *buf, size_t sz, UINT32 &fourcc, UINT32 &csz, UINT32 &consumed); + int getRealFileHeader(File_Header_v0_v1 *hdr, const unsigned char *buf, UINT32 object_id, int sz); + int getRealPropertyHeader(RMProperties *props, const unsigned char *buf, UINT32 object_id, int sz); + int getMediaPropHeader(MediaProperties *mh, const unsigned char *buf, UINT32 object_id, int sz); + int getContentDescription(ContentDescription *cont, const unsigned char *buf, UINT32 object_id, int sz); + int getMDProperties(MDProperties *md, const unsigned char *buf); + +#ifdef TESTING + void printRealFileHeader(std::ostream &os); + void printRealPropHeader(std::ostream &os); + void printMediaPropHeaders(std::ostream &os); + void printContentDescription(std::ostream &os); + void printID3v1Tag(std::ostream &os); + void printMetadataSection(std::ostream &os); + void printMDProperties(std::ostream &os, char *name, MDProperties *props); +#endif + }; + + } // namespace RealMedia +} // namespace TagLib + +#ifdef TESTING +std::ostream &operator<<(std::ostream &os, TagLib::RealMedia::RealMediaFF &rmff); +#endif + +#endif diff --git a/src/metadata/rmff/taglib_realmediafile.cpp b/src/metadata/rmff/taglib_realmediafile.cpp new file mode 100644 index 0000000..b28c846 --- /dev/null +++ b/src/metadata/rmff/taglib_realmediafile.cpp @@ -0,0 +1,213 @@ +/*************************************************************************** + copyright : (C) 2005 by Paul Cifarelli + email : paulc2@optonline.net + + copyright : (C) 2005 by Lukas Lalinsky + email : lalinsky@gmail.com + (portions) + ***************************************************************************/ + +/*************************************************************************** + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2 or higher as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin St, 5th fl, Boston, MA 02110-1301, * + * USA, or check http://www.fsf.org/about/contact.html * + ***************************************************************************/ + +#include +#include +#include +#include +#include "rmff.h" +#include "taglib_realmediafile.h" + +using namespace TagLib; +using namespace TagLib::RealMedia; + + +RealMedia::Tag::Tag(RealMediaFF *rmff, bool allocnew) : m_rmff(rmff), m_owner(allocnew) +{ + if (m_owner) + m_rmff = new RealMediaFF(*rmff); +} + +RealMedia::Tag::~Tag () +{ + if (m_owner) + delete m_rmff; +} + +String RealMedia::Tag::title () const +{ + return m_rmff->title(); +} + +String RealMedia::Tag::artist () const +{ + return m_rmff->artist(); +} + +String RealMedia::Tag::album () const +{ + return m_rmff->album(); +} + +String RealMedia::Tag::comment () const +{ + return m_rmff->comment(); +} + +String RealMedia::Tag::genre () const +{ + return m_rmff->genre(); +} + +TagLib::uint RealMedia::Tag::year () const +{ + return m_rmff->year(); +} + +TagLib::uint RealMedia::Tag::track () const +{ + return m_rmff->track(); +} + +void RealMedia::Tag::setTitle (const String &) +{ +// TODO: write support +} + +void RealMedia::Tag::setArtist (const String &) +{ +// TODO: write support +} + +void RealMedia::Tag::setAlbum (const String &) +{ +// TODO: write support +} + +void RealMedia::Tag::setComment (const String &) +{ +// TODO: write support +} + +void RealMedia::Tag::setGenre (const String &) +{ +// TODO: write support +} + +void RealMedia::Tag::setYear (uint) +{ +// TODO: write support +} + +void RealMedia::Tag::setTrack (uint) +{ +// TODO: write support +} + +bool RealMedia::Tag::isEmpty() const +{ + return TagLib::Tag::isEmpty() && m_rmff->isEmpty(); +} + +void RealMedia::Tag::duplicate(const Tag *source, Tag *target, bool overwrite) +{ + TagLib::Tag::duplicate(source, target, overwrite); + if (overwrite) + { + if (target->m_owner) + { + delete target->m_rmff; + target->m_rmff = new RealMediaFF(*source->m_rmff); + } + else + target->m_rmff = source->m_rmff; + } + else + { + if (target->isEmpty()) + if (target->m_owner) + { + delete target->m_rmff; + target->m_rmff = new RealMediaFF(*source->m_rmff); + } + else + target->m_rmff = source->m_rmff; + } +} + + + +int RealMedia::Properties::length () const +{ + return (m_rmff->length() / 1000); +} + +int RealMedia::Properties::bitrate () const +{ + return (m_rmff->bitrate() / 1000); +} + +int RealMedia::Properties::sampleRate () const +{ + return m_rmff->sampleRate(); +} + +int RealMedia::Properties::channels () const +{ + return m_rmff->channels(); +} + + +RealMedia::File::File(const char *file, bool readProperties, Properties::ReadStyle propertiesStyle) + : TagLib::File(file), m_rmfile(0), m_tag(0), m_props(0) +{ + m_rmfile = new RealMediaFF(file, readProperties, propertiesStyle); + m_tag = new RealMedia::Tag(m_rmfile); + m_props = new RealMedia::Properties(m_rmfile); +} + +RealMedia::File::~File() +{ + delete m_props; + delete m_tag; + delete m_rmfile; +} + +TagLib::Tag *RealMedia::File::tag() const +{ + return m_tag; +} + +RealMedia::Tag *RealMedia::File::RealMediaTag() const +{ + return m_tag; +} + +RealMedia::Properties *RealMedia::File::audioProperties() const +{ + return m_props; // m_rmfile->properties; +} + + + + + diff --git a/src/metadata/rmff/taglib_realmediafile.h b/src/metadata/rmff/taglib_realmediafile.h new file mode 100644 index 0000000..0f0ca58 --- /dev/null +++ b/src/metadata/rmff/taglib_realmediafile.h @@ -0,0 +1,133 @@ +/*************************************************************************** + copyright : (C) 2005 by Paul Cifarelli + email : paulc2@optonline.net + + copyright : (C) 2005 by Lukas Lalinsky + email : lalinsky@gmail.com + (portions) + ***************************************************************************/ + +/*************************************************************************** + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2 or higher as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin St, 5th fl, Boston, MA 02110-1301, * + * USA, or check http://www.fsf.org/about/contact.html * + ***************************************************************************/ +#ifndef _TAGLIB_REALMEDIAFILE_H_ +#define _TAGLIB_REALMEDIAFILE_H_ + +#include +#include +#include + +#include + +class RealMediaFF; +namespace TagLib { + + namespace RealMedia { + + class Tag : public TagLib::Tag + { + public: + Tag(RealMediaFF *rmff, bool allocnew = false); + virtual ~Tag (); + virtual String title () const; + virtual String artist () const; + virtual String album () const; + virtual String comment () const; + virtual String genre () const; + virtual uint year () const; + virtual uint track () const; + virtual void setTitle (const String &s); + virtual void setArtist (const String &s); + virtual void setAlbum (const String &s); + virtual void setComment (const String &s); + virtual void setGenre (const String &s); + virtual void setYear (uint i); + virtual void setTrack (uint i); + + bool isEmpty() const; + void duplicate(const Tag *source, Tag *target, bool overwrite); + + private: + Tag(); + RealMediaFF *m_rmff; + bool m_owner; + }; + + + class Properties : public TagLib::AudioProperties + { + public: + Properties(RealMediaFF *rmff) : TagLib::AudioProperties(Average), m_rmff(rmff) {} + virtual ~Properties() {} // you don't own rmff + virtual int length () const; + virtual int bitrate () const; + virtual int sampleRate () const; + virtual int channels () const; + + private: + Properties(); + RealMediaFF *m_rmff; + }; + + class File : public TagLib::File + { + public: + + File(const char *file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); + + virtual ~File(); + + /* + * Returns the TagLib::Tag for this file. + */ + virtual TagLib::Tag *tag() const; + + /* + * Returns the RealMedia::RealMediaTag for this file. + */ + virtual Tag *RealMediaTag() const; + + /* + * Returns the RealMedia::Properties for this file. + */ + virtual Properties *audioProperties() const; + + + /* + * Save the file. + * + * This returns true if the save was successful. + */ + virtual bool save() { return false; } // for now + + private: + + RealMediaFF *m_rmfile; + Tag *m_tag; + Properties *m_props; + }; + + } + +} + +#endif diff --git a/src/metadata/rmff/taglib_realmediafiletyperesolver.cpp b/src/metadata/rmff/taglib_realmediafiletyperesolver.cpp new file mode 100644 index 0000000..a8660a6 --- /dev/null +++ b/src/metadata/rmff/taglib_realmediafiletyperesolver.cpp @@ -0,0 +1,53 @@ +/*************************************************************************** + copyright : (C) 2005 by Paul Cifarelli + email : paulc2@optonline.net + ***************************************************************************/ + +/*************************************************************************** + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +/*************************************************************************** + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin St, 5th fl, Boston, MA 02110-1301, * + * USA, or check http://www.fsf.org/about/contact.html * + * * + ***************************************************************************/ + +#include +#include +#include +#include "taglib_realmediafiletyperesolver.h" +#include "taglib_realmediafile.h" +#include "rmff.h" + +#include + +TagLib::File *RealMediaFileTypeResolver::createFile(const char *fileName, + bool readProperties, + TagLib::AudioProperties::ReadStyle propertiesStyle) const +{ + const char *ext = strrchr(fileName, '.'); + if(ext && (!strcasecmp(ext, ".ra") || !strcasecmp(ext, ".rv") || !strcasecmp(ext, ".rm") || + !strcasecmp(ext, ".rmj") || !strcasecmp(ext, ".rmvb") )) + { + TagLib::RealMedia::File *f = new TagLib::RealMedia::File(fileName, readProperties, propertiesStyle); + if(f->isValid()) + return f; + else + { + delete f; + } + } + + return 0; +} diff --git a/src/metadata/rmff/taglib_realmediafiletyperesolver.h b/src/metadata/rmff/taglib_realmediafiletyperesolver.h new file mode 100644 index 0000000..b292e10 --- /dev/null +++ b/src/metadata/rmff/taglib_realmediafiletyperesolver.h @@ -0,0 +1,39 @@ +/*************************************************************************** + copyright : (C) 2005 by Paul Cifarelli + email : paulc2@optonline.net + ***************************************************************************/ + +/*************************************************************************** + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +/*************************************************************************** + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin St, 5th fl, Boston, MA 02110-1301, * + * USA, or check http://www.fsf.org/about/contact.html * + * * + ***************************************************************************/ +#ifndef _TAGLIB_REALMEDIAFILETYPERESOLVER_H_ +#define _TAGLIB_REALMEDIAFILETYPERESOLVER_H_ + +#include +#include + + +class RealMediaFileTypeResolver : public TagLib::FileRef::FileTypeResolver +{ + TagLib::File *createFile(const char *fileName, + bool readAudioProperties, + TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; +}; + +#endif diff --git a/src/metadata/speex/Makefile.am b/src/metadata/speex/Makefile.am new file mode 100644 index 0000000..6bf01aa --- /dev/null +++ b/src/metadata/speex/Makefile.am @@ -0,0 +1,16 @@ +SUBDIRS = + +INCLUDES = $(all_includes) $(taglib_includes) +METASOURCES = AUTO +libtagspeex_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libtagspeex.la + +libtagspeex_la_SOURCES = \ + speexfile.cpp \ + speexproperties.cpp \ + taglib_speexfiletyperesolver.cpp + +noinst_HEADERS = speexfile.h \ + speexproperties.h \ + taglib_speexfiletyperesolver.h + diff --git a/src/metadata/speex/speexfile.cpp b/src/metadata/speex/speexfile.cpp new file mode 100644 index 0000000..eccaded --- /dev/null +++ b/src/metadata/speex/speexfile.cpp @@ -0,0 +1,111 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2002 by Scott Wheeler + email : wheeler@kde.org + (original Vorbis implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include + +#include +#if 0 +#include +#endif + +#include "speexfile.h" + +using namespace TagLib; + +class Speex::File::FilePrivate +{ +public: + FilePrivate() : + comment(0), + properties(0) {} + + ~FilePrivate() + { + delete comment; + delete properties; + } + + Ogg::XiphComment *comment; + Properties *properties; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Speex::File::File(const char *file, bool readProperties, + Properties::ReadStyle propertiesStyle) : Ogg::File(file) +{ + d = new FilePrivate; + read(readProperties, propertiesStyle); +} + +Speex::File::~File() +{ + delete d; +} + +Ogg::XiphComment *Speex::File::tag() const +{ + return d->comment; +} + +Speex::Properties *Speex::File::audioProperties() const +{ + return d->properties; +} + +bool Speex::File::save() +{ + if(!d->comment) + d->comment = new Ogg::XiphComment; + + setPacket(1, d->comment->render()); + + return Ogg::File::save(); +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void Speex::File::read(bool readProperties, Properties::ReadStyle propertiesStyle) +{ + ByteVector speexHeaderData = packet(0); + + if(!speexHeaderData.startsWith("Speex ")) { +#if 0 + debug("Speex::File::read() -- invalid Speex identification header"); +#endif + return; + } + + ByteVector commentHeaderData = packet(1); + + d->comment = new Ogg::XiphComment(commentHeaderData); + + if(readProperties) + d->properties = new Properties(this, propertiesStyle); +} diff --git a/src/metadata/speex/speexfile.h b/src/metadata/speex/speexfile.h new file mode 100644 index 0000000..d300ac3 --- /dev/null +++ b/src/metadata/speex/speexfile.h @@ -0,0 +1,93 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2002 by Scott Wheeler + email : wheeler@kde.org + (original Vorbis implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_SPEEXFILE_H +#define TAGLIB_SPEEXFILE_H + +#include +#include + +#include "speexproperties.h" + +namespace TagLib { + + //! A namespace containing classes for Speex metadata + + namespace Speex { + + //! An implementation of Ogg::File with Speex specific methods + + /*! + * This is the central class in the Ogg Speex metadata processing collection + * of classes. It's built upon Ogg::File which handles processing of the Ogg + * logical bitstream and breaking it down into pages which are handled by + * the codec implementations, in this case Speex specifically. + */ + + class File : public Ogg::File + { + public: + /*! + * Contructs a Speex file from \a file. If \a readProperties is true the + * file's audio properties will also be read using \a propertiesStyle. If + * false, \a propertiesStyle is ignored. + */ + File(const char *file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the XiphComment for this file. XiphComment implements the tag + * interface, so this serves as the reimplementation of + * TagLib::File::tag(). + */ + virtual Ogg::XiphComment *tag() const; + + /*! + * Returns the Speex::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + virtual bool save(); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + + class FilePrivate; + FilePrivate *d; + }; + } + +} + +#endif diff --git a/src/metadata/speex/speexproperties.cpp b/src/metadata/speex/speexproperties.cpp new file mode 100644 index 0000000..edd2b71 --- /dev/null +++ b/src/metadata/speex/speexproperties.cpp @@ -0,0 +1,171 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2002 by Scott Wheeler + email : wheeler@kde.org + (original Vorbis implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +#if 0 +#include +#endif + +#include + +#include "speexproperties.h" +#include "speexfile.h" + +using namespace TagLib; + +class Speex::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate(File *f, ReadStyle s) : + file(f), + style(s), + length(0), + bitrate(0), + sampleRate(0), + channels(0), + speexVersion(0), + vbr(false), + mode(0) {} + + File *file; + ReadStyle style; + int length; + int bitrate; + int sampleRate; + int channels; + int speexVersion; + bool vbr; + int mode; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Speex::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style) +{ + d = new PropertiesPrivate(file, style); + read(); +} + +Speex::Properties::~Properties() +{ + delete d; +} + +int Speex::Properties::length() const +{ + return d->length; +} + +int Speex::Properties::bitrate() const +{ + return int(float(d->bitrate) / float(1000) + 0.5); +} + +int Speex::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int Speex::Properties::channels() const +{ + return d->channels; +} + +int Speex::Properties::speexVersion() const +{ + return d->speexVersion; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void Speex::Properties::read() +{ + // Get the identification header from the Ogg implementation. + + ByteVector data = d->file->packet(0); + + int pos = 28; + + // speex_version_id; /**< Version for Speex (for checking compatibility) */ + d->speexVersion = data.mid(pos, 4).toUInt(false); + pos += 4; + + // header_size; /**< Total size of the header ( sizeof(SpeexHeader) ) */ + pos += 4; + + // rate; /**< Sampling rate used */ + d->sampleRate = data.mid(pos, 4).toUInt(false); + pos += 4; + + // mode; /**< Mode used (0 for narrowband, 1 for wideband) */ + d->mode = data.mid(pos, 4).toUInt(false); + pos += 4; + + // mode_bitstream_version; /**< Version ID of the bit-stream */ + pos += 4; + + // nb_channels; /**< Number of channels encoded */ + d->channels = data.mid(pos, 4).toUInt(false); + pos += 4; + + // bitrate; /**< Bit-rate used */ + d->bitrate = data.mid(pos, 4).toUInt(false); + pos += 4; + + // frame_size; /**< Size of frames */ + //unsigned int frameSize = data.mid(pos, 4).toUInt(false); + pos += 4; + + // vbr; /**< 1 for a VBR encoding, 0 otherwise */ + d->vbr = data.mid(pos, 4).toUInt(false) == 1; + pos += 4; + + // frames_per_packet; /**< Number of frames stored per Ogg packet */ + //unsigned int framesPerPacket = data.mid(pos, 4).toUInt(false); + + const Ogg::PageHeader *first = d->file->firstPageHeader(); + const Ogg::PageHeader *last = d->file->lastPageHeader(); + + if(first && last) { + long long start = first->absoluteGranularPosition(); + long long end = last->absoluteGranularPosition(); + + if(start >= 0 && end >= 0 && d->sampleRate > 0) + d->length = (end - start) / (long long) d->sampleRate; +#if 0 + else + debug("Speex::Properties::read() -- Either the PCM values for the start or " + "end of this file was incorrect or the sample rate is zero."); +#endif + } +#if 0 + else + debug("Speex::Properties::read() -- Could not find valid first and last Ogg pages."); +#endif +} diff --git a/src/metadata/speex/speexproperties.h b/src/metadata/speex/speexproperties.h new file mode 100644 index 0000000..355ff3c --- /dev/null +++ b/src/metadata/speex/speexproperties.h @@ -0,0 +1,83 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2002 by Scott Wheeler + email : wheeler@kde.org + (original Vorbis implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_SPEEXPROPERTIES_H +#define TAGLIB_SPEEXPROPERTIES_H + +#include + +namespace TagLib { + + namespace Speex { + + class File; + + //! An implementation of audio property reading for Ogg Speex + + /*! + * This reads the data from an Ogg Speex stream found in the AudioProperties + * API. + */ + + class Properties : public AudioProperties + { + public: + /*! + * Create an instance of Vorbis::Properties with the data read from the + * Vorbis::File \a file. + */ + Properties(File *file, ReadStyle style = Average); + + /*! + * Destroys this VorbisProperties instance. + */ + virtual ~Properties(); + + // Reimplementations. + + virtual int length() const; + virtual int bitrate() const; + virtual int sampleRate() const; + virtual int channels() const; + + /*! + * Returns the Vorbis version, currently "0" (as specified by the spec). + */ + int speexVersion() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } + +} + +#endif diff --git a/src/metadata/speex/taglib_speexfiletyperesolver.cpp b/src/metadata/speex/taglib_speexfiletyperesolver.cpp new file mode 100644 index 0000000..9a5de0d --- /dev/null +++ b/src/metadata/speex/taglib_speexfiletyperesolver.cpp @@ -0,0 +1,44 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : aumuell@reserv.at + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "taglib_speexfiletyperesolver.h" +#include "speexfile.h" + +#include + +TagLib::File *SpeexFileTypeResolver::createFile(const char *fileName, + bool readProperties, + TagLib::AudioProperties::ReadStyle propertiesStyle) const +{ + const char *ext = strrchr(fileName, '.'); + if(ext && !strcasecmp(ext, ".spx")) + { + TagLib::Speex::File *f = new TagLib::Speex::File(fileName, readProperties, propertiesStyle); + if(f->isValid()) + return f; + else + { + delete f; + } + } + + return 0; +} diff --git a/src/metadata/speex/taglib_speexfiletyperesolver.h b/src/metadata/speex/taglib_speexfiletyperesolver.h new file mode 100644 index 0000000..b5c5c2c --- /dev/null +++ b/src/metadata/speex/taglib_speexfiletyperesolver.h @@ -0,0 +1,36 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : aumuell@reserv.at + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_SPEEXFILETYPERESOLVER_H +#define TAGLIB_SPEEXFILETYPERESOLVER_H + +#include +#include + + +class SpeexFileTypeResolver : public TagLib::FileRef::FileTypeResolver +{ + TagLib::File *createFile(const char *fileName, + bool readAudioProperties, + TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; +}; + +#endif diff --git a/src/metadata/tagengine.cpp b/src/metadata/tagengine.cpp new file mode 100755 index 0000000..34abd23 --- /dev/null +++ b/src/metadata/tagengine.cpp @@ -0,0 +1,419 @@ + +#include "tagengine.h" + +#include + +// #include +#include +#include //used to load genre list +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "wavpack/wvfile.h" +#include "trueaudio/ttafile.h" + +#include +#ifdef HAVE_MP4V2 +#include "mp4/mp4file.h" +#include "mp4/mp4tag.h" +#else +#include "m4a/mp4file.h" +#include "m4a/mp4itunestag.h" +#endif + + +// TODO COMPILATION tag +// FIXME BPM tag + +TagData::TagData( const QString& _artist, const QString& _composer, + const QString& _album, const QString& _title, + const QString& _genre, const QString& _comment, + int _track, int _disc, int _year, + int _length, int _fileSize, int _bitrate, int _samplingRate ) +{ + artist = _artist; + composer = _composer; + album = _album; + title = _title; + genre = _genre; + comment = _comment; + track = _track; + disc = _disc; + year = _year; + length = _length; + fileSize = _fileSize; + bitrate = _bitrate; + samplingRate = _samplingRate; +} + +TagData::~TagData() +{} + + +TagEngine::TagEngine() +{ + TagLib::StringList genres = TagLib::ID3v1::genreList(); + for( TagLib::StringList::ConstIterator it = genres.begin(), end = genres.end(); it != end; ++it ) + genreList += TStringToQString( (*it) ); + + genreList.sort(); +} + +TagEngine::~TagEngine() +{} + +TagData* TagEngine::readTags( const QString& file ) +{ + TagLib::FileRef fileref( QFile::encodeName(file) ); + TagData* tagData = new TagData(); + + if( !fileref.isNull() ) + { + TagLib::Tag *tag = fileref.tag(); + + tagData->track = 0; + tagData->year = 0; + tagData->disc = 0; + tagData->track_gain = 210588; // 0 is a valid value + tagData->album_gain = 210588; + + if( tag ) + { + tagData->title = TStringToQString( tag->title() ).stripWhiteSpace(); + tagData->artist = TStringToQString( tag->artist() ).stripWhiteSpace(); + tagData->album = TStringToQString( tag->album() ).stripWhiteSpace(); + tagData->genre = TStringToQString( tag->genre() ).stripWhiteSpace(); + tagData->comment = TStringToQString( tag->comment() ).stripWhiteSpace(); + tagData->track = tag->track(); + tagData->year = tag->year(); + } + + TagLib::AudioProperties *audioProperties = fileref.audioProperties(); + + if( audioProperties ) + { + tagData->length = audioProperties->length(); + // TODO read all information + //tagData->fileSize = ; + // = audioProperties->channels(); + //tagData->bitrate = audioProperties->bitrate(); + tagData->samplingRate = audioProperties->sampleRate(); + } + + QString disc; + QString track_gain; + QString album_gain; + if ( TagLib::MPEG::File *file = dynamic_cast( fileref.file() ) ) + { + if ( file->ID3v2Tag() ) + { + if ( !file->ID3v2Tag()->frameListMap()[ "TPOS" ].isEmpty() ) + disc = TStringToQString( file->ID3v2Tag()->frameListMap()["TPOS"].front()->toString() ).stripWhiteSpace(); + + if ( !file->ID3v2Tag()->frameListMap()[ "TCOM" ].isEmpty() ) + tagData->composer = TStringToQString( file->ID3v2Tag()->frameListMap()["TCOM"].front()->toString() ).stripWhiteSpace(); + } + if ( file->APETag() ) + { + if ( !file->APETag()->itemListMap()[ "REPLAYGAIN_TRACK_GAIN" ].isEmpty() ) + track_gain = TStringToQString( file->APETag()->itemListMap()["REPLAYGAIN_TRACK_GAIN"].toString() ).stripWhiteSpace(); + + if ( !file->APETag()->itemListMap()[ "REPLAYGAIN_ALBUM_GAIN" ].isEmpty() ) + album_gain = TStringToQString( file->APETag()->itemListMap()["REPLAYGAIN_ALBUM_GAIN"].toString() ).stripWhiteSpace(); + } + } + else if ( TagLib::Ogg::Vorbis::File *file = dynamic_cast( fileref.file() ) ) + { + if ( file->tag() ) + { + if ( !file->tag()->fieldListMap()[ "COMPOSER" ].isEmpty() ) + tagData->composer = TStringToQString( file->tag()->fieldListMap()["COMPOSER"].front() ).stripWhiteSpace(); + + if ( !file->tag()->fieldListMap()[ "DISCNUMBER" ].isEmpty() ) + disc = TStringToQString( file->tag()->fieldListMap()["DISCNUMBER"].front() ).stripWhiteSpace(); + + if ( !file->tag()->fieldListMap()[ "REPLAYGAIN_TRACK_GAIN" ].isEmpty() ) + track_gain = TStringToQString( file->tag()->fieldListMap()["REPLAYGAIN_TRACK_GAIN"].front() ).stripWhiteSpace(); + + if ( !file->tag()->fieldListMap()[ "REPLAYGAIN_ALBUM_GAIN" ].isEmpty() ) + album_gain = TStringToQString( file->tag()->fieldListMap()["REPLAYGAIN_ALBUM_GAIN"].front() ).stripWhiteSpace(); + } + } + else if ( TagLib::FLAC::File *file = dynamic_cast( fileref.file() ) ) + { + if ( file->xiphComment() ) + { + if ( !file->xiphComment()->fieldListMap()[ "COMPOSER" ].isEmpty() ) + tagData->composer = TStringToQString( file->xiphComment()->fieldListMap()["COMPOSER"].front() ).stripWhiteSpace(); + + if ( !file->xiphComment()->fieldListMap()[ "DISCNUMBER" ].isEmpty() ) + disc = TStringToQString( file->xiphComment()->fieldListMap()["DISCNUMBER"].front() ).stripWhiteSpace(); + + if ( !file->xiphComment()->fieldListMap()[ "REPLAYGAIN_TRACK_GAIN" ].isEmpty() ) + track_gain = TStringToQString( file->xiphComment()->fieldListMap()["REPLAYGAIN_TRACK_GAIN"].front() ).stripWhiteSpace(); + + if ( !file->xiphComment()->fieldListMap()[ "REPLAYGAIN_ALBUM_GAIN" ].isEmpty() ) + album_gain = TStringToQString( file->xiphComment()->fieldListMap()["REPLAYGAIN_ALBUM_GAIN"].front() ).stripWhiteSpace(); + } + + /*if ( file->tag() ) + { + if ( !file->tag()->fieldListMap()[ "REPLAYGAIN_TRACK_GAIN" ].isEmpty() ) + track_gain = TStringToQString( file->tag()->fieldListMap()["REPLAYGAIN_TRACK_GAIN"].front() ).stripWhiteSpace(); + + if ( !file->tag()->fieldListMap()[ "REPLAYGAIN_ALBUM_GAIN" ].isEmpty() ) + album_gain = TStringToQString( file->tag()->fieldListMap()["REPLAYGAIN_ALBUM_GAIN"].front() ).stripWhiteSpace(); + }*/ + } + else if ( TagLib::MP4::File *file = dynamic_cast( fileref.file() ) ) + { + TagLib::MP4::Tag *mp4tag = dynamic_cast( file->tag() ); + if( mp4tag ) + { + tagData->composer = TStringToQString( mp4tag->composer() ); + + disc = QString::number( mp4tag->disk() ); + } + } +/* else if ( TagLib::MPC::File *file = dynamic_cast( fileref.file() ) ) + { + if ( file->APETag() ) + { + if ( !file->APETag()->itemListMap()[ "REPLAYGAIN_TRACK_GAIN" ].isEmpty() ) + track_gain = TStringToQString( file->APETag()->itemListMap()["REPLAYGAIN_TRACK_GAIN"].toString() ).stripWhiteSpace(); + + if ( !file->APETag()->itemListMap()[ "REPLAYGAIN_ALBUM_GAIN" ].isEmpty() ) + album_gain = TStringToQString( file->APETag()->itemListMap()["REPLAYGAIN_ALBUM_GAIN"].toString() ).stripWhiteSpace(); + } + }*/ + else if ( TagLib::WavPack::File *file = dynamic_cast( fileref.file() ) ) + { + if ( file->APETag() ) + { + if ( !file->APETag()->itemListMap()[ "REPLAYGAIN_TRACK_GAIN" ].isEmpty() ) + track_gain = TStringToQString( file->APETag()->itemListMap()["REPLAYGAIN_TRACK_GAIN"].toString() ).stripWhiteSpace(); + + if ( !file->APETag()->itemListMap()[ "REPLAYGAIN_ALBUM_GAIN" ].isEmpty() ) + album_gain = TStringToQString( file->APETag()->itemListMap()["REPLAYGAIN_ALBUM_GAIN"].toString() ).stripWhiteSpace(); + } + } + else if ( TagLib::TTA::File *file = dynamic_cast( fileref.file() ) ) + { + if ( file->ID3v2Tag() ) + { + if ( !file->ID3v2Tag()->frameListMap()[ "TPOS" ].isEmpty() ) + disc = TStringToQString( file->ID3v2Tag()->frameListMap()["TPOS"].front()->toString() ).stripWhiteSpace(); + + if ( !file->ID3v2Tag()->frameListMap()[ "TCOM" ].isEmpty() ) + tagData->composer = TStringToQString( file->ID3v2Tag()->frameListMap()["TCOM"].front()->toString() ).stripWhiteSpace(); + } + } + + if( !disc.isEmpty() ) + { + int i = disc.find('/'); + if( i != -1 ) + // disc.right( i ).toInt() is total number of discs, we don't use this at the moment + tagData->disc = disc.left( i ).toInt(); + else + tagData->disc = disc.toInt(); + } + + if( !track_gain.isEmpty() ) + { + int i = track_gain.find(' '); + if( i != -1 ) + tagData->track_gain = track_gain.left( i ).toFloat(); + else + tagData->track_gain = track_gain.toFloat(); + } + + if( !album_gain.isEmpty() ) + { + int i = album_gain.find(' '); + if( i != -1 ) + tagData->album_gain = album_gain.left( i ).toFloat(); + else + tagData->album_gain = album_gain.toFloat(); + } + + return tagData; + } + + return 0; +} + +bool TagEngine::writeTags( const QString& file, TagData* tagData ) +{ + if( !tagData ) tagData = new TagData(); + + //Set default codec to UTF-8 (see bugs 111246 and 111232) + TagLib::ID3v2::FrameFactory::instance()->setDefaultTextEncoding( TagLib::String::UTF8 ); + + TagLib::FileRef fileref( QFile::encodeName(file), false ); + + if ( !fileref.isNull() ) + { + TagLib::Tag* tag = fileref.tag(); + if ( tag ) + { + tag->setTitle( QStringToTString(tagData->title) ); + tag->setArtist( QStringToTString(tagData->artist) ); + tag->setAlbum( QStringToTString(tagData->album) ); + tag->setTrack( tagData->track ); + tag->setYear( tagData->year ); + tag->setComment( QStringToTString(tagData->comment) ); + tag->setGenre( QStringToTString(tagData->genre) ); + } + else + { + return false; + } + + if ( TagLib::MPEG::File *file = dynamic_cast( fileref.file() ) ) + { + if ( file->ID3v2Tag() ) + { + if ( !file->ID3v2Tag()->frameListMap()[ "TPOS" ].isEmpty() ) + { + file->ID3v2Tag()->frameListMap()[ "TPOS" ].front()->setText( QStringToTString( QString::number(tagData->disc) ) ); + } + else + { + TagLib::ID3v2::TextIdentificationFrame *frame = new TagLib::ID3v2::TextIdentificationFrame( "TPOS", TagLib::ID3v2::FrameFactory::instance()->defaultTextEncoding() ); + frame->setText( QStringToTString( QString::number(tagData->disc) ) ); + file->ID3v2Tag()->addFrame( frame ); + } + + if ( !file->ID3v2Tag()->frameListMap()[ "TCOM" ].isEmpty() ) + { + file->ID3v2Tag()->frameListMap()[ "TCOM" ].front()->setText( QStringToTString( tagData->composer ) ); + } + else + { + TagLib::ID3v2::TextIdentificationFrame *frame = new TagLib::ID3v2::TextIdentificationFrame( "TCOM", TagLib::ID3v2::FrameFactory::instance()->defaultTextEncoding() ); + frame->setText( QStringToTString( tagData->composer ) ); + file->ID3v2Tag()->addFrame( frame ); + } + + // HACK sets the id3v2 genre tag as string + if ( !file->ID3v2Tag()->frameListMap()[ "TCON" ].isEmpty() ) + { + file->ID3v2Tag()->frameListMap()[ "TCON" ].front()->setText( QStringToTString( tagData->genre ) ); + } + else + { + TagLib::ID3v2::TextIdentificationFrame *frame = new TagLib::ID3v2::TextIdentificationFrame( "TCON", TagLib::ID3v2::FrameFactory::instance()->defaultTextEncoding() ); + frame->setText( QStringToTString( tagData->genre ) ); + file->ID3v2Tag()->addFrame( frame ); + } + + // HACK sets the id3v2 year tag + if ( !file->ID3v2Tag()->frameListMap()[ "TYER" ].isEmpty() ) + { + file->ID3v2Tag()->frameListMap()[ "TYER" ].front()->setText( QStringToTString( QString::number(tagData->year) ) ); + } + else + { + TagLib::ID3v2::TextIdentificationFrame *frame = new TagLib::ID3v2::TextIdentificationFrame( "TYER", TagLib::ID3v2::FrameFactory::instance()->defaultTextEncoding() ); + frame->setText( QStringToTString( QString::number(tagData->year) ) ); + file->ID3v2Tag()->addFrame( frame ); + } + } + } + else if ( TagLib::Ogg::Vorbis::File *file = dynamic_cast( fileref.file() ) ) + { + if ( file->tag() ) + { + file->tag()->addField( "COMPOSER", QStringToTString( tagData->composer ), true ); + + file->tag()->addField( "DISCNUMBER", QStringToTString( QString::number(tagData->disc) ), true ); + } + } + else if ( TagLib::FLAC::File *file = dynamic_cast( fileref.file() ) ) + { + if ( file->xiphComment() ) + { + file->xiphComment()->addField( "COMPOSER", QStringToTString( tagData->composer ), true ); + + file->xiphComment()->addField( "DISCNUMBER", QStringToTString( QString::number(tagData->disc) ), true ); + } + } + else if ( TagLib::MP4::File *file = dynamic_cast( fileref.file() ) ) + { + TagLib::MP4::Tag *mp4tag = dynamic_cast( file->tag() ); + if( mp4tag ) + { + mp4tag->setComposer( QStringToTString( tagData->composer ) ); + + mp4tag->setDisk( tagData->disc ); + } + } + if ( TagLib::TTA::File *file = dynamic_cast( fileref.file() ) ) + { + if ( file->ID3v2Tag() ) + { + if ( !file->ID3v2Tag()->frameListMap()[ "TPOS" ].isEmpty() ) + { + file->ID3v2Tag()->frameListMap()[ "TPOS" ].front()->setText( QStringToTString( QString::number(tagData->disc) ) ); + } + else + { + TagLib::ID3v2::TextIdentificationFrame *frame = new TagLib::ID3v2::TextIdentificationFrame( "TPOS", TagLib::ID3v2::FrameFactory::instance()->defaultTextEncoding() ); + frame->setText( QStringToTString( QString::number(tagData->disc) ) ); + file->ID3v2Tag()->addFrame( frame ); + } + + if ( !file->ID3v2Tag()->frameListMap()[ "TCOM" ].isEmpty() ) + { + file->ID3v2Tag()->frameListMap()[ "TCOM" ].front()->setText( QStringToTString( tagData->composer ) ); + } + else + { + TagLib::ID3v2::TextIdentificationFrame *frame = new TagLib::ID3v2::TextIdentificationFrame( "TCOM", TagLib::ID3v2::FrameFactory::instance()->defaultTextEncoding() ); + frame->setText( QStringToTString( tagData->composer ) ); + file->ID3v2Tag()->addFrame( frame ); + } + } + } + + return fileref.save(); + } + return false; +} + +// bool TagEngine::canWrite( QString format ) +// { +// format = format.lower(); +// +// if( format == "ogg" || +// format == "flac" || format == "fla" || +// format == "mp3" || // TODO mp2 ? +// format == "mpc" || +// format == "aac" || +// format == "ape" || format == "mac" || +// format == "aa" || +// format == "m4a" || format == "m4b" || format == "m4p" || format == "mp4" || format == "m4v" || format == "mp4v" || +// format == "ra" || format == "rv" || format == "rm" || format == "rmj" || format == "rmvb" || +// format == "wma" || format == "asf" ) +// { +// return true; +// } +// else { +// return false; +// } +// } + diff --git a/src/metadata/tagengine.h b/src/metadata/tagengine.h new file mode 100755 index 0000000..e21a48c --- /dev/null +++ b/src/metadata/tagengine.h @@ -0,0 +1,79 @@ + + +#ifndef TAGENGINE_H +#define TAGENGINE_H + +#include +#include + +/** + * @short All metainformation can be stored in this class + * @author Daniel Faust + * @version 0.3 + */ +class TagData +{ +public: + /** + * Constructor + */ + TagData( const QString& _artist = QString::null, const QString& _composer = QString::null, + const QString& _album = QString::null, const QString& _title = QString::null, + const QString& _genre = QString::null, const QString& _comment = QString::null, + int _track = 0, int _disc = 0, int _year = 0, + int _length = 0, int _fileSize = 0, int _bitrate = 0, int _samplingRate = 0 ); + + /** + * Destructor + */ + virtual ~TagData(); + + /** The tags */ + QString artist; + QString composer; + QString album; + QString title; + QString genre; + QString comment; + int track; + int disc; + int year; + float track_gain; + float album_gain; + + /** The technical information */ + int length; + int fileSize; + int bitrate; + int samplingRate; +}; + + +/** + * @short Manages everything that has something to do with tags + * @author Daniel Faust + * @version 0.3 + */ +class TagEngine +{ +public: + /** + * Constructor + */ + TagEngine(); + + /** + * Destructor + */ + virtual ~TagEngine(); + + /** A list of all genre */ + QStringList genreList; + + TagData* readTags( const QString& file ); + bool writeTags( const QString& file, TagData* tagData ); + +// bool canWrite( QString format ); // NOTE no const because this string is being modyfied +}; + +#endif // TAGENGINE_H diff --git a/src/metadata/tplugins.cpp b/src/metadata/tplugins.cpp new file mode 100755 index 0000000..b84d601 --- /dev/null +++ b/src/metadata/tplugins.cpp @@ -0,0 +1,151 @@ +/*************************************************************************** + copyright : (C) 2005, 2006 by Martin Aumueller + email : aumuell@reserv.at + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +// #include + +#include +#include + +#include +#include + +#ifdef HAVE_MP4V2 +#include "mp4/taglib_mp4filetyperesolver.h" +#include "mp4/mp4file.h" +#else +#include "m4a/taglib_mp4filetyperesolver.h" +#include "m4a/mp4file.h" +#endif + +#include "trueaudio/taglib_trueaudiofiletyperesolver.h" +#include "trueaudio/ttafile.h" +#include "wavpack/taglib_wavpackfiletyperesolver.h" +#include "wavpack/wvfile.h" +#include "speex/taglib_speexfiletyperesolver.h" +#include "speex/speexfile.h" +#include "asf/taglib_asffiletyperesolver.h" +#include "asf/asffile.h" +#include "rmff/taglib_realmediafiletyperesolver.h" +#include "rmff/taglib_realmediafile.h" +#include "audible/taglib_audiblefiletyperesolver.h" +#include "audible/taglib_audiblefile.h" +#include "wav/wavfiletyperesolver.h" +#include "wav/wavfile.h" +#include "aac/aacfiletyperesolver.h" +#include "ape/taglib_monkeysaudiofiletyperesolver.h" +#include "optimfrog/taglib_optimfrogfiletyperesolver.h" + +#include +#include +#include +#include +#include +#include + + +class MimeTypeFileTypeResolver : public TagLib::FileRef::FileTypeResolver +{ + TagLib::File *createFile(const char *fileName, + bool readAudioProperties, + TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; +}; + +TagLib::File *MimeTypeFileTypeResolver::createFile(const char *fileName, + bool readProperties, + TagLib::AudioProperties::ReadStyle propertiesStyle) const +{ + QString fn = QFile::decodeName( fileName ); + int accuracy = 0; + + KMimeType::Ptr mimetype = KMimeType::findByFileContent( fn, &accuracy ); + if( accuracy <= 0 ) + mimetype = KMimeType::findByPath( fn ); + + if( mimetype->is( "audio/aac" ) + || mimetype->is( "audio/mpeg" ) + || mimetype->is( "audio/mpegurl" ) + || mimetype->is( "audio/x-mpegurl" ) + || mimetype->is( "audio/x-mp3" )) + { + return new TagLib::MPEG::File(fileName, readProperties, propertiesStyle); + } + else if( mimetype->is( "audio/mp4" ) || mimetype->is( "video/mp4" ) ) + { + return new TagLib::MP4::File(fileName, readProperties, propertiesStyle); + } + else if( mimetype->is( "audio/x-ms-wma" ) + || mimetype->is( "video/x-ms-asf" ) + || mimetype->is( "video/x-msvideo" ) + || mimetype->is( "video/x-ms-wmv" ) ) + { + return new TagLib::ASF::File(fileName, readProperties, propertiesStyle); + } + else if( mimetype->is( "audio/vnd.rn-realaudio" ) + || mimetype->is( "audio/x-pn-realaudio" ) + || mimetype->is( "audio/x-pn-realaudioplugin" ) + || mimetype->is( "audio/vnd.rn-realvideo" ) ) + { + return new TagLib::RealMedia::File(fileName, readProperties, propertiesStyle); + } + else if( mimetype->is( "audio/vorbis" ) ) + { + return new TagLib::Ogg::Vorbis::File(fileName, readProperties, propertiesStyle); + } + else if( mimetype->is( "audio/x-oggflac" ) ) + { + return new TagLib::Ogg::FLAC::File(fileName, readProperties, propertiesStyle); + } + else if( mimetype->is( "audio/x-flac" ) ) + { + return new TagLib::FLAC::File(fileName, readProperties, propertiesStyle); + } + else if( mimetype->is( "audio/x-musepack" ) ) + { + return new TagLib::MPC::File(fileName, readProperties, propertiesStyle); + } + else if( mimetype->is( "audio/x-musepack" ) + || mimetype->is( "audio/x-ape" ) + || mimetype->is( "application/x-ofr" ) ) + { + return new TagLib::MPC::File(fileName, readProperties, propertiesStyle); + } + +// debug() << "kmimetype filetype guessing failed for" << fileName << endl; + + return 0; +} + +void registerTaglibPlugins() +{ + //TagLib::FileRef::addFileTypeResolver(new MimeTypeFileTypeResolver); + TagLib::FileRef::addFileTypeResolver(new MP4FileTypeResolver); + TagLib::FileRef::addFileTypeResolver(new ASFFileTypeResolver); + TagLib::FileRef::addFileTypeResolver(new RealMediaFileTypeResolver); + TagLib::FileRef::addFileTypeResolver(new AudibleFileTypeResolver); + TagLib::FileRef::addFileTypeResolver(new AACFileTypeResolver); + TagLib::FileRef::addFileTypeResolver(new WavPackFileTypeResolver); + TagLib::FileRef::addFileTypeResolver(new SpeexFileTypeResolver); + TagLib::FileRef::addFileTypeResolver(new TTAFileTypeResolver); + TagLib::FileRef::addFileTypeResolver(new WavFileTypeResolver); + TagLib::FileRef::addFileTypeResolver(new MonkeysAudioFileTypeResolver); + TagLib::FileRef::addFileTypeResolver(new OptimFrogFileTypeResolver); +} diff --git a/src/metadata/tplugins.h b/src/metadata/tplugins.h new file mode 100755 index 0000000..1ef356f --- /dev/null +++ b/src/metadata/tplugins.h @@ -0,0 +1,27 @@ +/*************************************************************************** + copyright : (C) 2005 by Martin Aumueller + email : aumuell@reserv.at + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef METADATA_TPLUGIN_H +#define METADATA_TPLUGIN_H + +void registerTaglibPlugins(); + +#endif diff --git a/src/metadata/trueaudio/Makefile.am b/src/metadata/trueaudio/Makefile.am new file mode 100644 index 0000000..01af09f --- /dev/null +++ b/src/metadata/trueaudio/Makefile.am @@ -0,0 +1,16 @@ +SUBDIRS = + +INCLUDES = $(all_includes) $(taglib_includes) +METASOURCES = AUTO +libtagtrueaudio_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libtagtrueaudio.la + +libtagtrueaudio_la_SOURCES = \ + ttafile.cpp \ + ttaproperties.cpp \ + taglib_trueaudiofiletyperesolver.cpp + +noinst_HEADERS = ttafile.h \ + ttaproperties.h \ + taglib_trueaudiofiletyperesolver.h + diff --git a/src/metadata/trueaudio/combinedtag.h b/src/metadata/trueaudio/combinedtag.h new file mode 100644 index 0000000..7d530d2 --- /dev/null +++ b/src/metadata/trueaudio/combinedtag.h @@ -0,0 +1,171 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef DO_NOT_DOCUMENT // Tell Doxygen not to document this header + +#ifndef TAGLIB_COMBINEDTAG_H +#define TAGLIB_COMBINEDTAG_H + +//////////////////////////////////////////////////////////////////////////////// +// Note that this header is not installed. +//////////////////////////////////////////////////////////////////////////////// + +#include + +namespace TagLib { + + /*! + * A union of two TagLib::Tags. + */ + class CombinedTag : public TagLib::Tag + { + public: + CombinedTag(Tag *tag1 = 0, Tag *tag2 = 0) + : TagLib::Tag(), + tag1(tag1), tag2(tag2) {} + + virtual String title() const { + if(tag1 && !tag1->title().isEmpty()) + return tag1->title(); + + if(tag2) + return tag2->title(); + + return String::null; + } + + virtual String artist() const { + if(tag1 && !tag1->artist().isEmpty()) + return tag1->artist(); + + if(tag2) + return tag2->artist(); + + return String::null; + } + + virtual String album() const { + if(tag1 && !tag1->album().isEmpty()) + return tag1->album(); + + if(tag2) + return tag2->album(); + + return String::null; + } + + virtual String comment() const { + if(tag1 && !tag1->comment().isEmpty()) + return tag1->comment(); + + if(tag2) + return tag2->comment(); + + return String::null; + } + + virtual String genre() const { + if(tag1 && !tag1->genre().isEmpty()) + return tag1->genre(); + + if(tag2) + return tag2->genre(); + + return String::null; + } + + virtual uint year() const { + if(tag1 && tag1->year() > 0) + return tag1->year(); + + if(tag2) + return tag2->year(); + + return 0; + } + + virtual uint track() const { + if(tag1 && tag1->track() > 0) + return tag1->track(); + + if(tag2) + return tag2->track(); + + return 0; + } + + virtual void setTitle(const String &s) { + if(tag1) + tag1->setTitle(s); + if(tag2) + tag2->setTitle(s); + } + + virtual void setArtist(const String &s) { + if(tag1) + tag1->setArtist(s); + if(tag2) + tag2->setArtist(s); + } + + virtual void setAlbum(const String &s) { + if(tag1) + tag1->setAlbum(s); + if(tag2) + tag2->setAlbum(s); + } + + virtual void setComment(const String &s) { + if(tag1) + tag1->setComment(s); + if(tag2) + tag2->setComment(s); + } + + virtual void setGenre(const String &s) { + if(tag1) + tag1->setGenre(s); + if(tag2) + tag2->setGenre(s); + } + + virtual void setYear(uint i) { + if(tag1) + tag1->setYear(i); + if(tag2) + tag2->setYear(i); + } + + virtual void setTrack(uint i) { + if(tag1) + tag1->setTrack(i); + if(tag2) + tag2->setTrack(i); + } + + private: + Tag *tag1; + Tag *tag2; + }; +} + +#endif +#endif diff --git a/src/metadata/trueaudio/taglib_trueaudiofiletyperesolver.cpp b/src/metadata/trueaudio/taglib_trueaudiofiletyperesolver.cpp new file mode 100644 index 0000000..e84e501 --- /dev/null +++ b/src/metadata/trueaudio/taglib_trueaudiofiletyperesolver.cpp @@ -0,0 +1,44 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : aumuell@reserv.at + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "taglib_trueaudiofiletyperesolver.h" +#include "ttafile.h" + +#include + +TagLib::File *TTAFileTypeResolver::createFile(const char *fileName, + bool readProperties, + TagLib::AudioProperties::ReadStyle propertiesStyle) const +{ + const char *ext = strrchr(fileName, '.'); + if(ext && !strcasecmp(ext, ".tta")) + { + TagLib::TTA::File *f = new TagLib::TTA::File(fileName, readProperties, propertiesStyle); + if(f->isValid()) + return f; + else + { + delete f; + } + } + + return 0; +} diff --git a/src/metadata/trueaudio/taglib_trueaudiofiletyperesolver.h b/src/metadata/trueaudio/taglib_trueaudiofiletyperesolver.h new file mode 100644 index 0000000..e436e43 --- /dev/null +++ b/src/metadata/trueaudio/taglib_trueaudiofiletyperesolver.h @@ -0,0 +1,36 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : aumuell@reserv.at + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_TRUEAUDIOFILETYPERESOLVER_H +#define TAGLIB_TRUEAUDIOFILETYPERESOLVER_H + +#include +#include + + +class TTAFileTypeResolver : public TagLib::FileRef::FileTypeResolver +{ + TagLib::File *createFile(const char *fileName, + bool readAudioProperties, + TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; +}; + +#endif diff --git a/src/metadata/trueaudio/ttafile.cpp b/src/metadata/trueaudio/ttafile.cpp new file mode 100644 index 0000000..3a02e20 --- /dev/null +++ b/src/metadata/trueaudio/ttafile.cpp @@ -0,0 +1,307 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +#include +#if 0 +#include +#endif + +#include "ttafile.h" +#include "id3v1tag.h" +#include "id3v2tag.h" +#include "id3v2header.h" +#include "combinedtag.h" + +using namespace TagLib; + +class TTA::File::FilePrivate +{ +public: + FilePrivate(const ID3v2::FrameFactory *frameFactory = ID3v2::FrameFactory::instance()) : + ID3v2FrameFactory(frameFactory), + ID3v2Tag(0), + ID3v2Location(-1), + ID3v2OriginalSize(0), + ID3v1Tag(0), + ID3v1Location(-1), + tag(0), + properties(0), + scanned(false), + hasID3v1(false), + hasID3v2(false) {} + + ~FilePrivate() + { + if (tag != ID3v1Tag && tag != ID3v2Tag) delete tag; + delete ID3v1Tag; + delete ID3v2Tag; + delete properties; + } + + const ID3v2::FrameFactory *ID3v2FrameFactory; + ID3v2::Tag *ID3v2Tag; + long ID3v2Location; + uint ID3v2OriginalSize; + + ID3v1::Tag *ID3v1Tag; + long ID3v1Location; + + Tag *tag; + + Properties *properties; + bool scanned; + + // These indicate whether the file *on disk* has these tags, not if + // this data structure does. This is used in computing offsets. + + bool hasID3v1; + bool hasID3v2; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +TTA::File::File(const char *file, bool readProperties, + Properties::ReadStyle propertiesStyle) : TagLib::File(file) +{ + d = new FilePrivate; + if(isOpen()) + read(readProperties, propertiesStyle); +} + +TTA::File::File(const char *file, ID3v2::FrameFactory *frameFactory, + bool readProperties, Properties::ReadStyle propertiesStyle) : + TagLib::File(file) +{ + d = new FilePrivate(frameFactory); + if(isOpen()) + read(readProperties, propertiesStyle); +} + +TTA::File::~File() +{ + delete d; +} + +TagLib::Tag *TTA::File::tag() const +{ + return d->tag; +} + +TTA::Properties *TTA::File::audioProperties() const +{ + return d->properties; +} + +void TTA::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory) +{ + d->ID3v2FrameFactory = factory; +} + +bool TTA::File::save() +{ + if(readOnly()) { +#if 0 + debug("TTA::File::save() -- File is read only."); +#endif + return false; + } + + // Update ID3v2 tag + + if(d->ID3v2Tag) { + if(!d->hasID3v2) { + d->ID3v2Location = 0; + d->ID3v2OriginalSize = 0; + } + insert(d->ID3v2Tag->render(), d->ID3v2Location, d->ID3v2OriginalSize); + d->hasID3v2 = true; + } + else if(d->hasID3v2) { + removeBlock(d->ID3v2Location, d->ID3v2OriginalSize); + d->hasID3v2 = false; + } + + // Update ID3v1 tag + + if(d->ID3v1Tag) { + if(!d->hasID3v1) { + seek(0, End); + d->ID3v1Location = tell(); + } + else + seek(d->ID3v1Location); + writeBlock(d->ID3v1Tag->render()); + d->hasID3v1 = true; + } + else if(d->hasID3v1) { + removeBlock(d->ID3v1Location, 128); + d->hasID3v1 = false; + } + + return true; +} + +ID3v1::Tag *TTA::File::ID3v1Tag(bool create) +{ + if(!create || d->ID3v1Tag) + return d->ID3v1Tag; + + // no ID3v1 tag exists and we've been asked to create one + + d->ID3v1Tag = new ID3v1::Tag; + + if(d->ID3v2Tag) + d->tag = new CombinedTag(d->ID3v2Tag, d->ID3v1Tag); + else + d->tag = d->ID3v1Tag; + + return d->ID3v1Tag; +} + +ID3v2::Tag *TTA::File::ID3v2Tag(bool create) +{ + if(!create || d->ID3v2Tag) + return d->ID3v2Tag; + + // no ID3v2 tag exists and we've been asked to create one + + d->ID3v2Tag = new ID3v2::Tag; + + if(d->ID3v1Tag) + d->tag = new CombinedTag(d->ID3v2Tag, d->ID3v1Tag); + else + d->tag = d->ID3v2Tag; + + return d->ID3v2Tag; +} + +void TTA::File::remove(int tags) +{ + if(tags & ID3v1) { + delete d->ID3v1Tag; + d->ID3v1Tag = 0; + + if(d->ID3v2Tag) + d->tag = d->ID3v2Tag; + else + d->tag = d->ID3v2Tag = new ID3v2::Tag; + } + + if(tags & ID3v2) { + delete d->ID3v2Tag; + d->ID3v2Tag = 0; + + if(d->ID3v1Tag) + d->tag = d->ID3v1Tag; + else + d->tag = d->ID3v2Tag = new ID3v2::Tag; + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void TTA::File::read(bool readProperties, Properties::ReadStyle /* propertiesStyle */) +{ + // Look for an ID3v2 tag + + d->ID3v2Location = findID3v2(); + + if(d->ID3v2Location >= 0) { + + d->ID3v2Tag = new ID3v2::Tag(this, d->ID3v2Location, d->ID3v2FrameFactory); + + d->ID3v2OriginalSize = d->ID3v2Tag->header()->completeTagSize(); + + if(d->ID3v2Tag->header()->tagSize() <= 0) { + delete d->ID3v2Tag; + d->ID3v2Tag = 0; + } + else + d->hasID3v2 = true; + } + + // Look for an ID3v1 tag + + d->ID3v1Location = findID3v1(); + + if(d->ID3v1Location >= 0) { + d->ID3v1Tag = new ID3v1::Tag(this, d->ID3v1Location); + d->hasID3v1 = true; + } + + if(d->hasID3v1 && d->hasID3v2) + d->tag = new CombinedTag(d->ID3v2Tag, d->ID3v1Tag); + else { + if(d->hasID3v1) + d->tag = d->ID3v1Tag; + else { + if(d->hasID3v2) + d->tag = d->ID3v2Tag; + else + d->tag = d->ID3v2Tag = new ID3v2::Tag; + } + } + + // Look for TTA metadata + + if(readProperties) { + seek(d->ID3v2Location + d->ID3v2OriginalSize); + d->properties = new Properties(readBlock(TTA::HeaderSize), + length() - d->ID3v2OriginalSize); + } +} + +long TTA::File::findID3v1() +{ + if(!isValid()) + return -1; + + seek(-128, End); + long p = tell(); + + if(readBlock(3) == ID3v1::Tag::fileIdentifier()) + return p; + + return -1; +} + +long TTA::File::findID3v2() +{ + if(!isValid()) + return -1; + + seek(0); + + if(readBlock(3) == ID3v2::Header::fileIdentifier()) + return 0; + + return -1; +} diff --git a/src/metadata/trueaudio/ttafile.h b/src/metadata/trueaudio/ttafile.h new file mode 100644 index 0000000..2cb0785 --- /dev/null +++ b/src/metadata/trueaudio/ttafile.h @@ -0,0 +1,178 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_TTAFILE_H +#define TAGLIB_TTAFILE_H + +#include "tfile.h" + +#include "ttaproperties.h" + +namespace TagLib { + + class Tag; + + namespace ID3v2 { class Tag; class FrameFactory; } + namespace ID3v1 { class Tag; } + + //! An implementation of TTA metadata + + /*! + * This is implementation of TTA metadata. + * + * This supports ID3v1 and ID3v2 tags as well as reading stream + * properties from the file. + */ + + namespace TTA { + + //! An implementation of TagLib::File with TTA specific methods + + /*! + * This implements and provides an interface for TTA files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to TTA files. + */ + + class File : public TagLib::File + { + public: + /*! + * This set of flags is used for various operations and is suitable for + * being OR-ed together. + */ + enum TagTypes { + //! Empty set. Matches no tag types. + NoTags = 0x0000, + //! Matches ID3v1 tags. + ID3v1 = 0x0001, + //! Matches ID3v2 tags. + ID3v2 = 0x0002, + //! Matches all tag types. + AllTags = 0xffff + }; + + /*! + * Contructs an MPC file from \a file. If \a readProperties is true the + * file's audio properties will also be read using \a propertiesStyle. If + * false, \a propertiesStyle is ignored. + */ + File(const char *file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Contructs an MPC file from \a file. If \a readProperties is true the + * file's audio properties will also be read using \a propertiesStyle. If + * false, \a propertiesStyle is ignored. The frames will be created using + * \a frameFactory. + */ + File(const char *file, ID3v2::FrameFactory *frameFactory, + bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. This will be an APE tag, an ID3v1 tag + * or a combination of the two. + */ + virtual TagLib::Tag *tag() const; + + /*! + * Returns the MPC::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Set the ID3v2::FrameFactory to something other than the default. + * + * \see ID3v2FrameFactory + */ + void setID3v2FrameFactory(const ID3v2::FrameFactory *factory); + + /*! + * Saves the file. + */ + virtual bool save(); + + /*! + * Returns a pointer to the ID3v2 tag of the file. + * + * If \a create is false (the default) this will return a null pointer + * if there is no valid ID3v2 tag. If \a create is true it will create + * an ID3v1 tag if one does not exist. If there is already an APE tag, the + * new ID3v1 tag will be placed after it. + * + * \note The Tag is still owned by the TTA::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + ID3v1::Tag *ID3v1Tag(bool create = false); + + /*! + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this will return a null pointer + * if there is no valid ID3v1 tag. If \a create is true it will create + * an ID3v1 tag if one does not exist. If there is already an APE tag, the + * new ID3v1 tag will be placed after it. + * + * \note The Tag is still owned by the TTA::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + ID3v2::Tag *ID3v2Tag(bool create = false); + + /*! + * This will remove the tags that match the OR-ed together TagTypes from the + * file. By default it removes all tags. + * + * \note This will also invalidate pointers to the tags + * as their memory will be freed. + * \note In order to make the removal permanent save() still needs to be called + */ + void remove(int tags = AllTags); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + void scan(); + long findID3v1(); + long findID3v2(); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/src/metadata/trueaudio/ttaproperties.cpp b/src/metadata/trueaudio/ttaproperties.cpp new file mode 100644 index 0000000..c4f6a29 --- /dev/null +++ b/src/metadata/trueaudio/ttaproperties.cpp @@ -0,0 +1,134 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +#if 0 +#include +#endif +#include + +#include "ttaproperties.h" +#include "ttafile.h" + +using namespace TagLib; + +class TTA::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate(const ByteVector &d, long length, ReadStyle s) : + data(d), + streamLength(length), + style(s), + version(0), + length(0), + bitrate(0), + sampleRate(0), + channels(0), + bitsPerSample(0) {} + + ByteVector data; + long streamLength; + ReadStyle style; + int version; + int length; + int bitrate; + int sampleRate; + int channels; + int bitsPerSample; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +TTA::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) : AudioProperties(style) +{ + d = new PropertiesPrivate(data, streamLength, style); + read(); +} + +TTA::Properties::~Properties() +{ + delete d; +} + +int TTA::Properties::length() const +{ + return d->length; +} + +int TTA::Properties::bitrate() const +{ + return d->bitrate; +} + +int TTA::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int TTA::Properties::bitsPerSample() const +{ + return d->bitsPerSample; +} + +int TTA::Properties::channels() const +{ + return d->channels; +} + +int TTA::Properties::ttaVersion() const +{ + return d->version; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void TTA::Properties::read() +{ + if(!d->data.startsWith("TTA")) + return; + + int pos = 3; + + d->version = d->data[pos] - '0'; + pos += 1 + 2; + + d->channels = d->data.mid(pos, 2).toShort(false); + pos += 2; + + d->bitsPerSample = d->data.mid(pos, 2).toShort(false); + pos += 2; + + d->sampleRate = d->data.mid(pos, 4).toUInt(false); + pos += 4; + + unsigned long samples = d->data.mid(pos, 4).toUInt(false); + d->length = samples / d->sampleRate; + + d->bitrate = d->length > 0 ? ((d->streamLength * 8L) / d->length) / 1000 : 0; +} diff --git a/src/metadata/trueaudio/ttaproperties.h b/src/metadata/trueaudio/ttaproperties.h new file mode 100644 index 0000000..e694e3d --- /dev/null +++ b/src/metadata/trueaudio/ttaproperties.h @@ -0,0 +1,86 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_TTAPROPERTIES_H +#define TAGLIB_TTAPROPERTIES_H + +#include "audioproperties.h" + +namespace TagLib { + + namespace TTA { + + class File; + + static const uint HeaderSize = 18; + + //! An implementation of audio property reading for TTA + + /*! + * This reads the data from an TTA stream found in the AudioProperties + * API. + */ + + class Properties : public AudioProperties + { + public: + /*! + * Create an instance of TTA::Properties with the data read from the + * ByteVector \a data. + */ + Properties(const ByteVector &data, long streamLength, ReadStyle style = Average); + + /*! + * Destroys this TTA::Properties instance. + */ + virtual ~Properties(); + + // Reimplementations. + + virtual int length() const; + virtual int bitrate() const; + virtual int sampleRate() const; + virtual int channels() const; + + /*! + * Returns number of bits per sample. + */ + int bitsPerSample() const; + + /*! + * Returns the major version number. + */ + int ttaVersion() const; + + private: + void read(); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/src/metadata/wav/Makefile.am b/src/metadata/wav/Makefile.am new file mode 100644 index 0000000..add569f --- /dev/null +++ b/src/metadata/wav/Makefile.am @@ -0,0 +1,15 @@ +SUBDIRS = + +INCLUDES = $(all_includes) $(taglib_includes) +METASOURCES = AUTO +libtagwav_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libtagwav.la + +libtagwav_la_SOURCES = wavproperties.cpp \ + wavfile.cpp \ + wavfiletyperesolver.cpp + +noinst_HEADERS = wavproperties.h \ + wavfile.h \ + wavfiletyperesolver.h + diff --git a/src/metadata/wav/wavfile.cpp b/src/metadata/wav/wavfile.cpp new file mode 100644 index 0000000..303c5b2 --- /dev/null +++ b/src/metadata/wav/wavfile.cpp @@ -0,0 +1,115 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : aumuell@reserv.at + + copyright : (C) 2005 by Andy Leadbetter + email : andrew.leadbetter@gmail.com + (original mp4 implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include + +#include "wavfile.h" + +#include +#include +#include + +namespace TagLib { +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Wav::File::File(const char *file, + bool readProperties, + Properties::ReadStyle propertiesStyle, + FILE *fp) + : TagLib::File(file) + , wavtag( NULL ) + , properties( NULL ) +{ + + // debug ("Wav::File: create new file object."); + //debug ( file ); + + /** + * Create the Wav file. + */ + + if(fp) + wavfile = fp; + else + wavfile = fopen(file, "rb"); + + if( isOpen() ) + { + read(readProperties, propertiesStyle ); + } +} + +Wav::File::~File() +{ + if(wavfile) + fclose(wavfile); + delete properties; +} + +TagLib::Tag *Wav::File::tag() const +{ + return NULL; +} + +TagLib::Tag *Wav::File::getWavTag() const +{ + return NULL; +} + +Wav::Properties *Wav::File::audioProperties() const +{ + return properties; +} + +bool Wav::File::save() +{ + return false; +} + +bool Wav::File::isOpen() +{ + return wavfile != NULL; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void Wav::File::read(bool readProperties, Properties::ReadStyle propertiesStyle) +{ + properties = new Wav::Properties(propertiesStyle); + + if (wavfile != NULL) { + if(readProperties) + { + // Parse bitrate etc. + properties->readWavProperties( wavfile ); + } + } +} + +} diff --git a/src/metadata/wav/wavfile.h b/src/metadata/wav/wavfile.h new file mode 100644 index 0000000..e47fdfb --- /dev/null +++ b/src/metadata/wav/wavfile.h @@ -0,0 +1,92 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : aumuell@reserv.at + + copyright : (C) 2005 by Andy Leadbetter + email : andrew.leadbetter@gmail.com + (original mp4 implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_WAVFILE_H +#define TAGLIB_WAVFILE_H + +#include +#include "wavproperties.h" + +namespace TagLib { + + namespace Wav { + + class Tag; + + class File : public TagLib::File + { + public: + /*! + * Contructs a Wav file from \a file. If \a readProperties is true the + * file's audio properties will also be read using \a propertiesStyle. If + * false, \a propertiesStyle is ignored. + */ + File(const char *file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average, + FILE *fp=NULL); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + + virtual TagLib::Tag *tag() const; + + /*! + * Returns the Wav::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Wav::Properties *audioProperties() const; + + /*! + * Save the file. + * This is the same as calling save(AllTags); + * + * \note As of now, saving Wav tags is not supported. + */ + virtual bool save(); + + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + + TagLib::Tag *getWavTag() const; + + bool isWavFile() const; + + protected: + File(const File &); + File &operator=(const File &); + bool isOpen(); + + + TagLib::Tag *wavtag; + Wav::Properties *properties; + + FILE *wavfile; + }; + } +} + +#endif diff --git a/src/metadata/wav/wavfiletyperesolver.cpp b/src/metadata/wav/wavfiletyperesolver.cpp new file mode 100644 index 0000000..830742f --- /dev/null +++ b/src/metadata/wav/wavfiletyperesolver.cpp @@ -0,0 +1,44 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : aumuell@reserv.at + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include + +#include "wavfiletyperesolver.h" +#include "wavfile.h" + +#include + +TagLib::File *WavFileTypeResolver::createFile(const char *fileName, + bool readProperties, + TagLib::AudioProperties::ReadStyle propertiesStyle) const +{ + const char *ext = strrchr(fileName, '.'); + if(ext && !strcasecmp(ext, ".wav")) + { + FILE *fp = fopen(fileName, "rb"); + if(!fp) + return 0; + + return new TagLib::Wav::File(fileName, readProperties, propertiesStyle, fp); + } + + return 0; +} diff --git a/src/metadata/wav/wavfiletyperesolver.h b/src/metadata/wav/wavfiletyperesolver.h new file mode 100644 index 0000000..de818c9 --- /dev/null +++ b/src/metadata/wav/wavfiletyperesolver.h @@ -0,0 +1,36 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : aumuell@reserv.at + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_WAVFILETYPERESOLVER_H +#define TAGLIB_WAVFILETYPERESOLVER_H + +#include +#include + + +class WavFileTypeResolver : public TagLib::FileRef::FileTypeResolver +{ + TagLib::File *createFile(const char *fileName, + bool readAudioProperties, + TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; +}; + +#endif diff --git a/src/metadata/wav/wavproperties.cpp b/src/metadata/wav/wavproperties.cpp new file mode 100644 index 0000000..20ba1ab --- /dev/null +++ b/src/metadata/wav/wavproperties.cpp @@ -0,0 +1,108 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : aumuell@reserv.at + + copyright : (C) 2005 by Andy Leadbetter + email : andrew.leadbetter@gmail.com + (original mp4 implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include + +#include "wavproperties.h" + +#include + +#include "wavfile.h" + +#include // ntohl + +using namespace TagLib; + +struct WavHeader +{ + uint32_t riff_id; + uint32_t riff_size; + uint32_t wave_id; + uint32_t format_id; + uint32_t format_size; + uint16_t format_tag; + uint16_t num_channels; + uint32_t num_samples_per_sec; + uint32_t num_avg_bytes_per_sec; + uint16_t num_block_align; + uint16_t bits_per_sample; + uint32_t data_id; + uint32_t num_data_bytes; +}; + + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Wav::Properties::Properties(Properties::ReadStyle style) : AudioProperties(style) +{ + m_length = 0; + m_bitrate = 0; + m_sampleRate = 0; + m_channels = 0; +} + +Wav::Properties::~Properties() +{ +} + +int Wav::Properties::length() const +{ + return m_length; +} + +int Wav::Properties::bitrate() const +{ + return m_bitrate; +} + +int Wav::Properties::sampleRate() const +{ + return m_sampleRate; +} + +int Wav::Properties::channels() const +{ + return m_channels; +} + +#define swap16(x) ((((x)&0xff00)>>8) | (((x)&0x00ff)<<8)) +#define swap32(x) ((swap16((x)&0x0000ffff)<<16) | swap16(((x)&0xffff0000)>>16)) + +void Wav::Properties::readWavProperties( FILE *fp ) +{ + fseek(fp, 0, SEEK_SET ); + WavHeader header; + if( fread(&header, sizeof(header), 1, fp) != 1 ) + { + return; + } + + m_channels = ntohs(swap16(header.num_channels)); + m_sampleRate = ntohl(swap32(header.num_samples_per_sec)); + m_bitrate = ntohl(swap32(header.num_avg_bytes_per_sec)) * 8 / 1000; + m_length = ntohl(swap32(header.num_data_bytes))/ntohl(swap32(header.num_avg_bytes_per_sec)); +} diff --git a/src/metadata/wav/wavproperties.h b/src/metadata/wav/wavproperties.h new file mode 100644 index 0000000..a02e734 --- /dev/null +++ b/src/metadata/wav/wavproperties.h @@ -0,0 +1,85 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : aumuell@reserv.at + + copyright : (C) 2005 by Andy Leadbetter + email : andrew.leadbetter@gmail.com + (original mp4 implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_WAVPROPERTIES_H +#define TAGLIB_WAVPROPERTIES_H + +#include + +#include +#include + +namespace TagLib { + + namespace Wav { + + class File; + + /*! + * This reads the data from a Wav stream to support the + * AudioProperties API. + */ + + class Properties : public AudioProperties + { + public: + /*! + * Initialize this structure + */ + Properties(Properties::ReadStyle style); + + /*! + * Destroys this Wav Properties instance. + */ + virtual ~Properties(); + + // Reimplementations. + + virtual int length() const; + virtual int bitrate() const; + virtual int sampleRate() const; + virtual int channels() const; + + void readWavProperties(FILE *file); + + + private: + void readAudioTrackProperties(FILE *file); + friend class Wav::File; + + int m_length; + int m_bitrate; + int m_sampleRate; + int m_channels; + + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(); + }; + } +} + +#endif diff --git a/src/metadata/wavpack/Makefile.am b/src/metadata/wavpack/Makefile.am new file mode 100644 index 0000000..93a98c6 --- /dev/null +++ b/src/metadata/wavpack/Makefile.am @@ -0,0 +1,16 @@ +SUBDIRS = + +INCLUDES = $(all_includes) $(taglib_includes) +METASOURCES = AUTO +libtagwavpack_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libtagwavpack.la + +libtagwavpack_la_SOURCES = \ + wvfile.cpp \ + wvproperties.cpp \ + taglib_wavpackfiletyperesolver.cpp + +noinst_HEADERS = wvfile.h \ + wvproperties.h \ + taglib_wavpackfiletyperesolver.h + diff --git a/src/metadata/wavpack/combinedtag.h b/src/metadata/wavpack/combinedtag.h new file mode 100644 index 0000000..7d530d2 --- /dev/null +++ b/src/metadata/wavpack/combinedtag.h @@ -0,0 +1,171 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef DO_NOT_DOCUMENT // Tell Doxygen not to document this header + +#ifndef TAGLIB_COMBINEDTAG_H +#define TAGLIB_COMBINEDTAG_H + +//////////////////////////////////////////////////////////////////////////////// +// Note that this header is not installed. +//////////////////////////////////////////////////////////////////////////////// + +#include + +namespace TagLib { + + /*! + * A union of two TagLib::Tags. + */ + class CombinedTag : public TagLib::Tag + { + public: + CombinedTag(Tag *tag1 = 0, Tag *tag2 = 0) + : TagLib::Tag(), + tag1(tag1), tag2(tag2) {} + + virtual String title() const { + if(tag1 && !tag1->title().isEmpty()) + return tag1->title(); + + if(tag2) + return tag2->title(); + + return String::null; + } + + virtual String artist() const { + if(tag1 && !tag1->artist().isEmpty()) + return tag1->artist(); + + if(tag2) + return tag2->artist(); + + return String::null; + } + + virtual String album() const { + if(tag1 && !tag1->album().isEmpty()) + return tag1->album(); + + if(tag2) + return tag2->album(); + + return String::null; + } + + virtual String comment() const { + if(tag1 && !tag1->comment().isEmpty()) + return tag1->comment(); + + if(tag2) + return tag2->comment(); + + return String::null; + } + + virtual String genre() const { + if(tag1 && !tag1->genre().isEmpty()) + return tag1->genre(); + + if(tag2) + return tag2->genre(); + + return String::null; + } + + virtual uint year() const { + if(tag1 && tag1->year() > 0) + return tag1->year(); + + if(tag2) + return tag2->year(); + + return 0; + } + + virtual uint track() const { + if(tag1 && tag1->track() > 0) + return tag1->track(); + + if(tag2) + return tag2->track(); + + return 0; + } + + virtual void setTitle(const String &s) { + if(tag1) + tag1->setTitle(s); + if(tag2) + tag2->setTitle(s); + } + + virtual void setArtist(const String &s) { + if(tag1) + tag1->setArtist(s); + if(tag2) + tag2->setArtist(s); + } + + virtual void setAlbum(const String &s) { + if(tag1) + tag1->setAlbum(s); + if(tag2) + tag2->setAlbum(s); + } + + virtual void setComment(const String &s) { + if(tag1) + tag1->setComment(s); + if(tag2) + tag2->setComment(s); + } + + virtual void setGenre(const String &s) { + if(tag1) + tag1->setGenre(s); + if(tag2) + tag2->setGenre(s); + } + + virtual void setYear(uint i) { + if(tag1) + tag1->setYear(i); + if(tag2) + tag2->setYear(i); + } + + virtual void setTrack(uint i) { + if(tag1) + tag1->setTrack(i); + if(tag2) + tag2->setTrack(i); + } + + private: + Tag *tag1; + Tag *tag2; + }; +} + +#endif +#endif diff --git a/src/metadata/wavpack/taglib_wavpackfiletyperesolver.cpp b/src/metadata/wavpack/taglib_wavpackfiletyperesolver.cpp new file mode 100644 index 0000000..fe289a2 --- /dev/null +++ b/src/metadata/wavpack/taglib_wavpackfiletyperesolver.cpp @@ -0,0 +1,44 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : aumuell@reserv.at + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "taglib_wavpackfiletyperesolver.h" +#include "wvfile.h" + +#include + +TagLib::File *WavPackFileTypeResolver::createFile(const char *fileName, + bool readProperties, + TagLib::AudioProperties::ReadStyle propertiesStyle) const +{ + const char *ext = strrchr(fileName, '.'); + if(ext && !strcasecmp(ext, ".wv")) + { + TagLib::WavPack::File *f = new TagLib::WavPack::File(fileName, readProperties, propertiesStyle); + if(f->isValid()) + return f; + else + { + delete f; + } + } + + return 0; +} diff --git a/src/metadata/wavpack/taglib_wavpackfiletyperesolver.h b/src/metadata/wavpack/taglib_wavpackfiletyperesolver.h new file mode 100644 index 0000000..b9d4500 --- /dev/null +++ b/src/metadata/wavpack/taglib_wavpackfiletyperesolver.h @@ -0,0 +1,36 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : aumuell@reserv.at + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_WAVPACKFILETYPERESOLVER_H +#define TAGLIB_WAVPACKFILETYPERESOLVER_H + +#include +#include + + +class WavPackFileTypeResolver : public TagLib::FileRef::FileTypeResolver +{ + TagLib::File *createFile(const char *fileName, + bool readAudioProperties, + TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; +}; + +#endif diff --git a/src/metadata/wavpack/wvfile.cpp b/src/metadata/wavpack/wvfile.cpp new file mode 100644 index 0000000..3890bc9 --- /dev/null +++ b/src/metadata/wavpack/wvfile.cpp @@ -0,0 +1,311 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +#include +#if 0 +#include +#endif + +#include "wvfile.h" +#include "id3v1tag.h" +#include "id3v2header.h" +#include "apetag.h" +#include "apefooter.h" +#include "combinedtag.h" + +using namespace TagLib; + +class WavPack::File::FilePrivate +{ +public: + FilePrivate() : + APETag(0), + APELocation(-1), + APESize(0), + ID3v1Tag(0), + ID3v1Location(-1), + tag(0), + properties(0), + scanned(false), + hasAPE(false), + hasID3v1(false) {} + + ~FilePrivate() + { + if (tag != ID3v1Tag && tag != APETag) delete tag; + delete ID3v1Tag; + delete APETag; + delete properties; + } + + APE::Tag *APETag; + long APELocation; + uint APESize; + + ID3v1::Tag *ID3v1Tag; + long ID3v1Location; + + Tag *tag; + + Properties *properties; + bool scanned; + + // These indicate whether the file *on disk* has these tags, not if + // this data structure does. This is used in computing offsets. + + bool hasAPE; + bool hasID3v1; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +WavPack::File::File(const char *file, bool readProperties, + Properties::ReadStyle propertiesStyle) : TagLib::File(file) +{ + d = new FilePrivate; + read(readProperties, propertiesStyle); +} + +WavPack::File::~File() +{ + delete d; +} + +TagLib::Tag *WavPack::File::tag() const +{ + return d->tag; +} + +WavPack::Properties *WavPack::File::audioProperties() const +{ + return d->properties; +} + +bool WavPack::File::save() +{ + if(readOnly()) { +#if 0 + debug("WavPack::File::save() -- File is read only."); +#endif + return false; + } + + // Update ID3v1 tag + + if(d->ID3v1Tag) { + if(d->hasID3v1) { + seek(d->ID3v1Location); + writeBlock(d->ID3v1Tag->render()); + } + else { + seek(0, End); + d->ID3v1Location = tell(); + writeBlock(d->ID3v1Tag->render()); + d->hasID3v1 = true; + } + } else + if(d->hasID3v1) { + removeBlock(d->ID3v1Location, 128); + d->hasID3v1 = false; + if(d->hasAPE) { + if(d->APELocation > d->ID3v1Location) + d->APELocation -= 128; + } + } + + // Update APE tag + + if(d->APETag) { + if(d->hasAPE) + insert(d->APETag->render(), d->APELocation, d->APESize); + else { + if(d->hasID3v1) { + insert(d->APETag->render(), d->ID3v1Location, 0); + d->APESize = d->APETag->footer()->completeTagSize(); + d->hasAPE = true; + d->APELocation = d->ID3v1Location; + d->ID3v1Location += d->APESize; + } + else { + seek(0, End); + d->APELocation = tell(); + writeBlock(d->APETag->render()); + d->APESize = d->APETag->footer()->completeTagSize(); + d->hasAPE = true; + } + } + } + else + if(d->hasAPE) { + removeBlock(d->APELocation, d->APESize); + d->hasAPE = false; + if(d->hasID3v1) { + if (d->ID3v1Location > d->APELocation) + d->ID3v1Location -= d->APESize; + } + } + + return true; +} + +ID3v1::Tag *WavPack::File::ID3v1Tag(bool create) +{ + if(!create || d->ID3v1Tag) + return d->ID3v1Tag; + + // no ID3v1 tag exists and we've been asked to create one + + d->ID3v1Tag = new ID3v1::Tag; + + if(d->APETag) + d->tag = new CombinedTag(d->APETag, d->ID3v1Tag); + else + d->tag = d->ID3v1Tag; + + return d->ID3v1Tag; +} + +APE::Tag *WavPack::File::APETag(bool create) +{ + if(!create || d->APETag) + return d->APETag; + + // no APE tag exists and we've been asked to create one + + d->APETag = new APE::Tag; + + if(d->ID3v1Tag) + d->tag = new CombinedTag(d->APETag, d->ID3v1Tag); + else + d->tag = d->APETag; + + return d->APETag; +} + +void WavPack::File::remove(int tags) +{ + if(tags & ID3v1) { + delete d->ID3v1Tag; + d->ID3v1Tag = 0; + + if(d->APETag) + d->tag = d->APETag; + else + d->tag = d->APETag = new APE::Tag; + } + + if(tags & APE) { + delete d->APETag; + d->APETag = 0; + + if(d->ID3v1Tag) + d->tag = d->ID3v1Tag; + else + d->tag = d->APETag = new APE::Tag; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void WavPack::File::read(bool readProperties, Properties::ReadStyle /* propertiesStyle */) +{ + // Look for an ID3v1 tag + + d->ID3v1Location = findID3v1(); + + if(d->ID3v1Location >= 0) { + d->ID3v1Tag = new ID3v1::Tag(this, d->ID3v1Location); + d->hasID3v1 = true; + } + + // Look for an APE tag + + d->APELocation = findAPE(); + + if(d->APELocation >= 0) { + d->APETag = new APE::Tag(this, d->APELocation); + d->APESize = d->APETag->footer()->completeTagSize(); + d->APELocation = d->APELocation + d->APETag->footer()->size() - d->APESize; + d->hasAPE = true; + } + + if(d->hasID3v1 && d->hasAPE) + d->tag = new CombinedTag(d->APETag, d->ID3v1Tag); + else { + if(d->hasID3v1) + d->tag = d->ID3v1Tag; + else { + if(d->hasAPE) + d->tag = d->APETag; + else + d->tag = d->APETag = new APE::Tag; + } + } + + // Look for WavPack audio properties + + if(readProperties) { + seek(0); + d->properties = new Properties(readBlock(WavPack::HeaderSize), + length() - d->APESize); + } +} + +long WavPack::File::findAPE() +{ + if(!isValid()) + return -1; + + if(d->hasID3v1) + seek(-160, End); + else + seek(-32, End); + + long p = tell(); + + if(readBlock(8) == APE::Tag::fileIdentifier()) + return p; + + return -1; +} + +long WavPack::File::findID3v1() +{ + if(!isValid()) + return -1; + + seek(-128, End); + long p = tell(); + + if(readBlock(3) == ID3v1::Tag::fileIdentifier()) + return p; + + return -1; +} diff --git a/src/metadata/wavpack/wvfile.h b/src/metadata/wavpack/wvfile.h new file mode 100644 index 0000000..6c57f6d --- /dev/null +++ b/src/metadata/wavpack/wvfile.h @@ -0,0 +1,160 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_WVFILE_H +#define TAGLIB_WVFILE_H + +#include "tfile.h" + +#include "wvproperties.h" + +namespace TagLib { + + class Tag; + + namespace ID3v1 { class Tag; } + namespace APE { class Tag; } + + //! An implementation of WavPack metadata + + /*! + * This is implementation of WavPack metadata. + * + * This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream + * properties from the file. + */ + + namespace WavPack { + + //! An implementation of TagLib::File with WavPack specific methods + + /*! + * This implements and provides an interface for WavPack files to the + * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing + * the abstract TagLib::File API as well as providing some additional + * information specific to WavPack files. + */ + + class File : public TagLib::File + { + public: + /*! + * This set of flags is used for various operations and is suitable for + * being OR-ed together. + */ + enum TagTypes { + //! Empty set. Matches no tag types. + NoTags = 0x0000, + //! Matches ID3v1 tags. + ID3v1 = 0x0001, + //! Matches APE tags. + APE = 0x0002, + //! Matches all tag types. + AllTags = 0xffff + }; + + /*! + * Contructs an WavPack file from \a file. If \a readProperties is true the + * file's audio properties will also be read using \a propertiesStyle. If + * false, \a propertiesStyle is ignored. + */ + File(const char *file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the Tag for this file. This will be an APE tag, an ID3v1 tag + * or a combination of the two. + */ + virtual TagLib::Tag *tag() const; + + /*! + * Returns the MPC::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Saves the file. + */ + virtual bool save(); + + /*! + * Returns a pointer to the ID3v1 tag of the file. + * + * If \a create is false (the default) this will return a null pointer + * if there is no valid ID3v1 tag. If \a create is true it will create + * an ID3v1 tag if one does not exist. If there is already an APE tag, the + * new ID3v1 tag will be placed after it. + * + * \note The Tag is still owned by the APE::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + ID3v1::Tag *ID3v1Tag(bool create = false); + + /*! + * Returns a pointer to the APE tag of the file. + * + * If \a create is false (the default) this will return a null pointer + * if there is no valid APE tag. If \a create is true it will create + * a APE tag if one does not exist. + * + * \note The Tag is still owned by the APE::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + APE::Tag *APETag(bool create = false); + + /*! + * This will remove the tags that match the OR-ed together TagTypes from the + * file. By default it removes all tags. + * + * \note This will also invalidate pointers to the tags + * as their memory will be freed. + * \note In order to make the removal permanent save() still needs to be called + */ + void remove(int tags = AllTags); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + void scan(); + long findID3v1(); + long findAPE(); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/src/metadata/wavpack/wvproperties.cpp b/src/metadata/wavpack/wvproperties.cpp new file mode 100644 index 0000000..376824d --- /dev/null +++ b/src/metadata/wavpack/wvproperties.cpp @@ -0,0 +1,141 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include +#if 0 +#include +#endif +#include + +#include "wvproperties.h" +#include "wvfile.h" + +using namespace TagLib; + +class WavPack::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate(const ByteVector &d, long length, ReadStyle s) : + data(d), + streamLength(length), + style(s), + length(0), + bitrate(0), + sampleRate(0), + channels(0), + version(0), + bitsPerSample(0) {} + + ByteVector data; + long streamLength; + ReadStyle style; + int length; + int bitrate; + int sampleRate; + int channels; + int version; + int bitsPerSample; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +WavPack::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) : AudioProperties(style) +{ + d = new PropertiesPrivate(data, streamLength, style); + read(); +} + +WavPack::Properties::~Properties() +{ + delete d; +} + +int WavPack::Properties::length() const +{ + return d->length; +} + +int WavPack::Properties::bitrate() const +{ + return d->bitrate; +} + +int WavPack::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int WavPack::Properties::channels() const +{ + return d->channels; +} + +int WavPack::Properties::version() const +{ + return d->version; +} + +int WavPack::Properties::bitsPerSample() const +{ + return d->bitsPerSample; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +static const unsigned int sample_rates[] = { 6000, 8000, 9600, 11025, 12000, + 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000, 192000 }; + +#define BYTES_STORED 3 +#define MONO_FLAG 4 + +#define SHIFT_LSB 13 +#define SHIFT_MASK (0x1fL << SHIFT_LSB) + +#define SRATE_LSB 23 +#define SRATE_MASK (0xfL << SRATE_LSB) + +void WavPack::Properties::read() +{ + if(!d->data.startsWith("wvpk")) + return; + + d->version = d->data.mid(8, 2).toShort(false); + + unsigned int flags = d->data.mid(24, 4).toUInt(false); + d->bitsPerSample = ((flags & BYTES_STORED) + 1) * 8 - + ((flags & SHIFT_MASK) >> SHIFT_LSB); + d->sampleRate = sample_rates[(flags & SRATE_MASK) >> SRATE_LSB]; + d->channels = (flags & MONO_FLAG) ? 1 : 2; + + unsigned int samples = d->data.mid(12, 4).toUInt(false); + d->length = d->sampleRate > 0 ? (samples + (d->sampleRate / 2)) / d->sampleRate : 0; + + d->bitrate = d->length > 0 ? ((d->streamLength * 8L) / d->length) / 1000 : 0; +} + diff --git a/src/metadata/wavpack/wvproperties.h b/src/metadata/wavpack/wvproperties.h new file mode 100644 index 0000000..b615adf --- /dev/null +++ b/src/metadata/wavpack/wvproperties.h @@ -0,0 +1,86 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : lalinsky@gmail.com + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : kde@carewolf.org + (original MPC implementation) + ***************************************************************************/ + +/*************************************************************************** + * This library is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License version * + * 2.1 as published by the Free Software Foundation. * + * * + * This library is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_WVPROPERTIES_H +#define TAGLIB_WVPROPERTIES_H + +#include "audioproperties.h" + +namespace TagLib { + + namespace WavPack { + + class File; + + static const uint HeaderSize = 32; + + //! An implementation of audio property reading for WavPack + + /*! + * This reads the data from an WavPack stream found in the AudioProperties + * API. + */ + + class Properties : public AudioProperties + { + public: + /*! + * Create an instance of WavPack::Properties with the data read from the + * ByteVector \a data. + */ + Properties(const ByteVector &data, long streamLength, ReadStyle style = Average); + + /*! + * Destroys this WavPack::Properties instance. + */ + virtual ~Properties(); + + // Reimplementations. + + virtual int length() const; + virtual int bitrate() const; + virtual int sampleRate() const; + virtual int channels() const; + + /*! + * Returns number of bits per sample. + */ + int bitsPerSample() const; + + /*! + * Returns WavPack version. + */ + int version() const; + + private: + void read(); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/src/options.cpp b/src/options.cpp new file mode 100755 index 0000000..fc1a5a8 --- /dev/null +++ b/src/options.cpp @@ -0,0 +1,273 @@ + +#include "options.h" +#include "optionssimple.h" +#include "optionsdetailed.h" +#include "config.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +// FIXME prevent converting wav files to wav + +Options::Options( Config* _config, const QString &text, QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + config = _config; + connect( config, SIGNAL(configChanged()), + this, SLOT(configChanged()) + ); + + QGridLayout *gridLayout = new QGridLayout( this, 1, 1 ); + + tab = new KTabWidget( this, "tab" ); + + optionsDetailed = new OptionsDetailed( config, this, "optionsDetailed" ); + optionsSimple = new OptionsSimple( config, optionsDetailed, text, this, "optionsSimple" ); + + tab->addTab( optionsSimple, i18n("Simple") ); + connect( optionsSimple, SIGNAL(optionsChanged()), + this, SLOT(somethingChanged()) + ); + + tab->addTab( optionsDetailed, i18n("Detailed") ); + connect( optionsDetailed, SIGNAL(optionsChanged()), + this, SLOT(somethingChanged()) + ); + +// connect( optionsSimple, SIGNAL(setFormat(const QString&)), +// optionsDetailed, SLOT(setFormat(const QString&)) +// ); +// connect( optionsSimple, SIGNAL(setQualityMode(const QString&)), +// optionsDetailed, SLOT(setQualityMode(const QString&)) +// ); +// connect( optionsSimple, SIGNAL(setQuality(int)), +// optionsDetailed, SLOT(setQuality(int)) +// ); +// connect( optionsSimple, SIGNAL(setBitrateMode(const QString&)), +// optionsDetailed, SLOT(setBitrateMode(const QString&)) +// ); +// connect( optionsSimple, SIGNAL(setBitrateRangeEnabled(bool)), +// optionsDetailed, SLOT(setBitrateRangeEnabled(bool)) +// ); +// connect( optionsSimple, SIGNAL(setMinBitrate(int)), +// optionsDetailed, SLOT(setMinBitrate(int)) +// ); +// connect( optionsSimple, SIGNAL(setMaxBitrate(int)), +// optionsDetailed, SLOT(setMaxBitrate(int)) +// ); +// connect( optionsSimple, SIGNAL(setSamplingrateEnabled(bool)), +// optionsDetailed, SLOT(setSamplingrateEnabled(bool)) +// ); +// connect( optionsSimple, SIGNAL(setSamplingrate(int)), +// optionsDetailed, SLOT(setSamplingrate(int)) +// ); +// connect( optionsSimple, SIGNAL(setSamplingrate(const QString&)), +// optionsDetailed, SLOT(setSamplingrate(const QString&)) +// ); +// connect( optionsSimple, SIGNAL(setChannelsEnabled(bool)), +// optionsDetailed, SLOT(setChannelsEnabled(bool)) +// ); +// connect( optionsSimple, SIGNAL(setChannels(const QString&)), +// optionsDetailed, SLOT(setChannels(const QString&)) +// ); +// connect( optionsSimple, SIGNAL(setReplayGainEnabled(bool)), +// optionsDetailed, SLOT(setReplayGainEnabled(bool)) +// ); +// connect( optionsSimple, SIGNAL(setOutputDirectoryMode(OutputDirectory::Mode)), +// optionsDetailed, SLOT(setOutputDirectoryMode(OutputDirectory::Mode)) +// ); +// connect( optionsSimple, SIGNAL(setOutputDirectoryPath(const QString&)), +// optionsDetailed, SLOT(setOutputDirectoryPath(const QString&)) +// ); +// connect( optionsSimple, SIGNAL(setOptions(const ConversionOptions&)), +// optionsDetailed, SLOT(setCurrentOptions(const ConversionOptions&)) +// ); +// connect( optionsSimple, SIGNAL(setUserOptions(const QString&)), +// optionsDetailed, SLOT(setUserOptions(const QString&)) +// ); + + if( config->data.general.startTab == 0 ) tab->setCurrentPage( config->data.general.lastTab ); + else tab->setCurrentPage( config->data.general.startTab - 1 ); + gridLayout->addWidget( tab, 0, 0 ); + connect( tab, SIGNAL( currentChanged(QWidget*) ), + this, SLOT( tabChanged(QWidget*) ) + ); + + // draw the toggle button + QVBoxLayout *optionsTopBox = new QVBoxLayout( -1, "optionsTopBox" ); + gridLayout->addLayout( optionsTopBox, 0, 0 ); + + QHBoxLayout *optionsBox = new QHBoxLayout( 6, "optionsBox" ); + optionsTopBox->addLayout( optionsBox ); + optionsTopBox->addStretch(); + + optionsBox->addStretch(); + +// pPluginsNotify = new KPushButton( "", this, "pPluginsNotify"); +// pPluginsNotify->setPixmap( KGlobal::iconLoader()->loadIcon("connect_creating",KIcon::Toolbar) ); +// QToolTip::add( pPluginsNotify, i18n("There are new plugin updates available.\nClick on this button in order to open the configuration dialog.") ); +// pPluginsNotify->hide(); +// pPluginsNotify->setPaletteBackgroundColor( QColor(255,220,247) ); +// optionsBox->addWidget( pPluginsNotify ); +// connect( pPluginsNotify, SIGNAL(clicked()), +// this, SLOT(showConfigDialogPlugins()) +// ); + + pBackendsNotify = new KPushButton( "", this, "pBackendsNotify"); + pBackendsNotify->setPixmap( KGlobal::iconLoader()->loadIcon("kcmsystem",KIcon::Toolbar) ); + QToolTip::add( pBackendsNotify, i18n("soundKonverter either found new backends or misses some.\nClick on this button in order to open the configuration dialog.") ); + pBackendsNotify->setShown( config->backendsChanged ); + config->backendsChanged = false; + pBackendsNotify->setPaletteBackgroundColor( QColor(255,220,247) ); + optionsBox->addWidget( pBackendsNotify ); + connect( pBackendsNotify, SIGNAL(clicked()), + this, SLOT(showConfigDialogBackends()) + ); + + pAdvancedOptionsToggle = new KPushButton( i18n("Advanced Options"), this, "pAdvancedOptionsToggle"); + pAdvancedOptionsToggle->setToggleButton( true ); + pAdvancedOptionsToggle->hide(); + optionsBox->addWidget( pAdvancedOptionsToggle ); + connect( pAdvancedOptionsToggle, SIGNAL(clicked()), + optionsDetailed, SLOT(toggleAdvancedOptions()) + ); +/* NOTE kaligames.de is down + if( config->data.plugins.checkForUpdates ) { + config->onlinePluginsChanged = false; + getPluginListJob = KIO::file_copy("http://kaligames.de/downloads/soundkonverter/plugins/download.php?version=" + QString::number(config->data.app.configVersion), + locateLocal("data","soundkonverter/pluginlist_new.txt"), -1, true, false, false ); + connect( getPluginListJob, SIGNAL(result(KIO::Job*)), + this, SLOT(getPluginListFinished(KIO::Job*)) + ); + } +*/ + if( config->data.general.defaultProfile == i18n("Last used") || config->getAllProfiles().findIndex(config->data.general.defaultProfile) != -1 ) { + setCurrentOptions( config->getProfile(config->data.general.defaultProfile) ); + } + else { + setProfile( config->data.general.defaultProfile ); + setFormat( config->data.general.defaultFormat ); + } +} + +Options::~Options() +{} + +// void Options::getPluginListFinished( KIO::Job* job ) +// { +// if( job->error() == 0 ) { +// QFile file( locateLocal("data","soundkonverter/pluginlist.txt") ); +// QFile newFile( locateLocal("data","soundkonverter/pluginlist_new.txt") ); +// +// if( !file.exists() ) { // TODO check against the installed plugins +// pPluginsNotify->show(); +// KIO::file_move( locateLocal("data","soundkonverter/pluginlist_new.txt"), locateLocal("data","soundkonverter/pluginlist.txt"), -1, true, false, false ); +// config->onlinePluginsChanged = true; +// return; +// } +// +// if( file.open(IO_ReadOnly) && newFile.open(IO_ReadOnly) ) { +// QTextStream stream( &file ); +// QTextStream newStream( &newFile ); +// while( !stream.atEnd() && !newStream.atEnd() ) { +// if( stream.readLine() != newStream.readLine() ) { +// file.close(); +// newFile.close(); +// pPluginsNotify->show(); +// KIO::file_move( locateLocal("data","soundkonverter/pluginlist_new.txt"), locateLocal("data","soundkonverter/pluginlist.txt"), -1, true, false, false ); +// config->onlinePluginsChanged = true; +// return; +// } +// } +// if( stream.atEnd() != newStream.atEnd() ) { +// file.close(); +// newFile.close(); +// pPluginsNotify->show(); +// KIO::file_move( locateLocal("data","soundkonverter/pluginlist_new.txt"), locateLocal("data","soundkonverter/pluginlist.txt"), -1, true, false, false ); +// config->onlinePluginsChanged = true; +// return; +// } +// file.close(); +// newFile.close(); +// } +// newFile.remove(); +// } +// } + +// void Options::showConfigDialogPlugins() +// { +// pPluginsNotify->hide(); +// emit showConfigPluginsPage(); +// } + +void Options::showConfigDialogBackends() +{ + pBackendsNotify->hide(); + emit showConfigEnvironmentPage(); +} + +ConversionOptions Options::getCurrentOptions() +{ + return optionsDetailed->getCurrentOptions(); +} + +void Options::setCurrentOptions( const ConversionOptions& options ) +{ + optionsDetailed->setCurrentOptions( options ); + /*if( tab->page(tab->currentPageIndex()) == optionsSimple ) { + optionsSimple->refill(); + }*/ + optionsSimple->refill(); +} + +void Options::tabChanged( QWidget* widget ) +{ + if( widget == optionsSimple ) { + pAdvancedOptionsToggle->hide(); + optionsSimple->refill(); + } + else { + pAdvancedOptionsToggle->show(); + } + config->data.general.lastTab = tab->currentPageIndex(); +} + +void Options::setProfile( const QString& profile ) +{ + optionsSimple->setCurrentProfile( profile ); +} + +void Options::setFormat( const QString& format ) +{ + optionsSimple->setCurrentFormat( format ); +} + +void Options::setOutputDirectory( const QString& directory ) +{ + optionsSimple->setCurrentOutputDirectory( directory ); +} + +void Options::somethingChanged() +{ + emit optionsChanged(); +} + +// TODO right this way? - seems to work +void Options::configChanged() +{ + optionsDetailed->refill(); + /*if( tab->page(tab->currentPageIndex()) == optionsSimple ) { + optionsSimple->refill(); + }*/ + optionsSimple->refill(); +} + diff --git a/src/options.h b/src/options.h new file mode 100755 index 0000000..f675aa1 --- /dev/null +++ b/src/options.h @@ -0,0 +1,123 @@ + + +#ifndef OPTIONS_H +#define OPTIONS_H + +#include + +#include "conversionoptions.h" + +#include + +class OptionsSimple; +class OptionsDetailed; +class Config; + +class QStringList; +class KTabWidget; +class KPushButton; + + +/** + * All we need to know about a profile + */ +struct ProfileData +{ + QString name; + ConversionOptions options; +}; + + +/** + * The data pool + */ +// struct OptionsData +// { +// QString name; +// ConversionOptions options; +// }; + + +/** + * @short The widget, where we can set our output options + * @author Daniel Faust + * @version 0.3 + */ +class Options : public QWidget +{ + Q_OBJECT +public: + /** + * Constructor + */ + Options( Config*, const QString &text, QWidget* parent = 0, const char* name = 0 ); + + /** + * Destructor + */ + virtual ~Options(); + + /** + * Return the current options + */ + ConversionOptions getCurrentOptions(); + +public slots: + /** + * Set the current options + */ + void setCurrentOptions( const ConversionOptions& ); + + /** + * Set the current profile + */ + void setProfile( const QString& ); + + /** + * Set the current format + */ + void setFormat( const QString& ); + + /** + * Set the current output directory + */ + void setOutputDirectory( const QString& ); + +private: + /** Toggle between normal and advanced options in the detailed tab */ + KPushButton* pAdvancedOptionsToggle; + + //** Notify the user about new plugins */ +// KPushButton* pPluginsNotify; + /** Notify the user about new / lost backends */ + KPushButton* pBackendsNotify; + + KTabWidget* tab; + + OutputDirectory* outputDirectory; + + OptionsSimple* optionsSimple; + OptionsDetailed* optionsDetailed; + + Config *config; + + KIO::FileCopyJob* getPluginListJob; + + // /** Copy all options from the detailed tab to the simple tab / find the matching profile */ + //void updateSimpleTab(); + +private slots: + void tabChanged( QWidget* ); + void somethingChanged(); + void configChanged(); +// void getPluginListFinished( KIO::Job* job ); +// void showConfigDialogPlugins(); + void showConfigDialogBackends(); + +signals: + void optionsChanged(); + void showConfigPluginsPage(); + void showConfigEnvironmentPage(); +}; + +#endif // OPTIONS_H diff --git a/src/optionsdetailed.cpp b/src/optionsdetailed.cpp new file mode 100755 index 0000000..320f3bb --- /dev/null +++ b/src/optionsdetailed.cpp @@ -0,0 +1,911 @@ + +#include "optionsdetailed.h" +#include "convertpluginloader.h" +#include "config.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +//#include +#include + +#include + + +// TODO hide save button, if shown in the edit options window? + +// FIXME refill the formats box, when the configuration changed + +OptionsDetailed::OptionsDetailed( Config* _config, QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + config = _config; + + QGridLayout *gridLayout = new QGridLayout( this ); + + // normal options + normalOptions = new QWidget( this, "normalOptions" ); + gridLayout->addWidget( normalOptions, 0, 0 ); + + QGridLayout *normalGrid = new QGridLayout( normalOptions, 2, 1, 6, 3 ); + + QHBoxLayout *normalTopBox = new QHBoxLayout(); + normalGrid->addLayout( normalTopBox, 0, 0 ); + + QLabel* lConvert = new QLabel( i18n("Convert")+":", normalOptions, "lConvert" ); + normalTopBox->addWidget( lConvert, 0, Qt::AlignVCenter ); + cFormat = new KComboBox( normalOptions, "cFormat" ); + normalTopBox->addWidget( cFormat, 0, Qt::AlignVCenter ); + connect( cFormat, SIGNAL(activated(int)), + this, SLOT(formatChanged()) + ); + connect( cFormat, SIGNAL(activated(int)), + this, SLOT(somethingChanged()) + ); + cQualityMode = new KComboBox( normalOptions, "cQualityMode" ); + cQualityMode->setFixedSize( cQualityMode->sizeHint() ); + normalTopBox->addWidget( cQualityMode, 0, Qt::AlignVCenter ); + connect( cQualityMode, SIGNAL(activated(int)), + this, SLOT(qualityModeChanged()) + ); + connect( cQualityMode, SIGNAL(activated(int)), + this, SLOT(somethingChanged()) + ); + iQuality = new KIntSpinBox( normalOptions, "iQuality" ); + normalTopBox->addWidget( iQuality, 0, Qt::AlignVCenter ); + connect( iQuality, SIGNAL(valueChanged(int)), + this, SLOT(qualityChanged()) + ); + connect( iQuality, SIGNAL(valueChanged(int)), + this, SLOT(somethingChanged()) + ); + cBitrateMode = new KComboBox( normalOptions, "cBitrateMode" ); + QToolTip::add( cBitrateMode, i18n("vbr - variable bitrate\nabr - average bitrate\ncbr - constant bitrate") ); + normalTopBox->addWidget( cBitrateMode, 0, Qt::AlignVCenter ); + connect( cBitrateMode, SIGNAL(activated(int)), + this, SLOT(bitrateModeChanged()) + ); + connect( cBitrateMode, SIGNAL(activated(int)), + this, SLOT(somethingChanged()) + ); + normalTopBox->addSpacing( 18 ); + + cBitrateRangeSwitch = new QCheckBox( i18n("Bitrate range")+":", normalOptions, "cBitrateRangeSwitch" ); + QToolTip::add( cBitrateRangeSwitch, i18n("Use it only if, you know what you are doing, you could reduce the quality.") ); + normalTopBox->addWidget( cBitrateRangeSwitch, 0, Qt::AlignVCenter ); + connect( cBitrateRangeSwitch, SIGNAL(toggled(bool)), + this, SLOT(bitrateRangeToggled()) + ); + connect( cBitrateRangeSwitch, SIGNAL(toggled(bool)), + this, SLOT(somethingChanged()) + ); + iMinBitrate = new KIntSpinBox( normalOptions, "iMinBitrate" ); + iMinBitrate->setMinValue( 32 ); + iMinBitrate->setMaxValue( 320 ); + iMinBitrate->setLineStep( 8 ); + iMinBitrate->setValue( 64 ); + normalTopBox->addWidget( iMinBitrate, 0, Qt::AlignVCenter ); + connect( iMinBitrate, SIGNAL(valueChanged(int)), + this, SLOT(somethingChanged()) + ); + lBitrateRangeTo = new QLabel( "-", normalOptions, "lBitrateRangeTo" ); + normalTopBox->addWidget( lBitrateRangeTo, 0, Qt::AlignVCenter ); + iMaxBitrate = new KIntSpinBox( normalOptions, "iMaxBitrate" ); + iMaxBitrate->setMinValue( 32 ); + iMaxBitrate->setMaxValue( 320 ); + iMaxBitrate->setLineStep( 8 ); + iMaxBitrate->setValue( 192 ); + normalTopBox->addWidget( iMaxBitrate, 0, Qt::AlignVCenter ); + connect( iMaxBitrate, SIGNAL(valueChanged(int)), + this, SLOT(somethingChanged()) + ); + lBitrateRangeUnit = new QLabel( "kbps", normalOptions, "lBitrateRangeUnit" ); + normalTopBox->addWidget( lBitrateRangeUnit, 0, Qt::AlignVCenter ); + normalTopBox->addStretch(); + + QHBoxLayout *normalMiddleBox = new QHBoxLayout(); + normalGrid->addLayout( normalMiddleBox, 1, 0 ); + + cSamplingrateSwitch = new QCheckBox( i18n("Resample")+":", normalOptions, "cSamplingrateSwitch" ); + normalMiddleBox->addWidget( cSamplingrateSwitch, 0, Qt::AlignVCenter ); + connect( cSamplingrateSwitch, SIGNAL(toggled(bool)), + this, SLOT(samplingrateToggled()) + ); + connect( cSamplingrateSwitch, SIGNAL(toggled(bool)), + this, SLOT(somethingChanged()) + ); + cSamplingrate = new KComboBox( normalOptions, "cSamplingrate" ); + cSamplingrate->setEditable(true); + cSamplingrate->insertItem("48000"); + cSamplingrate->insertItem("44100"); + cSamplingrate->insertItem("32000"); + cSamplingrate->insertItem("24000"); + cSamplingrate->insertItem("22050"); + cSamplingrate->insertItem("16000"); + cSamplingrate->insertItem("12000"); + cSamplingrate->insertItem("11025"); + cSamplingrate->insertItem("8000"); + cSamplingrate->setCurrentText("44100"); + normalMiddleBox->addWidget( cSamplingrate, 0, Qt::AlignVCenter ); + connect( cSamplingrate, SIGNAL(activated(int)), + this, SLOT(somethingChanged()) + ); + lSamplingrateUnit = new QLabel( "Hz", normalOptions, "lSamplingrateUnit" ); + normalMiddleBox->addWidget( lSamplingrateUnit, 0, Qt::AlignVCenter ); + normalMiddleBox->addSpacing( 18 ); + + cChannelsSwitch = new QCheckBox( i18n("Channels")+":", normalOptions, "cChannelsSwitch" ); + normalMiddleBox->addWidget( cChannelsSwitch, 0, Qt::AlignVCenter ); + connect( cChannelsSwitch, SIGNAL(toggled(bool)), + this, SLOT(channelsToggled()) + ); + connect( cChannelsSwitch, SIGNAL(toggled(bool)), + this, SLOT(somethingChanged()) + ); + cChannels = new KComboBox( normalOptions, "cChannels" ); +/* sChannels.append( i18n("Mono") ); + sChannels.append( i18n("Stereo") ); + sChannels.append( i18n("Joint-Stereo") ); + sChannels.append( i18n("Forced Joint-Stereo") ); + sChannels.append( i18n("Dual Channels") ); + cChannels->insertStringList( sChannels );*/ + normalMiddleBox->addWidget( cChannels, 0, Qt::AlignVCenter ); + connect( cChannels, SIGNAL(activated(int)), + this, SLOT(somethingChanged()) + ); + normalMiddleBox->addSpacing( 18 ); + + cReplayGain = new QCheckBox( i18n("Replay Gain"), normalOptions, "cReplayGain" ); + cReplayGain->setChecked(true); + QToolTip::add( cReplayGain, i18n("Add a Replay Gain tag to the converted file.") ); + QWhatsThis::add( cReplayGain, i18n("Replay Gain is a volume correction technique. A volume difference is calculated and stored in a tag. This way audio players can automatically adjust the volume and the original music data is not modified (like at normalization).") ); + normalMiddleBox->addWidget( cReplayGain, 0, Qt::AlignVCenter ); + connect( cReplayGain, SIGNAL(toggled(bool)), + this, SLOT(somethingChanged()) + ); + normalMiddleBox->addStretch(); + + QHBoxLayout *normalBottomBox = new QHBoxLayout( ); + normalGrid->addLayout( normalBottomBox, 2, 0 ); + + outputDirectory = new OutputDirectory( config, normalOptions, "outputDirectory" ); + normalBottomBox->addWidget( outputDirectory, 0, Qt::AlignVCenter ); + connect( outputDirectory, SIGNAL(modeChanged(OutputDirectory::Mode)), + this, SLOT(somethingChanged()) + ); + connect( outputDirectory, SIGNAL(directoryChanged(const QString&)), + this, SLOT(somethingChanged()) + ); + normalBottomBox->addSpacing( 18 ); + + pProfileSave = new KToolBarButton( "filesave", 1003, normalOptions, "pProfileSave" ); + QToolTip::add( pProfileSave, i18n("Save current options as a profile") ); + normalBottomBox->addWidget( pProfileSave, 0, Qt::AlignVCenter ); + connect( pProfileSave, SIGNAL(clicked()), + this, SLOT(saveProfile()) + ); + + // advanced options + advancedOptions = new QWidget( this, "advancedOptions" ); + advancedOptions->hide(); + gridLayout->addWidget( advancedOptions, 0, 0 ); + + QGridLayout *advancedGrid = new QGridLayout( advancedOptions, 2, 1, 6, 3 ); + + QHBoxLayout *advancedTopBox = new QHBoxLayout(); + advancedGrid->addLayout( advancedTopBox, 0, 0 ); + + QLabel* lUserOptionsLabel = new QLabel( i18n("Command")+":", advancedOptions, "lUserOptionsLabel" ); + advancedTopBox->addWidget( lUserOptionsLabel, 0, Qt::AlignVCenter ); + lUserOptions = new KLineEdit( advancedOptions, "lUserOptions" ); + advancedTopBox->addWidget( lUserOptions, 0, Qt::AlignVCenter ); + connect( lUserOptions, SIGNAL(textChanged(const QString&)), + this, SLOT(somethingChanged()) + ); + + QHBoxLayout *advancedMiddleBox = new QHBoxLayout(); + advancedGrid->addLayout( advancedMiddleBox, 1, 0 ); + + QLabel* lInfoParams = new QLabel( i18n("%p: The parameters generated by soundKonverter"), advancedOptions, "lInfoParams" ); + advancedMiddleBox->addWidget( lInfoParams, 0, Qt::AlignVCenter ); + + QHBoxLayout *advancedBottomBox = new QHBoxLayout(); + advancedGrid->addLayout( advancedBottomBox, 2, 0 ); + + QLabel* lInfoFiles = new QLabel( i18n("%i: The input file ; %o: The output file"), advancedOptions, "lInfoFiles" ); + advancedBottomBox->addWidget( lInfoFiles, 0, Qt::AlignVCenter ); + + refill(); +} + +OptionsDetailed::~OptionsDetailed() +{} + +ConversionOptions OptionsDetailed::getCurrentOptions() +{ + ConversionOptions options; + + options.encodingOptions.sFormat = cFormat->currentText(); + options.encodingOptions.sQualityMode = cQualityMode->currentText(); + if( iQuality->isEnabled() ) { + options.encodingOptions.iQuality = iQuality->value(); + } + else { + options.encodingOptions.iQuality = 0; + } + if( cQualityMode->currentText() == i18n("Bitrate") || cQualityMode->currentText() == i18n("Quality") ) { + options.encodingOptions.sBitrateMode = cBitrateMode->currentText(); + } + else { + options.encodingOptions.sBitrateMode = ""; + } + + if( cBitrateRangeSwitch->isEnabled() && cBitrateRangeSwitch->isChecked() ) { + options.encodingOptions.bBitrateRange = true; + options.encodingOptions.iMinBitrate = iMinBitrate->value(); + options.encodingOptions.iMaxBitrate = iMaxBitrate->value(); + } + else { + options.encodingOptions.bBitrateRange = false; + options.encodingOptions.iMinBitrate = 0; + options.encodingOptions.iMaxBitrate = 0; + } + + if( cSamplingrateSwitch->isEnabled() && cSamplingrateSwitch->isChecked() ) { + options.encodingOptions.samplingRate.bEnabled = true; + options.encodingOptions.samplingRate.iSamplingRate = cSamplingrate->currentText().toInt(); + } + else { + options.encodingOptions.samplingRate.bEnabled = false; + options.encodingOptions.samplingRate.iSamplingRate = 0; + } + + if( cChannelsSwitch->isEnabled() && cChannelsSwitch->isChecked() ) { + options.encodingOptions.channels.bEnabled = true; + options.encodingOptions.channels.sChannels = cChannels->currentText(); + } + else { + options.encodingOptions.channels.bEnabled = false; + options.encodingOptions.channels.sChannels = ""; + } + + if( cReplayGain->isEnabled() && cReplayGain->isChecked() ) { + options.encodingOptions.replaygain.bEnabled = true; + } + else { + options.encodingOptions.replaygain.bEnabled = false; + } + + options.outputOptions.mode = outputDirectory->mode(); + options.outputOptions.directory = outputDirectory->directory(); + + options.encodingOptions.sInOutFiles = lUserOptions->text(); + + return options; +} + +void OptionsDetailed::setCurrentOptions( const ConversionOptions& options ) +{ + // NOTE the values are not verified because they HAVE to be correct + + cFormat->setCurrentItem( formatIndex(options.encodingOptions.sFormat) ); + formatChanged(); + cQualityMode->setCurrentItem( qualityModeIndex(options.encodingOptions.sQualityMode) ); + qualityModeChanged(); + if( options.encodingOptions.iQuality != 0 ) { + iQuality->setValue( options.encodingOptions.iQuality ); + } + if( options.encodingOptions.sBitrateMode != "" ) { + cBitrateMode->setCurrentItem( bitrateModeIndex(options.encodingOptions.sBitrateMode) ); + } + + if( options.encodingOptions.bBitrateRange == true ) { + cBitrateRangeSwitch->setChecked( true ); + iMinBitrate->setValue( options.encodingOptions.iMinBitrate ); + iMaxBitrate->setValue( options.encodingOptions.iMaxBitrate ); + } + else { + cBitrateRangeSwitch->setChecked( false ); + } + + if( options.encodingOptions.samplingRate.bEnabled == true ) { + cSamplingrateSwitch->setChecked( true ); + cSamplingrate->setCurrentText( QString::number(options.encodingOptions.samplingRate.iSamplingRate) ); + } + else { + cSamplingrateSwitch->setChecked( false ); + } + + if( options.encodingOptions.channels.bEnabled == true ) { + cChannelsSwitch->setChecked( true ); + cChannels->setCurrentItem( channelsIndex(options.encodingOptions.channels.sChannels) ); + } + else { + cChannelsSwitch->setChecked( false ); + } + + if( options.encodingOptions.replaygain.bEnabled == true ) { + cReplayGain->setChecked( true ); + } + else { + cReplayGain->setChecked( false ); + } + + outputDirectory->setMode( options.outputOptions.mode ); + outputDirectory->setDirectory( options.outputOptions.directory ); + + lUserOptions->setText( options.encodingOptions.sInOutFiles ); +} + +void OptionsDetailed::saveProfile() +{ + bool ok; + QString name = KInputDialog::getText( i18n("New profile"), i18n("Enter a name for the new profile:"), "", &ok ); + if( ok ) { + QStringList profiles; + profiles += i18n("Very low"); + profiles += i18n("Low"); + profiles += i18n("Medium"); + profiles += i18n("High"); + profiles += i18n("Very high"); + profiles += i18n("Lossless"); + profiles += i18n("Hybrid"); + profiles += i18n("Last used"); + profiles += "Last used"; + profiles += i18n("User defined"); + if( profiles.findIndex(name) != -1 ) { + KMessageBox::error( this, + i18n("You cannot overwrite the built-in profiles."), + i18n("Profile already exists") ); + return; + } + profiles = config->getAllProfiles(); + if( profiles.findIndex(name) == -1 ) { + config->addProfile( name, getCurrentOptions() ); + } + else { + int ret = KMessageBox::questionYesNo( this, + i18n("A profile with this name already exists.\n\nDo you want to overwrite the existing one?"), + i18n("Profile already exists") ); + if( ret == KMessageBox::Yes ) { + config->removeProfile( name ); + config->addProfile( name, getCurrentOptions() ); + } + } + } +} + +int OptionsDetailed::formatIndex( const QString &string ) +{ + return sFormat.findIndex( string ); +} + +int OptionsDetailed::qualityModeIndex( const QString &string ) +{ + return sQualityMode.findIndex( string ); +} + +int OptionsDetailed::bitrateModeIndex( const QString &string ) +{ + return sBitrateMode.findIndex( string ); +} + +int OptionsDetailed::channelsIndex( const QString &string ) +{ + return sChannels.findIndex( string ); +} + +void OptionsDetailed::refill() +{ + QString format = cFormat->currentText(); + + sFormat = config->allEncodableFormats(); + sFormat.append( "wav" ); + cFormat->clear(); + cFormat->insertStringList( sFormat ); + + cFormat->setCurrentItem( formatIndex(format) ); + + formatChanged(); +} + +void OptionsDetailed::formatChanged() +{ + if( cFormat->currentText() == "wav" ) { + cReplayGain->setEnabled( false ); + sQualityMode.clear(); + sQualityMode.append( i18n("Lossless") ); + cQualityMode->clear(); + cQualityMode->insertStringList( sQualityMode ); + qualityModeChanged(); + lUserOptions->setEnabled( false ); + return; + } + + FormatItem* formatItem = config->getFormatItem( cFormat->currentText() ); + if( formatItem == 0 ) { + // FIXME error handling + //kdDebug() << "NULL POINTER: `" << "Convert::formatChanged() / formatItem" << "'" << endl; + return; + } + ConvertPlugin* plugin = formatItem->encoder; + if( plugin == 0 ) { + // FIXME error handling + //kdDebug() << "NULL POINTER: `" << "OptionsDetailed::formatChanged() / plugin" << "'" << endl; + return; + } + + lUserOptions->setEnabled( true ); + QString lastString = lUserOptions->text(); + QString bin = config->binaries[plugin->enc.bin]; + if( lastString.left(bin.length()) != bin ) { + lUserOptions->setText( config->binaries[plugin->enc.bin] + " " + plugin->enc.in_out_files ); + } + + QString lastQualityMode = cQualityMode->currentText(); + sQualityMode.clear(); + + if( formatItem->replaygain || ( plugin->enc.replaygain.enabled && formatItem->internalReplayGain ) ) { + cReplayGain->setEnabled( true ); + } + else { + cReplayGain->setEnabled( false ); + } + + if( plugin->enc.lossy.enabled ) { + if( plugin->enc.lossy.quality.enabled ) { + sQualityMode.append( i18n("Quality") ); + } + if( plugin->enc.lossy.bitrate.abr.enabled || plugin->enc.lossy.bitrate.cbr.enabled ) { + sQualityMode.append( i18n("Bitrate") ); + } + if( !plugin->enc.lossy.quality.enabled && !plugin->enc.lossy.bitrate.abr.enabled && !plugin->enc.lossy.bitrate.cbr.enabled ) { + sQualityMode.append( i18n("Unchanged") ); + } + } + if( plugin->enc.lossless.enabled ) { + sQualityMode.append( i18n("Lossless") ); + } + if( plugin->enc.hybrid.enabled ) { + sQualityMode.append( i18n("Hybrid") ); + } + if( !plugin->enc.lossy.enabled && !plugin->enc.lossless.enabled && !plugin->enc.hybrid.enabled ) { + sQualityMode.append( i18n("Undefined") ); + } + + cQualityMode->clear(); + cQualityMode->insertStringList( sQualityMode ); + + cQualityMode->setCurrentItem( qualityModeIndex(lastQualityMode) ); + qualityModeChanged(); +} + +void OptionsDetailed::qualityModeChanged() +{ + QWhatsThis::remove( iQuality ); + + if( cFormat->currentText() == "wav" ) { + iQuality->setEnabled( false ); + cBitrateMode->setEnabled( false ); + cBitrateRangeSwitch->setEnabled( false ); + iMinBitrate->setEnabled( false ); + lBitrateRangeTo->setEnabled( false ); + iMaxBitrate->setEnabled( false ); + lBitrateRangeUnit->setEnabled( false ); + cSamplingrateSwitch->setEnabled( false ); + cSamplingrate->setEnabled( false ); + lSamplingrateUnit->setEnabled( false ); + cChannelsSwitch->setEnabled( false ); + cChannels->setEnabled( false ); + return; + } + + QString qualityModeString = cQualityMode->currentText(); + QString lastString; + int lastValue; + + ConvertPlugin* plugin = config->encoderForFormat( cFormat->currentText() ); + + if( lastQualityMode != qualityModeString ) { + lastValue = 0; + lastQualityMode = qualityModeString; + } + else { + lastValue = iQuality->value(); + } + + if( qualityModeString != i18n("Lossless") ) { +// bitrateRangeToggled(); NOTE seems to be unnecessary + if( plugin->enc.lossy.samplingrate.enabled ) cSamplingrateSwitch->setEnabled( true ); + else cSamplingrateSwitch->setEnabled( false ); + samplingrateToggled(); + if( plugin->enc.lossy.channels.mono_enabled || plugin->enc.lossy.channels.stereo_enabled || plugin->enc.lossy.channels.joint_stereo_enabled || + plugin->enc.lossy.channels.forced_joint_stereo_enabled || plugin->enc.lossy.channels.dual_channels_enabled ) { + cChannelsSwitch->setEnabled( true ); + lastString = cChannels->currentText(); + sChannels.clear(); + if( plugin->enc.lossy.channels.mono_enabled ) { + sChannels.append( i18n("Mono") ); + } + if( plugin->enc.lossy.channels.stereo_enabled ) { + sChannels.append( i18n("Stereo") ); + } + if( plugin->enc.lossy.channels.joint_stereo_enabled ) { + sChannels.append( i18n("Joint-Stereo") ); + } + if( plugin->enc.lossy.channels.forced_joint_stereo_enabled ) { + sChannels.append( i18n("Forced Joint-Stereo") ); + } + if( plugin->enc.lossy.channels.dual_channels_enabled ) { + sChannels.append( i18n("Dual Channels") ); + } + cChannels->clear(); + cChannels->insertStringList( sChannels ); + cChannels->setCurrentItem( channelsIndex(lastString) ); + } + else cChannelsSwitch->setEnabled( false ); + channelsToggled(); + } + + if( qualityModeString == i18n("Bitrate") ) { + QToolTip::add( iQuality, i18n("Kilobit per second") ); + iQuality->setEnabled( true ); + iQuality->setMinValue( 32 ); + iQuality->setMaxValue( 320 ); + iQuality->setLineStep( 8 ); + if( lastValue != 0 ) iQuality->setValue( lastValue ); + else iQuality->setValue( 192 ); + cBitrateMode->setEnabled( true ); + lastString = cBitrateMode->currentText(); + sBitrateMode.clear(); + if( plugin->enc.lossy.bitrate.abr.enabled ) { + sBitrateMode.append( "abr" ); + } + if( plugin->enc.lossy.bitrate.cbr.enabled ) { + sBitrateMode.append( "cbr" ); + } + cBitrateMode->clear(); + cBitrateMode->insertStringList( sBitrateMode ); + cBitrateMode->setCurrentItem( bitrateModeIndex(lastString) ); + bitrateModeChanged(); + } + else if( qualityModeString == i18n("Quality") ) { +// QToolTip::add( iQuality, i18n("This is a relative quality between 0 and 100.\nThe higher this number the higher is the quality.\nsoundKonverter will convert it into the file format's quality format.\nSee the \"What's this?\" for more informations.") ); + iQuality->setEnabled( true ); + iQuality->setMinValue( 0 ); + iQuality->setMaxValue( 100 ); + iQuality->setLineStep( 5 ); + if( lastValue != 0 ) iQuality->setValue( lastValue ); + else iQuality->setValue( 40 ); + qualityChanged(); + cBitrateMode->setEnabled( true ); + sBitrateMode.clear(); + sBitrateMode.append( "vbr" ); + cBitrateMode->clear(); + cBitrateMode->insertStringList( sBitrateMode ); + bitrateModeChanged(); + + if( plugin->enc.lossy.quality.help ) { + QString str = plugin->enc.lossy.quality.help; + str.replace("\\n","
"); + QWhatsThis::add( iQuality, "

"+str+"

" ); + } + } + else if( qualityModeString == i18n("Lossless") || qualityModeString == i18n("Undefined") ) { + iQuality->setEnabled( false ); + cBitrateMode->setEnabled( false ); + cBitrateRangeSwitch->setEnabled( false ); + iMinBitrate->setEnabled( false ); + lBitrateRangeTo->setEnabled( false ); + iMaxBitrate->setEnabled( false ); + lBitrateRangeUnit->setEnabled( false ); + cSamplingrateSwitch->setEnabled( false ); + cSamplingrate->setEnabled( false ); + lSamplingrateUnit->setEnabled( false ); + cChannelsSwitch->setEnabled( false ); + cChannels->setEnabled( false ); + } + else if( qualityModeString == i18n("Hybrid") ) { + QToolTip::add( iQuality, i18n("Kilobit per second") ); + iQuality->setEnabled( true ); + iQuality->setMinValue( 32 ); + iQuality->setMaxValue( 320 ); + iQuality->setLineStep( 8 ); + if( lastValue != 0 ) iQuality->setValue( lastValue ); + else iQuality->setValue( 192 ); + cBitrateMode->setEnabled( false ); + } + else if( qualityModeString == i18n("Unchanged") ) { + iQuality->setEnabled( false ); + cBitrateMode->setEnabled( false ); + cBitrateRangeSwitch->setEnabled( false ); + iMinBitrate->setEnabled( false ); + lBitrateRangeTo->setEnabled( false ); + iMaxBitrate->setEnabled( false ); + lBitrateRangeUnit->setEnabled( false ); + } +} + +void OptionsDetailed::qualityChanged() +{ + if( cQualityMode->currentText() == i18n("Quality") ) { + QToolTip::remove( iQuality ); + + FormatItem* formatItem = config->getFormatItem( cFormat->currentText() ); + if( formatItem == 0 ) { + // FIXME error handling + //kdDebug() << "NULL POINTER: `" << "Convert::formatChanged() / formatItem" << "'" << endl; + return; + } + ConvertPlugin* plugin = formatItem->encoder; + if( plugin == 0 ) { + // FIXME error handling + //kdDebug() << "NULL POINTER: `" << "OptionsDetailed::formatChanged() / plugin" << "'" << endl; + return; + } + + QString quality; + if( plugin->enc.lossy.quality.enabled ) { + quality = plugin->enc.lossy.quality.param; + int qualityLevel = iQuality->value(); + if( plugin->enc.lossy.quality.profiles.empty() ) { + if( plugin->enc.lossy.quality.step < 1 ) { + if( plugin->enc.lossy.quality.range_max >= plugin->enc.lossy.quality.range_min) +// t_float = ( (float)item->fileListItem->options.encodingOptions.iQuality * ( plugin->enc.lossy.quality.range_max - plugin->enc.lossy.quality.range_min ) / 100 ) + plugin->enc.lossy.quality.range_min; + quality.replace( "%q", QString::number( ( (float)qualityLevel * ( plugin->enc.lossy.quality.range_max - plugin->enc.lossy.quality.range_min ) / 100 ) + plugin->enc.lossy.quality.range_min ) ); + else +// t_float = ( (100.0f - (float)item->fileListItem->options.encodingOptions.iQuality) * ( plugin->enc.lossy.quality.range_min - plugin->enc.lossy.quality.range_max ) / 100 ) + plugin->enc.lossy.quality.range_max; + quality.replace( "%q", QString::number( ( (100.0f - qualityLevel) * ( plugin->enc.lossy.quality.range_min - plugin->enc.lossy.quality.range_max ) / 100 ) + plugin->enc.lossy.quality.range_max ) ); + } + else { + if( plugin->enc.lossy.quality.range_max >= plugin->enc.lossy.quality.range_min) +// t_int = ( item->fileListItem->options.encodingOptions.iQuality * (int)( plugin->enc.lossy.quality.range_max - plugin->enc.lossy.quality.range_min ) / 100) + (int)plugin->enc.lossy.quality.range_min; + quality.replace( "%q", QString::number( (qualityLevel * (int)( plugin->enc.lossy.quality.range_max - plugin->enc.lossy.quality.range_min ) / 100) + (int)plugin->enc.lossy.quality.range_min ) ); + else +// t_int = ( (100 - item->fileListItem->options.encodingOptions.iQuality) * (int)( plugin->enc.lossy.quality.range_min - plugin->enc.lossy.quality.range_max ) / 100) + (int)plugin->enc.lossy.quality.range_max; + quality.replace( "%q", QString::number( ( (100 - qualityLevel) * (int)( plugin->enc.lossy.quality.range_min - plugin->enc.lossy.quality.range_max ) / 100) + (int)plugin->enc.lossy.quality.range_max ) ); + } + if( plugin->enc.bin == "oggenc" ) quality.replace(QChar('.'),KGlobal::locale()->decimalSymbol()); // HACK make oggenc usable with all langauges + else if( plugin->enc.lossy.quality.separator != '.' ) { + quality.replace( QChar('.'), plugin->enc.lossy.quality.separator ); + } + } + else { + QStringList::Iterator it = plugin->enc.lossy.quality.profiles.at( rint(qualityLevel*plugin->enc.lossy.quality.range_max/100) ); + quality.replace( "%q", *it ); + } + } + + QToolTip::add( iQuality, i18n("This is a relative quality between 0 and 100.\nThe higher this number the higher is the quality.\nsoundKonverter will convert it into the file format's quality format.\nSee the \"What's this?\" for more informations.\n\nCurrent parameter: \"%1\"").arg(quality) ); +// QToolTip toolTip( iQuality ); +// toolTip.tip( i18n("Current parameter: \"%1\"").arg(quality) ); + } +} + +void OptionsDetailed::bitrateModeChanged() +{ + ConvertPlugin* plugin = config->encoderForFormat( cFormat->currentText() ); + + if( cBitrateMode->currentText() == "abr" && plugin->enc.lossy.bitrate.abr.bitrate_range.enabled ) { + cBitrateRangeSwitch->setEnabled( true ); + bitrateRangeToggled(); + } + else { + cBitrateRangeSwitch->setEnabled( false ); + iMinBitrate->setEnabled( false ); + lBitrateRangeTo->setEnabled( false ); + iMaxBitrate->setEnabled( false ); + lBitrateRangeUnit->setEnabled( false ); + } +} + +void OptionsDetailed::bitrateRangeToggled() +{ + if( cBitrateRangeSwitch->isChecked() && cBitrateRangeSwitch->isEnabled() ) { + iMinBitrate->setEnabled( true ); + lBitrateRangeTo->setEnabled( true ); + iMaxBitrate->setEnabled( true ); + lBitrateRangeUnit->setEnabled( true ); + } + else { + iMinBitrate->setEnabled( false ); + lBitrateRangeTo->setEnabled( false ); + iMaxBitrate->setEnabled( false ); + lBitrateRangeUnit->setEnabled( false ); + } +} + +void OptionsDetailed::samplingrateToggled() { + if( cSamplingrateSwitch->isChecked() && cSamplingrateSwitch->isEnabled() ) { + cSamplingrate->setEnabled( true ); + lSamplingrateUnit->setEnabled( true ); + } + else { + cSamplingrate->setEnabled( false ); + lSamplingrateUnit->setEnabled( false ); + } +} + +void OptionsDetailed::channelsToggled() { + if( cChannelsSwitch->isChecked() && cChannelsSwitch->isEnabled() ) { + cChannels->setEnabled( true ); + } + else { + cChannels->setEnabled( false); + } +} + +void OptionsDetailed::somethingChanged() +{ + emit optionsChanged(); +} + +//////////////////////////////////////////////////////////// +// access the options data - BEGIN +//////////////////////////////////////////////////////////// + +QString OptionsDetailed::getFormat() +{ + return cFormat->currentText(); +} + +// QString OptionsDetailed::getQualityMode() +// { +// return cQualityMode->currentText(); +// } + +OutputDirectory::Mode OptionsDetailed::getOutputDirectoryMode() +{ + return outputDirectory->mode(); +} + +QString OptionsDetailed::getOutputDirectoryPath() +{ + return outputDirectory->directory(); +} + + +void OptionsDetailed::setFormat( const QString &format ) +{ + cFormat->setCurrentItem( formatIndex(format) ); + + formatChanged(); +} + +void OptionsDetailed::setQualityMode( const QString &qualityMode ) +{ + cQualityMode->setCurrentItem( qualityModeIndex(qualityMode) ); + qualityModeChanged(); +} + +void OptionsDetailed::setQuality( int quality ) +{ + iQuality->setValue( quality ); +} + +void OptionsDetailed::setBitrateMode( const QString &bitrateMode ) +{ + cBitrateMode->setCurrentItem( bitrateModeIndex(bitrateMode) ); + bitrateModeChanged(); +} + +void OptionsDetailed::setBitrateRangeEnabled( bool enabled ) +{ + cBitrateRangeSwitch->setChecked( enabled ); +} + +void OptionsDetailed::setMinBitrate( int bitrate ) +{ + iMinBitrate->setValue( bitrate ); +} + +void OptionsDetailed::setMaxBitrate( int bitrate ) +{ + iMaxBitrate->setValue( bitrate ); +} + +void OptionsDetailed::setSamplingrateEnabled( bool enabled ) +{ + cSamplingrateSwitch->setChecked( enabled ); +} + +void OptionsDetailed::setSamplingrate( int samplingrate ) +{ + char text[8]; + + sprintf( text, "%i", samplingrate ); + + setSamplingrate( text ); +} + +void OptionsDetailed::setSamplingrate( const QString &samplingrate ) +{ + cSamplingrate->setCurrentText( samplingrate ); +} + +void OptionsDetailed::setChannelsEnabled( bool enabled ) +{ + cChannelsSwitch->setChecked( enabled ); +} + +void OptionsDetailed::setChannels( const QString &channels ) +{ + cChannels->setCurrentItem( channelsIndex(channels) ); +} + +void OptionsDetailed::setReplayGainEnabled( bool enabled ) +{ + cReplayGain->setChecked( enabled ); +} + +void OptionsDetailed::setOutputDirectoryMode( OutputDirectory::Mode mode ) +{ + outputDirectory->setMode( mode ); +} + +void OptionsDetailed::setOutputDirectoryPath( const QString &path ) +{ + outputDirectory->setDirectory( path ); +} + +void OptionsDetailed::setUserOptions( const QString &options ) +{ + lUserOptions->setText( options ); +} + +int OptionsDetailed::getQuality() +{ + return iQuality->value(); +} + +bool OptionsDetailed::getBitrateRangeEnabled() +{ + return cBitrateRangeSwitch->isChecked(); +} + +bool OptionsDetailed::getSamplingrateEnabled() +{ + return cSamplingrateSwitch->isChecked(); +} + +int OptionsDetailed::getSamplingrate() +{ + return cSamplingrate->currentText().toInt(); +} + +bool OptionsDetailed::getChannelsEnabled() +{ + return cChannelsSwitch->isChecked(); +} + +QString OptionsDetailed::getChannels() +{ + return cChannels->currentText(); +} + +//////////////////////////////////////////////////////////// +// access the options data - END +//////////////////////////////////////////////////////////// + +void OptionsDetailed::toggleAdvancedOptions() +{ + if( normalOptions->isVisible() ) { + normalOptions->hide(); + advancedOptions->show(); + } + else { + advancedOptions->hide(); + normalOptions->show(); + } +} + diff --git a/src/optionsdetailed.h b/src/optionsdetailed.h new file mode 100755 index 0000000..e743907 --- /dev/null +++ b/src/optionsdetailed.h @@ -0,0 +1,145 @@ + + +#ifndef OPTIONSDETAILED_H +#define OPTIONSDETAILED_H + +#include "outputdirectory.h" +#include "conversionoptions.h" + +#include + +class Config; +//class OutputDirectory; +class ConversionOptions; + +class QLabel; +class KIntSpinBox; +class QCheckBox; +class KComboBox; +class KLineEdit; +class KToolBarButton; + +/** + * @short The options widget for setting up the output options more detailed + * @author Daniel Faust + * @version 0.3 + */ +class OptionsDetailed : public QWidget +{ + Q_OBJECT +public: + /** + * Constructor + */ + OptionsDetailed( Config*, QWidget* parent=0, const char* name=0 ); + + /** + * Destructor + */ + virtual ~OptionsDetailed(); + + /** + * Return the current options + */ + ConversionOptions getCurrentOptions(); + + /** + * Set the current options + */ + void setCurrentOptions( const ConversionOptions& ); + + /** + * Refills the whole form (e.g. after a config change) + */ + void refill(); // TODO syncronize with optionsSimple + +private: + KComboBox* cFormat; + KComboBox* cQualityMode; + KIntSpinBox* iQuality; + KComboBox* cBitrateMode; + + QCheckBox* cBitrateRangeSwitch; + KIntSpinBox* iMinBitrate; + QLabel* lBitrateRangeTo; + KIntSpinBox* iMaxBitrate; + QLabel* lBitrateRangeUnit; + + QCheckBox* cSamplingrateSwitch; + KComboBox* cSamplingrate; + QLabel* lSamplingrateUnit; + QCheckBox* cChannelsSwitch; + KComboBox* cChannels; + QCheckBox* cReplayGain; + + KToolBarButton* pProfileSave; + + KLineEdit* lUserOptions; + + QWidget* normalOptions; + QWidget* advancedOptions; + + OutputDirectory* outputDirectory; + + Config* config; +// QString getQualityMode(); + + QString lastQualityMode; + + /** because we can't search within combo boxes, we need a seperate string lists, that we can search */ + QStringList sFormat; + QStringList sQualityMode; + QStringList sBitrateMode; + QStringList sChannels; + int formatIndex( const QString &string ); + int qualityModeIndex( const QString &string ); + int bitrateModeIndex( const QString &string ); + int channelsIndex( const QString &string ); + + int getQuality(); + bool getBitrateRangeEnabled(); + bool getSamplingrateEnabled(); + int getSamplingrate(); + bool getChannelsEnabled(); + QString getChannels(); + +private slots: + void formatChanged(); + void qualityModeChanged(); + void qualityChanged(); + void bitrateModeChanged(); + void bitrateRangeToggled(); + void samplingrateToggled(); + void channelsToggled(); + void saveProfile(); + void somethingChanged(); + +public: + QString getFormat(); + OutputDirectory::Mode getOutputDirectoryMode(); + QString getOutputDirectoryPath(); + void setFormat( const QString &format ); + void setQualityMode( const QString &qualityMode ); + void setQuality( int quality ); + void setBitrateMode( const QString &bitrateMode ); + void setBitrateRangeEnabled( bool enabled ); + void setMinBitrate( int bitrate ); + void setMaxBitrate( int bitrate ); + void setSamplingrateEnabled( bool enabled ); + void setSamplingrate( int sampleRate ); + void setSamplingrate( const QString &sampleRate ); + void setChannelsEnabled( bool enabled ); + void setChannels( const QString &channels ); + void setReplayGainEnabled( bool enabled ); + void setOutputDirectoryMode( OutputDirectory::Mode mode ); + void setOutputDirectoryPath( const QString &path ); + void setUserOptions( const QString &options ); + +public slots: + void toggleAdvancedOptions(); + +signals: + void optionsChanged(); +}; + +#endif // OPTIONSDETAILED_H diff --git a/src/optionseditor.cpp b/src/optionseditor.cpp new file mode 100755 index 0000000..efd9b1e --- /dev/null +++ b/src/optionseditor.cpp @@ -0,0 +1,729 @@ + +#include "optionseditor.h" +#include "options.h" +#include "tagengine.h" +#include "filelist.h" +#include "conversionoptions.h" +#include "outputdirectory.h" + +#include +#include +#include +#include + +#include +#include +#include +//#include +#include +#include +#include +#include + +// TODO add warning, when editing tags and converting to an unsupported file format + +OptionsEditor::OptionsEditor( TagEngine* _tagEngine, Config* _config, FileList* _fileList, QWidget* parent, const char* name, Page startPage ) + : KDialogBase( + IconList, + i18n("Options Editor"), + /*User2 | User1 |*/ Ok, + Ok, // default button + parent, + name, + false, // modal + true/*, // separator + i18n("Next"), + i18n("Previous")*/ + ) +{ + fileList = _fileList; + config = _config; + tagEngine = _tagEngine; + + // create an icon loader object for loading icons + KIconLoader* iconLoader = new KIconLoader(); + + resize( 400, 350 ); + // TODO move the dialog beside the main window + setIcon( iconLoader->loadIcon("view_text",KIcon::Small) ); + +// setButtonGuiItem( User2, KGuiItem(i18n("Previous"),iconLoader->loadIconSet("previous",KIcon::Small,16,true/*KDE3.5,false*/)) ); +// setButtonGuiItem( User1, KGuiItem(i18n("Next"),iconLoader->loadIconSet("next",KIcon::Small,16,true/*KDE3.5,false*/)) ); + setButtonGuiItem( Ok, KGuiItem(i18n("Close"),iconLoader->loadIconSet("exit",KIcon::Small,16,true/*KDE3.5,false*/)) ); + + //// options page //// + conversionOptions = addPage( i18n("Conversion"), i18n("Conversion options"), iconLoader->loadIcon("soundkonverter",KIcon::Desktop) ); + // the grid for all widgets in the main window + QGridLayout* conversionOptionsGridLayout = new QGridLayout( conversionOptions, 1, 1, 0, 6, "conversionOptionsGridLayout" ); + // generate the options input area + options = new Options( config, i18n("Choose your prefered output options and click on \"Close\"!"), conversionOptions, "options" ); + conversionOptionsGridLayout->addWidget( options, 0, 0 ); + connect( options, SIGNAL(optionsChanged()), + this, SLOT(optionsChanged()) + ); + conversionOptionsGridLayout->setRowStretch( 1, 1 ); + + lEditOptions = new QLabel( "", conversionOptions, "lEditOptions" ); + conversionOptionsGridLayout->addWidget( lEditOptions, 2, 0 ); + lEditOptions->setAlignment( Qt::AlignHCenter ); + lEditOptions->hide(); + pEditOptions = new KPushButton( i18n("Edit conversion options"), conversionOptions, "pEditOptions" ); + pEditOptions->setFixedWidth( pEditOptions->sizeHint().width() ); + conversionOptionsGridLayout->addWidget( pEditOptions, 3, 0, Qt::AlignHCenter ); + pEditOptions->hide(); + connect( pEditOptions, SIGNAL(clicked()), + this, SLOT(editOptionsClicked()) + ); + + //// tags page //// + tags = addPage( i18n("Tags"), i18n("Tags"), iconLoader->loadIcon("view_text",KIcon::Desktop) ); + // the grid for all widgets in the main window + QGridLayout* tagsGridLayout = new QGridLayout( tags, 1, 1, 0, 6, "tagsGridLayout" ); + + // add the inputs + // add a horizontal box layout for the title and track number + QHBoxLayout *titleBox = new QHBoxLayout( -1, "titleBox" ); + tagsGridLayout->addLayout( titleBox, 0, 1 ); + // and fill it up + lTitleLabel = new QLabel( i18n("Title:"), tags, "lTitleLabel" ); + tagsGridLayout->addWidget( lTitleLabel, 0, 0 ); + lTitle = new KLineEdit( tags, "lTitle" ); + titleBox->addWidget( lTitle ); + connect( lTitle, SIGNAL(textChanged(const QString&)), + this, SLOT(titleChanged(const QString&)) + ); + pTitleEdit = new KPushButton( " ", tags, "pTitleEdit" ); + pTitleEdit->setPixmap( iconLoader->loadIcon("kwrite",KIcon::Small) ); + pTitleEdit->setFixedSize( lTitle->sizeHint().height(), lTitle->sizeHint().height() ); + pTitleEdit->hide(); + titleBox->addWidget( pTitleEdit ); + connect( pTitleEdit, SIGNAL(clicked()), + this, SLOT(editTitleClicked()) + ); + lNumberLabel = new QLabel( i18n("Track No.:"), tags, "lNumberLabel" ); + titleBox->addWidget( lNumberLabel ); + iNumber = new KIntSpinBox( 0, 999, 1, 1, 10, tags, "iNumber" ); + titleBox->addWidget( iNumber ); + connect( iNumber, SIGNAL(valueChanged(int)), + this, SLOT(numberChanged(int)) + ); + pNumberEdit = new KPushButton( " ", tags, "pNumberEdit" ); + pNumberEdit->setPixmap( iconLoader->loadIcon("kwrite",KIcon::Small) ); + pNumberEdit->setFixedSize( iNumber->sizeHint().height(), iNumber->sizeHint().height() ); + pNumberEdit->hide(); + titleBox->addWidget( pNumberEdit ); + connect( pNumberEdit, SIGNAL(clicked()), + this, SLOT(editNumberClicked()) + ); + + // add a horizontal box layout for the artist and the composer + QHBoxLayout *artistBox = new QHBoxLayout( -1, "artistBox" ); + tagsGridLayout->addLayout( artistBox, 1, 1 ); + // and fill it up + lArtistLabel = new QLabel( i18n("Artist:"), tags, "lArtistLabel" ); + tagsGridLayout->addWidget( lArtistLabel, 1, 0 ); + lArtist = new KLineEdit( tags, "lArtist" ); + artistBox->addWidget( lArtist ); + connect( lArtist, SIGNAL(textChanged(const QString&)), + this, SLOT(artistChanged(const QString&)) + ); + pArtistEdit = new KPushButton( " ", tags, "pArtistEdit" ); + pArtistEdit->setPixmap( iconLoader->loadIcon("kwrite",KIcon::Small) ); + pArtistEdit->setFixedSize( lArtist->sizeHint().height(), lArtist->sizeHint().height() ); + pArtistEdit->hide(); + artistBox->addWidget( pArtistEdit ); + connect( pArtistEdit, SIGNAL(clicked()), + this, SLOT(editArtistClicked()) + ); + lComposerLabel = new QLabel( i18n("Composer:"), tags, "lComposerLabel" ); + artistBox->addWidget( lComposerLabel ); + lComposer = new KLineEdit( tags, "lComposer" ); + artistBox->addWidget( lComposer ); + connect( lComposer, SIGNAL(textChanged(const QString&)), + this, SLOT(composerChanged(const QString&)) + ); + pComposerEdit = new KPushButton( " ", tags, "pComposerEdit" ); + pComposerEdit->setPixmap( iconLoader->loadIcon("kwrite",KIcon::Small) ); + pComposerEdit->setFixedSize( lComposer->sizeHint().height(), lComposer->sizeHint().height() ); + pComposerEdit->hide(); + artistBox->addWidget( pComposerEdit ); + connect( pComposerEdit, SIGNAL(clicked()), + this, SLOT(editComposerClicked()) + ); + + // add a horizontal box layout for the album + QHBoxLayout *albumBox = new QHBoxLayout( -1, "albumBox" ); + tagsGridLayout->addLayout( albumBox, 2, 1 ); + // and fill it up + lAlbumLabel = new QLabel( i18n("Album:"), tags, "lAlbumLabel" ); + tagsGridLayout->addWidget( lAlbumLabel, 2, 0 ); + lAlbum = new KLineEdit( tags, "lAlbum" ); + albumBox->addWidget( lAlbum ); + connect( lAlbum, SIGNAL(textChanged(const QString&)), + this, SLOT(albumChanged(const QString&)) + ); + pAlbumEdit = new KPushButton( " ", tags, "pAlbumEdit" ); + pAlbumEdit->setPixmap( iconLoader->loadIcon("kwrite",KIcon::Small) ); + pAlbumEdit->setFixedSize( lAlbum->sizeHint().height(), lAlbum->sizeHint().height() ); + pAlbumEdit->hide(); + albumBox->addWidget( pAlbumEdit ); + connect( pAlbumEdit, SIGNAL(clicked()), + this, SLOT(editAlbumClicked()) + ); + + // add a horizontal box layout for the disc number, year and genre + QHBoxLayout *albumdataBox = new QHBoxLayout( -1, "albumdataBox" ); + tagsGridLayout->addLayout( albumdataBox, 3, 1 ); + // and fill it up + lDiscLabel = new QLabel( i18n("Disc No.:"), tags, "lDiscLabel" ); + tagsGridLayout->addWidget( lDiscLabel, 3, 0 ); + iDisc = new KIntSpinBox( 0, 99, 1, 1, 10, tags, "iDisc" ); + albumdataBox->addWidget( iDisc ); + connect( iDisc, SIGNAL(valueChanged(int)), + this, SLOT(discChanged(int)) + ); + pDiscEdit = new KPushButton( " ", tags, "pDiscEdit" ); + pDiscEdit->setPixmap( iconLoader->loadIcon("kwrite",KIcon::Small) ); + pDiscEdit->setFixedSize( iDisc->sizeHint().height(), iDisc->sizeHint().height() ); + pDiscEdit->hide(); + albumdataBox->addWidget( pDiscEdit ); + connect( pDiscEdit, SIGNAL(clicked()), + this, SLOT(editDiscClicked()) + ); + albumdataBox->addStretch(); + lYearLabel = new QLabel( i18n("Year:"), tags, "lYearLabel" ); + albumdataBox->addWidget( lYearLabel ); + iYear = new KIntSpinBox( 0, 99999, 1, QDate::currentDate().year(), 10, tags, "iYear" ); + albumdataBox->addWidget( iYear ); + connect( iYear, SIGNAL(valueChanged(int)), + this, SLOT(yearChanged(int)) + ); + pYearEdit = new KPushButton( " ", tags, "pYearEdit" ); + pYearEdit->setPixmap( iconLoader->loadIcon("kwrite",KIcon::Small) ); + pYearEdit->setFixedSize( iYear->sizeHint().height(), iYear->sizeHint().height() ); + pYearEdit->hide(); + albumdataBox->addWidget( pYearEdit ); + connect( pYearEdit, SIGNAL(clicked()), + this, SLOT(editYearClicked()) + ); + albumdataBox->addStretch(); + lGenreLabel = new QLabel( i18n("Genre:"), tags, "lGenreLabel" ); + albumdataBox->addWidget( lGenreLabel ); + cGenre = new KComboBox( true, tags, "cGenre" ); + cGenre->insertStringList( tagEngine->genreList ); + cGenre->setCurrentText( "" ); + KCompletion *cGenreCompletion = cGenre->completionObject(); + cGenreCompletion->insertItems( tagEngine->genreList ); + cGenreCompletion->setIgnoreCase( tags ); + albumdataBox->addWidget( cGenre ); + connect( cGenre, SIGNAL(textChanged(const QString&)), + this, SLOT(genreChanged(const QString&)) + ); + pGenreEdit = new KPushButton( " ", tags, "pGenreEdit" ); + pGenreEdit->setPixmap( iconLoader->loadIcon("kwrite",KIcon::Small) ); + pGenreEdit->setFixedSize( cGenre->sizeHint().height(), cGenre->sizeHint().height() ); + pGenreEdit->hide(); + albumdataBox->addWidget( pGenreEdit ); + connect( pGenreEdit, SIGNAL(clicked()), + this, SLOT(editGenreClicked()) + ); + + // add a horizontal box layout for the comment + QHBoxLayout *commentBox = new QHBoxLayout( -1, "commentBox" ); + tagsGridLayout->addLayout( commentBox, 4, 1 ); + // and fill it up + lCommentLabel = new QLabel( i18n("Comment:"), tags, "lCommentLabel" ); + tagsGridLayout->addWidget( lCommentLabel, 4, 0 ); + tComment = new KTextEdit( tags, "tComment" ); + commentBox->addWidget( tComment ); + connect( tComment, SIGNAL(textChanged()), + this, SLOT(commentChanged()) + ); + pCommentEdit = new KPushButton( " ", tags, "pCommentEdit" ); + pCommentEdit->setPixmap( iconLoader->loadIcon("kwrite",KIcon::Small) ); + pCommentEdit->setFixedSize( lTitle->sizeHint().height(), lTitle->sizeHint().height() ); + pCommentEdit->hide(); + commentBox->addWidget( pCommentEdit ); + connect( pCommentEdit, SIGNAL(clicked()), + this, SLOT(editCommentClicked()) + ); + tagsGridLayout->setRowStretch( 4, 1 ); + + lEditTags = new QLabel( "", tags, "lEditTags" ); + tagsGridLayout->addWidget( lEditTags, 5, 1 ); + lEditTags->setAlignment( Qt::AlignHCenter ); + lEditTags->hide(); + pEditTags = new KPushButton( i18n("Edit tags"), tags, "pEditTags" ); + pEditTags->setFixedWidth( pEditTags->sizeHint().width() ); + tagsGridLayout->addWidget( pEditTags, 6, 1, Qt::AlignHCenter ); + pEditTags->hide(); + connect( pEditTags, SIGNAL(clicked()), + this, SLOT(editTagsClicked()) + ); + + // delete the icon loader object + delete iconLoader; +} + +OptionsEditor::~OptionsEditor() +{} + +/*void OptionsEditor::moveWindow( int x, int y ) +{ + move( x, y ); +}*/ + +void OptionsEditor::setTagInputEnabled( bool enabled ) +{ + lTitleLabel->setEnabled( enabled ); + lTitle->setEnabled( enabled ); + pTitleEdit->hide(); + lNumberLabel->setEnabled( enabled ); + iNumber->setEnabled( enabled ); + pNumberEdit->hide(); + lArtistLabel->setEnabled( enabled ); + lArtist->setEnabled( enabled ); + pArtistEdit->hide(); + lComposerLabel->setEnabled( enabled ); + lComposer->setEnabled( enabled ); + pComposerEdit->hide(); + lAlbumLabel->setEnabled( enabled ); + lAlbum->setEnabled( enabled ); + pAlbumEdit->hide(); + lDiscLabel->setEnabled( enabled ); + iDisc->setEnabled( enabled ); + pDiscEdit->hide(); + lYearLabel->setEnabled( enabled ); + iYear->setEnabled( enabled ); + pYearEdit->hide(); + lGenreLabel->setEnabled( enabled ); + cGenre->setEnabled( enabled ); + pGenreEdit->hide(); + lCommentLabel->setEnabled( enabled ); + tComment->setEnabled( enabled ); + tComment->setReadOnly( !enabled ); + pCommentEdit->hide(); + + if( !enabled ) { + lTitle->setText( "" ); + iNumber->setValue( 0 ); + lArtist->setText( "" ); + lComposer->setText( "" ); + lAlbum->setText( "" ); + iDisc->setValue( 0 ); + iYear->setValue( 0 ); + cGenre->setCurrentText( "" ); + tComment->setText( "" ); + } +} + +void OptionsEditor::itemsSelected( QValueList items ) +{ + for( QValueList::Iterator it = items.begin(); it != items.end(); ) { + if( (*it)->converting || (*it) == 0 ) it = items.remove( it ); + else it++; + } + + selectedItems = items; + + if( items.count() == 0 ) { + setCaption( i18n("No file selected") ); + options->setEnabled( false ); + lEditOptions->hide(); + pEditOptions->hide(); + setTagInputEnabled( false ); + lEditTags->hide(); + pEditTags->hide(); + return; + } + + options->setEnabled( true ); + lEditOptions->hide(); + pEditOptions->hide(); + setTagInputEnabled( true ); + lEditTags->hide(); + pEditTags->hide(); + + if( items.count() == 1 ) { + setCaption( KURL::decode_string(items.first()->fileName).replace("%2f","/").replace("%%","%") ); + // HACK ...but seems to work... + // FIXME directory does get set properly + disconnect( options, SIGNAL(optionsChanged()), 0, 0 ); + options->setCurrentOptions( items.first()->options ); + connect( options, SIGNAL(optionsChanged()), + this, SLOT(optionsChanged()) + ); + if( items.first()->tags == 0 && !items.first()->local ) { + setTagInputEnabled( false ); + lEditTags->setText( i18n("The tags could not be read, because this file isn't a local one.\n" + "soundKonverter will try to read the tags, when it is about to convert the file.\n" + "If you want to edit the tags, you can hit the button below but then soundKonverter will not try\n" + "to read the tags.") ); + lEditTags->show(); + pEditTags->show(); + } + else if( items.first()->tags == 0 ) { + setTagInputEnabled( false ); + lEditTags->setText( i18n("Reading the tags of this file failed.\n" + "soundKonverter will try to read the tags a second time, when it is about to convert the file.\n" + "If you want to edit the tags, you can hit the button below but then soundKonverter will not try\n" + "to read the tags a second time.") ); + lEditTags->show(); + pEditTags->show(); + } + else { + lTitle->setText( items.first()->tags->title ); + iNumber->setValue( items.first()->tags->track ); + lArtist->setText( items.first()->tags->artist ); + lComposer->setText( items.first()->tags->composer ); + lAlbum->setText( items.first()->tags->album ); + iDisc->setValue( items.first()->tags->disc ); + iYear->setValue( items.first()->tags->year ); + cGenre->setCurrentText( items.first()->tags->genre ); + tComment->setText( items.first()->tags->comment ); + } + } + else { + setCaption( i18n("%1 Files").arg(items.count()) ); + QValueList::Iterator it = items.begin(); + ConversionOptions cOptions = (*it)->options; + QString title = ( (*it)->tags == 0 ) ? "" : (*it)->tags->title; + int number = ( (*it)->tags == 0 ) ? 0 : (*it)->tags->track; + QString artist = ( (*it)->tags == 0 ) ? "" : (*it)->tags->artist; + QString composer = ( (*it)->tags == 0 ) ? "" : (*it)->tags->composer; + QString album = ( (*it)->tags == 0 ) ? "" : (*it)->tags->album; + int disc = ( (*it)->tags == 0 ) ? 0 : (*it)->tags->disc; + int year = ( (*it)->tags == 0 ) ? 0 : (*it)->tags->year; + QString genre = ( (*it)->tags == 0 ) ? "" : (*it)->tags->genre; + QString comment = ( (*it)->tags == 0 ) ? "" : (*it)->tags->comment; + while( it != items.end() ) { + if( !cOptions.nearlyEqual((*it)->options) ) { + options->setEnabled( false ); + lEditOptions->setText( i18n("You have selected multiple files with different conversion options.\nYou can change the options of all files by hitting the button below.") ); + lEditOptions->show(); + pEditOptions->show(); + } + if( (*it)->tags == 0 ) { + setTagInputEnabled( false ); + lEditTags->setText( i18n("Reading the tags of one or more files failed.\n" + "soundKonverter will try to read the tags a second time, when it is about to convert the files.\n" + "If you want to edit the tags, you can hit the button below but then soundKonverter will not try\n" + "to read the tags a second time.") ); + lEditTags->show(); + pEditTags->show(); + it++; + continue; + } + if( title != (*it)->tags->title && lTitle->isEnabled() ) { + lTitle->setEnabled( false ); + lTitle->setText( "" ); + pTitleEdit->show(); + } + if( number != (*it)->tags->track && iNumber->isEnabled() ) { + iNumber->setEnabled( false ); + iNumber->setValue( 1 ); + pNumberEdit->show(); + } + if( artist != (*it)->tags->artist && lArtist->isEnabled() ) { + lArtist->setEnabled( false ); + lArtist->setText( "" ); + pArtistEdit->show(); + } + if( composer != (*it)->tags->composer && lComposer->isEnabled() ) { + lComposer->setEnabled( false ); + lComposer->setText( "" ); + pComposerEdit->show(); + } + if( album != (*it)->tags->album && lAlbum->isEnabled() ) { + lAlbum->setEnabled( false ); + lAlbum->setText( "" ); + pAlbumEdit->show(); + } + if( disc != (*it)->tags->disc && iDisc->isEnabled() ) { + iDisc->setEnabled( false ); + iDisc->setValue( 1 ); + pDiscEdit->show(); + } + if( year != (*it)->tags->year && iYear->isEnabled() ) { + iYear->setEnabled( false ); + iYear->setValue( QDate::currentDate().year() ); + pYearEdit->show(); + } + if( genre != (*it)->tags->genre && cGenre->isEnabled() ) { + cGenre->setEnabled( false ); + cGenre->setCurrentText( "" ); + pGenreEdit->show(); + } + if( comment != (*it)->tags->comment && tComment->isEnabled() ) { + tComment->setEnabled( false ); + tComment->setReadOnly( true ); + tComment->setText( "" ); + pCommentEdit->show(); + } + it++; + } + if( options->isEnabled() ) { + // HACK ...but seems to work... + // FIXME directory does get set properly + disconnect( options, SIGNAL(optionsChanged()), 0, 0 ); + options->setCurrentOptions( items.first()->options ); + connect( options, SIGNAL(optionsChanged()), + this, SLOT(optionsChanged()) + ); + } + if( lTitle->isEnabled() ) { + lTitle->setText( title ); + } + if( iNumber->isEnabled() ) { + iNumber->setValue( number ); + } + if( lArtist->isEnabled() ) { + lArtist->setText( artist ); + } + if( lComposer->isEnabled() ) { + lComposer->setText( composer ); + } + if( lAlbum->isEnabled() ) { + lAlbum->setText( album ); + } + if( iDisc->isEnabled() ) { + iDisc->setValue( disc ); + } + if( iYear->isEnabled() ) { + iYear->setValue( year ); + } + if( cGenre->isEnabled() ) { + cGenre->setCurrentText( genre ); + } + if( tComment->isEnabled() ) { + tComment->setText( comment ); + } + } +} + +void OptionsEditor::setPreviousEnabled( bool enabled ) +{ + enableButton( User2, enabled ); +} + +void OptionsEditor::setNextEnabled( bool enabled ) +{ + enableButton( User1, enabled ); +} + + +void OptionsEditor::optionsChanged() +{ + if( !options->isEnabled() ) return; + + QString filePathName; +// QString outputFilePathName; + + for( QValueList::Iterator it = selectedItems.begin(); it != selectedItems.end(); ++it ) { + filePathName = (*it)->options.filePathName; +// outputFilePathName = (*it)->options.outputFilePathName; + (*it)->options = options->getCurrentOptions(); + (*it)->options.filePathName = filePathName; +// (*it)->options.outputFilePathName = outputFilePathName; + //(*it)->updateOptionsCell(); + //(*it)->updateOutputCell(); + fileList->updateItem( *it ); + } +} + +void OptionsEditor::titleChanged( const QString& text ) +{ + if( !lTitle->isEnabled() ) return; + + for( QValueList::Iterator it = selectedItems.begin(); it != selectedItems.end(); ++it ) { + (*it)->tags->title = text; + //(*it)->updateOutputCell(); + fileList->updateItem( *it ); + } +} + +void OptionsEditor::numberChanged( int value ) +{ + if( !iNumber->isEnabled() ) return; + + for( QValueList::Iterator it = selectedItems.begin(); it != selectedItems.end(); ++it ) { + (*it)->tags->track = value; + //(*it)->updateOutputCell(); + fileList->updateItem( *it ); + } +} + +void OptionsEditor::artistChanged( const QString& text ) +{ + if( !lArtist->isEnabled() ) return; + + for( QValueList::Iterator it = selectedItems.begin(); it != selectedItems.end(); ++it ) { + (*it)->tags->artist = text; + //(*it)->updateOutputCell(); + fileList->updateItem( *it ); + } +} + +void OptionsEditor::composerChanged( const QString& text ) +{ + if( !lComposer->isEnabled() ) return; + + for( QValueList::Iterator it = selectedItems.begin(); it != selectedItems.end(); ++it ) { + (*it)->tags->composer = text; + //(*it)->updateOutputCell(); + fileList->updateItem( *it ); + } +} + +void OptionsEditor::albumChanged( const QString& text ) +{ + if( !lAlbum->isEnabled() ) return; + + for( QValueList::Iterator it = selectedItems.begin(); it != selectedItems.end(); ++it ) { + (*it)->tags->album = text; + //(*it)->updateOutputCell(); + fileList->updateItem( *it ); + } +} + +void OptionsEditor::discChanged( int value ) +{ + if( !iDisc->isEnabled() ) return; + + for( QValueList::Iterator it = selectedItems.begin(); it != selectedItems.end(); ++it ) { + (*it)->tags->disc = value; + //(*it)->updateOutputCell(); + fileList->updateItem( *it ); + } +} + +void OptionsEditor::yearChanged( int value ) +{ + if( !iYear->isEnabled() ) return; + + for( QValueList::Iterator it = selectedItems.begin(); it != selectedItems.end(); ++it ) { + (*it)->tags->year = value; + //(*it)->updateOutputCell(); + fileList->updateItem( *it ); + } +} + +void OptionsEditor::genreChanged( const QString& text ) +{ + if( !cGenre->isEnabled() ) return; + + for( QValueList::Iterator it = selectedItems.begin(); it != selectedItems.end(); ++it ) { + (*it)->tags->genre = text; + //(*it)->updateOutputCell(); + fileList->updateItem( *it ); + } +} + +void OptionsEditor::commentChanged() +{ + if( !tComment->isEnabled() ) return; + + QString text = tComment->text(); + + for( QValueList::Iterator it = selectedItems.begin(); it != selectedItems.end(); ++it ) { + (*it)->tags->comment = text; + //(*it)->updateOutputCell(); + fileList->updateItem( *it ); + } +} + + +void OptionsEditor::editTitleClicked() +{ + lTitle->setEnabled( true ); + lTitle->setFocus(); + pTitleEdit->hide(); + titleChanged( lTitle->text() ); +} + +void OptionsEditor::editNumberClicked() +{ + iNumber->setEnabled( true ); + iNumber->setFocus(); + pNumberEdit->hide(); + numberChanged( iNumber->value() ); +} + +void OptionsEditor::editArtistClicked() +{ + lArtist->setEnabled( true ); + lArtist->setFocus(); + pArtistEdit->hide(); + artistChanged( lArtist->text() ); +} + +void OptionsEditor::editComposerClicked() +{ + lComposer->setEnabled( true ); + lComposer->setFocus(); + pComposerEdit->hide(); + composerChanged( lComposer->text() ); +} + +void OptionsEditor::editAlbumClicked() +{ + lAlbum->setEnabled( true ); + lAlbum->setFocus(); + pAlbumEdit->hide(); + albumChanged( lAlbum->text() ); +} + +void OptionsEditor::editDiscClicked() +{ + iDisc->setEnabled( true ); + iDisc->setFocus(); + pDiscEdit->hide(); + discChanged( iDisc->value() ); +} + +void OptionsEditor::editYearClicked() +{ + iYear->setEnabled( true ); + iYear->setFocus(); + pYearEdit->hide(); + yearChanged( iYear->value() ); +} + +void OptionsEditor::editGenreClicked() +{ + cGenre->setEnabled( true ); + cGenre->setFocus(); + pGenreEdit->hide(); + genreChanged( cGenre->currentText() ); +} + +void OptionsEditor::editCommentClicked() +{ + tComment->setEnabled( true ); + tComment->setReadOnly( false ); + tComment->setFocus(); + pCommentEdit->hide(); + commentChanged(); +} + + +void OptionsEditor::editOptionsClicked() +{ + // TODO set default / first profile (use config values) + options->setProfile( i18n("Medium") ); + options->setFormat( "ogg" ); + options->setEnabled( true ); + lEditOptions->hide(); + pEditOptions->hide(); + optionsChanged(); +} + +void OptionsEditor::editTagsClicked() +{ + for( QValueList::Iterator it = selectedItems.begin(); it != selectedItems.end(); ++it ) { + (*it)->tags = new TagData(); + } + + itemsSelected( selectedItems ); +} + diff --git a/src/optionseditor.h b/src/optionseditor.h new file mode 100755 index 0000000..d509774 --- /dev/null +++ b/src/optionseditor.h @@ -0,0 +1,146 @@ + + +#ifndef OPTIONSEDITOR_H +#define OPTIONSEDITOR_H + +#include +//#include + +class Options; +class Config; +class TagEngine; +class FileList; +class FileListItem; + +class KLineEdit; +class KComboBox; +class KIntSpinBox; +class KTextEdit; +class KPushButton; +class QLabel; + +/** + * @short The options edit dialog that can be opened through the file list's context menu + * @author Daniel Faust + * @version 0.3 + */ +class OptionsEditor : public KDialogBase +{ + Q_OBJECT +public: + enum Page { + OptionsPage, + TagsPage + }; + + /** + * Constructor + */ + OptionsEditor( TagEngine*, Config*, FileList* _fileList, QWidget* parent = 0, const char* name=0, Page startPage = OptionsPage ); + + /** + * Destructor + */ + virtual ~OptionsEditor(); + + FileListItem* selectedItem(); + +private: + FileList* fileList; + Config* config; + TagEngine* tagEngine; + + QFrame* conversionOptions; + QFrame* tags; + + /** The widget, where we can set our output options */ + Options* options; + + /** A lineedit for entering the title of track */ + QLabel* lTitleLabel; + KLineEdit* lTitle; + KPushButton* pTitleEdit; + /** A spinbox for entering or selecting the track number */ + QLabel* lNumberLabel; + KIntSpinBox* iNumber; + KPushButton* pNumberEdit; + /** A lineedit for entering the artist of a track */ + QLabel* lArtistLabel; + KLineEdit* lArtist; + KPushButton* pArtistEdit; + /** A lineedit for entering the composer of a track */ + QLabel* lComposerLabel; + KLineEdit* lComposer; + KPushButton* pComposerEdit; + /** A lineedit for entering the album name */ + QLabel* lAlbumLabel; + KLineEdit* lAlbum; + KPushButton* pAlbumEdit; + /** A spinbox for entering or selecting the disc number */ + QLabel* lDiscLabel; + KIntSpinBox* iDisc; + KPushButton* pDiscEdit; + /** A spinbox for entering or selecting the year of the album */ + QLabel* lYearLabel; + KIntSpinBox* iYear; + KPushButton* pYearEdit; + /** A combobox for entering or selecting the genre of the album */ + QLabel* lGenreLabel; + KComboBox* cGenre; + KPushButton* pGenreEdit; + /** A textedit for entering a comment for a track */ + QLabel* lCommentLabel; + KTextEdit* tComment; + KPushButton* pCommentEdit; + + /** When hitting this button, the options lock (when multiple files are selected) will be deactivated */ + QLabel* lEditOptions; + KPushButton* pEditOptions; + + /** When hitting this button, the tag lock (when reading tags failed) will be deactivated */ + QLabel* lEditTags; + KPushButton* pEditTags; + + //FileListItem* currentItem; + QValueList selectedItems; + + void setTagInputEnabled( bool enabled ); + +private slots: + void optionsChanged(); + + void editTitleClicked(); + void editNumberClicked(); + void editArtistClicked(); + void editComposerClicked(); + void editAlbumClicked(); + void editDiscClicked(); + void editYearClicked(); + void editGenreClicked(); + void editCommentClicked(); + + void titleChanged( const QString& text ); + void numberChanged( int value ); + void artistChanged( const QString& text ); + void composerChanged( const QString& text ); + void albumChanged( const QString& text ); + void discChanged( int value ); + void yearChanged( int value ); + void genreChanged( const QString& text ); + void commentChanged(); + + void editOptionsClicked(); + void editTagsClicked(); + +public slots: + void itemsSelected( QValueList ); + void setPreviousEnabled( bool ); + void setNextEnabled( bool ); + //void moveWindow( int x, int y ); + +signals: + void previousItem(); + void nextItem(); +}; + +#endif // OPTIONSEDITOR_H diff --git a/src/optionsrequester.cpp b/src/optionsrequester.cpp new file mode 100755 index 0000000..3fc90b4 --- /dev/null +++ b/src/optionsrequester.cpp @@ -0,0 +1,98 @@ + +#include "optionsrequester.h" +#include "options.h" +#include "config.h" + +#include +#include +#include + +#include +#include +#include + + +OptionsRequester::OptionsRequester( Config* config, QStringList list, QWidget *parent, const char *name, bool modal, WFlags f ) + : KDialog( parent, name, modal, f ) +{ + setCaption( i18n("Choose output options") ); + + files = list; + int row = 1; + + // create an icon loader object for loading icons + KIconLoader* iconLoader = new KIconLoader(); + + QGridLayout *grid = new QGridLayout( this, 2, 1, 11, 6 ); + + options = new Options( config, i18n("Click on \"Ok\" to add the files to the list in the main window!"), this, "options" ); + grid->addWidget( options, 0, 0 ); + + QStringList::Iterator it = files.begin(); + while( it != files.end() ) + { + QString sFormat = *it; + int i = sFormat.findRev( '.' ); + sFormat.remove( 0, i + 1 ); + sFormat.lower(); + + if( sFormat == "wav" ) // FIXME use mime types + { + QHBoxLayout *warningBox = new QHBoxLayout(); + grid->addLayout( warningBox, 1, 0 ); + QLabel* lWarning = new QLabel( i18n("Warning: If you select \"wav\" as output format, your wav files will not be added to the list."), this, "lWarning" ); + warningBox->addWidget( lWarning ); + row++; + break; + } + it++; + } + + QHBoxLayout* buttonBox = new QHBoxLayout(); + grid->addLayout( buttonBox, row, 0 ); + + buttonBox->addStretch(); + + pCancel = new KPushButton( iconLoader->loadIcon("exit",KIcon::Small), i18n("Cancel"), this, "pCancel" ); + buttonBox->addWidget( pCancel ); + + pOk = new KPushButton( iconLoader->loadIcon("apply",KIcon::Small), i18n("Ok"), this, "pOk" ); + buttonBox->addWidget( pOk ); + + connect( pCancel, SIGNAL(clicked()), + this, SLOT(reject()) + ); + connect( pOk, SIGNAL(clicked()), + this, SLOT(okClicked()) + ); + + // delete the icon loader object + delete iconLoader; +} + +OptionsRequester::~OptionsRequester() +{} + +void OptionsRequester::okClicked() +{ + emit setCurrentOptions( options->getCurrentOptions() ); + emit addFiles( files ); + accept(); +} + +void OptionsRequester::setProfile( const QString& profile ) +{ + options->setProfile( profile ); +} + +void OptionsRequester::setFormat( const QString& format ) +{ + options->setFormat( format ); +} + +void OptionsRequester::setOutputDirectory( const QString& directory ) +{ + options->setOutputDirectory( directory ); +} + + diff --git a/src/optionsrequester.h b/src/optionsrequester.h new file mode 100755 index 0000000..594e955 --- /dev/null +++ b/src/optionsrequester.h @@ -0,0 +1,54 @@ + + +#ifndef OPTIONSREQUESTER_H +#define OPTIONSREQUESTER_H + +#include + +#include "conversionoptions.h" + +class Options; +class Config; +class QStringList; +class KPushButton; + +/** + * @short Shows an input dialog for selecting conversion options + * @author Daniel Faust + * @version 0.3 + */ +class OptionsRequester : public KDialog +{ + Q_OBJECT +public: + /** + * Default Constructor + */ + OptionsRequester( Config*, QStringList list, QWidget *parent=0, const char *name=0, bool modal=true, WFlags f=0 ); + + /** + * Default Destructor + */ + virtual ~OptionsRequester(); + + void setProfile( const QString& profile ); + void setFormat( const QString& format ); + void setOutputDirectory( const QString& directory ); + +private slots: + void okClicked(); + +signals: + void setCurrentOptions( const ConversionOptions& ); + void addFiles( QStringList ); + +private: + KPushButton* pOk; + KPushButton* pCancel; + QStringList files; + + Options* options; +}; + +#endif // OPTIONSREQUESTER_H + diff --git a/src/optionssimple.cpp b/src/optionssimple.cpp new file mode 100755 index 0000000..47b431f --- /dev/null +++ b/src/optionssimple.cpp @@ -0,0 +1,574 @@ + +#include "optionssimple.h" +#include "config.h" +#include "convertpluginloader.h" +#include "optionsdetailed.h" + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +//#include +#include + + +// FIXME when changing the output directory, check if the profile is a user defined and set it to 'User defined', if it is + +// TODO hide lossless/hybrid/etc. when not available +OptionsSimple::OptionsSimple( Config* _config, OptionsDetailed* _optionsDetailed, const QString &text, QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + config = _config; + optionsDetailed = _optionsDetailed; + + // create an icon loader object for loading icons + KIconLoader* iconLoader = new KIconLoader(); + + QGridLayout *grid = new QGridLayout( this, 3, 1, 6, 3 ); + + QHBoxLayout *topBox = new QHBoxLayout( ); + grid->addLayout( topBox, 0, 0 ); + + QLabel *lQuality = new QLabel( i18n("Quality")+":", this, "lQuality" ); + topBox->addWidget( lQuality, 0, Qt::AlignVCenter ); + cProfile = new KComboBox( this, "cProfile" ); + sProfile += i18n("Very low"); + sProfile += i18n("Low"); + sProfile += i18n("Medium"); + sProfile += i18n("High"); + sProfile += i18n("Very high"); + sProfile += i18n("Lossless"); + sProfile += i18n("Hybrid"); + sProfile += config->getAllProfiles(); + sProfile.remove( i18n("Last used") ); + sProfile.remove( "Last used" ); + sProfile += i18n("User defined"); + cProfile->insertStringList( sProfile ); + topBox->addWidget( cProfile, 0, Qt::AlignVCenter ); + connect( cProfile, SIGNAL(activated(int)), + this, SLOT(profileChanged()) + ); + connect( cProfile, SIGNAL(activated(int)), + this, SLOT(somethingChanged()) + ); + topBox->addSpacing( 3 ); + //pProfileRemove = new KToolBarButton( "editdelete", 1002, this, "pProfileRemove" ); + pProfileRemove = new KPushButton( iconLoader->loadIcon("editdelete",KIcon::Small), i18n("Remove"), this, "pProfileRemove" ); + pProfileRemove->hide(); + QToolTip::add( pProfileRemove, i18n("Remove the selected profile") ); + topBox->addWidget( pProfileRemove, 0, Qt::AlignVCenter ); + connect( pProfileRemove, SIGNAL(clicked()), + this, SLOT(profileRemove()) + ); + //pProfileInfo = new KToolBarButton( "messagebox_info", 1110, this, "pProfileInfo" ); + pProfileInfo = new KPushButton( iconLoader->loadIcon("messagebox_info",KIcon::Small), i18n("Info"), this, "pProfileInfo" ); + QToolTip::add( pProfileInfo, i18n("Information about the selected profile") ); + topBox->addWidget( pProfileInfo, 0, Qt::AlignVCenter ); + connect( pProfileInfo, SIGNAL(clicked()), + this, SLOT(profileInfo()) + ); + topBox->addSpacing( 18 ); + + QLabel *lFormat = new QLabel( i18n("Output format")+":", this, "lFormat" ); + topBox->addWidget( lFormat, 0, Qt::AlignVCenter ); + cFormat = new KComboBox( this, "cFormat" ); + topBox->addWidget( cFormat, 0, Qt::AlignVCenter ); + connect( cFormat, SIGNAL(activated(int)), + this, SLOT(formatChanged()) + ); + connect( cFormat, SIGNAL(activated(int)), + this, SLOT(somethingChanged()) + ); + topBox->addSpacing( 3 ); + //pFormatInfo = new KToolBarButton( "messagebox_info", 1111, this, "pFormatInfo" ); + pFormatInfo = new KPushButton( iconLoader->loadIcon("messagebox_info",KIcon::Small), i18n("Info"), this, "pFormatInfo" ); + QToolTip::add( pFormatInfo, i18n("Information about the selected file format") ); + topBox->addWidget( pFormatInfo, 0, Qt::AlignVCenter ); + connect( pFormatInfo, SIGNAL(clicked()), + this, SLOT(formatInfo()) + ); + topBox->addStretch( ); + + QHBoxLayout *middleBox = new QHBoxLayout( ); + grid->addLayout( middleBox, 1, 0 ); + + outputDirectory = new OutputDirectory( config, this, "outputDirectory" ); + middleBox->addWidget( outputDirectory, 0, Qt::AlignVCenter ); + connect( outputDirectory, SIGNAL(modeChanged(OutputDirectory::Mode)), + this, SLOT(outputDirectoryModeChanged(OutputDirectory::Mode)) + ); + connect( outputDirectory, SIGNAL(directoryChanged(const QString&)), + this, SLOT(outputDirectoryPathChanged(const QString&)) + ); + connect( outputDirectory, SIGNAL(modeChanged(OutputDirectory::Mode)), + this, SLOT(somethingChanged()) + ); + connect( outputDirectory, SIGNAL(directoryChanged(const QString&)), + this, SLOT(somethingChanged()) + ); + + QHBoxLayout *bottomBox = new QHBoxLayout( ); + grid->addLayout( bottomBox, 2, 0 ); + + QLabel *lInfo = new QLabel( text, this, "lInfo" ); + lInfo->setFixedHeight( cProfile->height() ); + bottomBox->addWidget( lInfo, 0, Qt::AlignVCenter | Qt::AlignLeft ); + + // delete the icon loader object + delete iconLoader; +} + + +OptionsSimple::~OptionsSimple() +{ +} + +int OptionsSimple::profileIndex( const QString &string ) +{ + QString profile = string; + if( profile == "Very low" ) profile = i18n("Very low"); + else if( profile == "Low" ) profile = i18n("Low"); + else if( profile == "Medium" ) profile = i18n("Medium"); + else if( profile == "High" ) profile = i18n("High"); + else if( profile == "Very high" ) profile = i18n("Very high"); + else if( profile == "Lossless" ) profile = i18n("Lossless"); + else if( profile == "Hybrid" ) profile = i18n("Hybrid"); + else if( profile == "User defined" ) profile = i18n("User defined"); + return sProfile.findIndex( profile ); +} + +int OptionsSimple::formatIndex( const QString &string ) +{ + return sFormat.findIndex( string ); +} + +void OptionsSimple::profileInfo() +{ + QString sProfileString = cProfile->currentText(); + + if( sProfileString == i18n("Very low") ) { + KMessageBox::information( this, + i18n("This produces sound files of a very low quality.\nThat can be useful, if you have a mobile device, where your memory cell is limited. It is not recommended to save your music in this quality without a copy with higher quality.\nIt can also be used to save audio files with voices."), + i18n("Profile")+": "+sProfileString ); + } + else if( sProfileString == i18n("Low") ) { + KMessageBox::information( this, + i18n("This produces sound files of a low quality.\nThat can be useful if you habe a mobile device where your memory cell is limited. It is not recommended to save your music in this quality without a copy with higher quality."), + i18n("Profile")+": "+sProfileString ); + } + else if( sProfileString == i18n("Medium") ) { + KMessageBox::information( this, + i18n("This produces sound files of a medium quality.\nIf your disc space is limited, you can use this to save your music."), + i18n("Profile")+": "+sProfileString ); + } + else if( sProfileString == i18n("High") ) { + KMessageBox::information( this, + i18n("This produces sound files of a high quality.\nIf you have enough disc space available, you can use this to save your music."), + i18n("Profile")+": "+sProfileString ); + } + else if( sProfileString == i18n("Very high") ) { + KMessageBox::information( this, + i18n("This produces sound files of a very high quality.\nYou should only use this, if you are a quality freak and have enough disc space available."), + i18n("Profile")+": "+sProfileString ); + } + else if( sProfileString == i18n("Lossless") ) { + KMessageBox::information( this, + i18n("This produces files, that have exact the same quality as the input files.\nThis files are very big and definitely only for quality freaks."), + i18n("Profile")+": "+sProfileString ); + } + else if( sProfileString == i18n("Hybrid") ) { + KMessageBox::information( this, + i18n("This produces two files. One lossy compressed playable file and one correction file.\nBoth files together result in a file that is equivalent to the input file."), + i18n("Profile")+": "+sProfileString ); + } + else if( sProfileString == i18n("User defined") ) { + KMessageBox::information( this, + i18n("You can define your own profile in the \"detailed\" tab."), + i18n("Profile")+": "+sProfileString ); + } +// else { // the info button is hidden when showing user defined profiles +// KMessageBox::error( this, +// i18n("This is a user defined profile."), +// i18n("Profile")+": "+sProfileString ); +// } +} + +void OptionsSimple::profileRemove() +{ + int ret = KMessageBox::questionYesNo( this, + i18n("Do you really want to remove the profile: %1").arg(cProfile->currentText()), + i18n("Remove profile?") ); + if( ret != KMessageBox::Yes ) return; + + config->removeProfile( cProfile->currentText() ); + + sProfile.clear(); + cProfile->clear(); + sProfile += i18n("Very low"); + sProfile += i18n("Low"); + sProfile += i18n("Medium"); + sProfile += i18n("High"); + sProfile += i18n("Very high"); + sProfile += i18n("Lossless"); + sProfile += i18n("Hybrid"); + sProfile += config->getAllProfiles(); + sProfile.remove( i18n("Last used") ); + sProfile.remove( "Last used" ); + sProfile += i18n("User defined"); + cProfile->insertStringList( sProfile ); + profileChanged(); +} + +void OptionsSimple::formatInfo() +{ + QString format = cFormat->currentText(); + + if( format == "wav" ) { + KMessageBox::information( this, + i18n("

Wave is a file format, that doesn't compress it's audio data.

\n

So the quality is very high, but the file size is enormous. It is widely spread and should work with every audio player.

\nhttp://en.wikipedia.org/wiki/Wav"), + i18n("File format")+": " + format, + QString::null, KMessageBox::Notify | KMessageBox::AllowLink ); + return; + } + else { + KMessageBox::information( this, + config->getFormatDescription(format), + i18n("File format")+": " + format, + QString::null, KMessageBox::Notify | KMessageBox::AllowLink ); + } +} + +void OptionsSimple::profileChanged() +{ + QString last; + + ConversionOptions options = config->getProfile( cProfile->currentText() ); + if( !options.encodingOptions.sFormat.isEmpty() ) { + pProfileRemove->show(); + pProfileInfo->hide(); + last = cFormat->currentText(); + cFormat->clear(); + sFormat = options.encodingOptions.sFormat; + cFormat->insertStringList( sFormat ); + cFormat->setCurrentItem( formatIndex(last) ); + outputDirectory->setMode( options.outputOptions.mode ); + outputDirectory->setDirectory( options.outputOptions.directory ); + optionsDetailed->setCurrentOptions( options ); + return; + } + + pProfileRemove->hide(); + pProfileInfo->show(); + + if( cProfile->currentText() == i18n("Very low") ) { + last = cFormat->currentText(); + cFormat->clear(); + sFormat = config->allLossyEncodableFormats(); + cFormat->insertStringList( sFormat ); + cFormat->setCurrentItem( formatIndex(last) ); + formatChanged(); + ConvertPlugin* plugin = config->encoderForFormat( cFormat->currentText() ); + if( plugin == 0 ) { + // FIXME error handling + //kdDebug() << "NULL POINTER: `" << "OptionsSimple::profileChanged() / Very low" << "'" << endl; + return; + } + if( plugin->enc.lossy.quality.enabled ) { + optionsDetailed->setQualityMode( i18n("Quality") ); + optionsDetailed->setQuality( 20 ); + } + else if( plugin->enc.lossy.bitrate.abr.enabled || plugin->enc.lossy.bitrate.cbr.enabled) { + optionsDetailed->setQualityMode( i18n("Bitrate") ); + optionsDetailed->setQuality( 64 ); + } + optionsDetailed->setBitrateRangeEnabled( false ); + optionsDetailed->setSamplingrateEnabled( true ); + optionsDetailed->setSamplingrate( 22050 ); + optionsDetailed->setChannelsEnabled( true ); + optionsDetailed->setChannels( i18n("Mono") ); + optionsDetailed->setReplayGainEnabled( true ); + optionsDetailed->setUserOptions( config->binaries[plugin->enc.bin] + " " + plugin->enc.in_out_files ); + } + else if( cProfile->currentText() == i18n("Low") ) { + last = cFormat->currentText(); + cFormat->clear(); + sFormat = config->allLossyEncodableFormats(); + cFormat->insertStringList( sFormat ); + cFormat->setCurrentItem( formatIndex(last) ); + formatChanged(); + ConvertPlugin* plugin = config->encoderForFormat( cFormat->currentText() ); + if( plugin == 0 ) { + // FIXME error handling + //kdDebug() << "NULL POINTER: `" << "OptionsSimple::profileChanged() / Low" << "'" << endl; + return; + } + if( plugin->enc.lossy.quality.enabled ) { + optionsDetailed->setQualityMode( i18n("Quality") ); + optionsDetailed->setQuality( 30 ); + } + else if( plugin->enc.lossy.bitrate.abr.enabled || plugin->enc.lossy.bitrate.cbr.enabled ) { + optionsDetailed->setQualityMode( i18n("Bitrate") ); + optionsDetailed->setQuality( 96 ); + } + optionsDetailed->setBitrateRangeEnabled( false ); + optionsDetailed->setSamplingrateEnabled( true ); + optionsDetailed->setSamplingrate( 22050 ); + optionsDetailed->setChannelsEnabled( false ); + optionsDetailed->setReplayGainEnabled( true ); + optionsDetailed->setUserOptions( config->binaries[plugin->enc.bin] + " " + plugin->enc.in_out_files ); + } + else if( cProfile->currentText() == i18n("Medium") ) { + last = cFormat->currentText(); + cFormat->clear(); + sFormat = config->allLossyEncodableFormats(); + cFormat->insertStringList( sFormat ); + cFormat->setCurrentItem( formatIndex(last) ); + formatChanged(); + ConvertPlugin* plugin = config->encoderForFormat( cFormat->currentText() ); + if( plugin == 0 ) { + // FIXME error handling + //kdDebug() << "NULL POINTER: `" << "OptionsSimple::profileChanged() / Medium" << "'" << endl; + return; + } + if( plugin->enc.lossy.quality.enabled ) { + optionsDetailed->setQualityMode( i18n("Quality") ); + optionsDetailed->setQuality( 40 ); + } + else if( plugin->enc.lossy.bitrate.abr.enabled || plugin->enc.lossy.bitrate.cbr.enabled ) { + optionsDetailed->setQualityMode( i18n("Bitrate") ); + optionsDetailed->setQuality( 192 ); + } + optionsDetailed->setBitrateRangeEnabled( false ); + optionsDetailed->setSamplingrateEnabled( false ); + optionsDetailed->setChannelsEnabled( false ); + optionsDetailed->setReplayGainEnabled( true ); + optionsDetailed->setUserOptions( config->binaries[plugin->enc.bin] + " " + plugin->enc.in_out_files ); + } + else if( cProfile->currentText() == i18n("High") ) { + last = cFormat->currentText(); + cFormat->clear(); + sFormat = config->allLossyEncodableFormats(); + cFormat->insertStringList( sFormat ); + cFormat->setCurrentItem( formatIndex(last) ); + formatChanged(); + ConvertPlugin* plugin = config->encoderForFormat( cFormat->currentText() ); + if( plugin == 0 ) { + // FIXME error handling + //kdDebug() << "NULL POINTER: `" << "OptionsSimple::profileChanged() / High" << "'" << endl; + return; + } + if( plugin->enc.lossy.quality.enabled ) { + optionsDetailed->setQualityMode( i18n("Quality") ); + optionsDetailed->setQuality( 50 ); + } + else if( plugin->enc.lossy.bitrate.abr.enabled || plugin->enc.lossy.bitrate.cbr.enabled ) { + optionsDetailed->setQualityMode( i18n("Bitrate") ); + optionsDetailed->setQuality( 240 ); + } + optionsDetailed->setBitrateRangeEnabled( false ); + optionsDetailed->setSamplingrateEnabled( false ); + optionsDetailed->setChannelsEnabled( false ); + optionsDetailed->setReplayGainEnabled( true ); + optionsDetailed->setUserOptions( config->binaries[plugin->enc.bin] + " " + plugin->enc.in_out_files ); + } + else if( cProfile->currentText() == i18n("Very high") ) { + last = cFormat->currentText(); + cFormat->clear(); + sFormat = config->allLossyEncodableFormats(); + cFormat->insertStringList( sFormat ); + cFormat->setCurrentItem( formatIndex(last) ); + formatChanged(); + ConvertPlugin* plugin = config->encoderForFormat( cFormat->currentText() ); + if( plugin == 0 ) { + // FIXME error handling + //kdDebug() << "NULL POINTER: `" << "OptionsSimple::profileChanged() / Very high" << "'" << endl; + return; + } + if( plugin->enc.lossy.quality.enabled ) { + optionsDetailed->setQualityMode( i18n("Quality") ); + optionsDetailed->setQuality( 60 ); + } + else if( plugin->enc.lossy.bitrate.abr.enabled || plugin->enc.lossy.bitrate.cbr.enabled ) { + optionsDetailed->setQualityMode( i18n("Bitrate") ); + optionsDetailed->setQuality( 320 ); + } + optionsDetailed->setBitrateRangeEnabled( false ); + optionsDetailed->setSamplingrateEnabled( false ); + optionsDetailed->setChannelsEnabled( false ); + optionsDetailed->setReplayGainEnabled( true ); + optionsDetailed->setUserOptions( config->binaries[plugin->enc.bin] + " " + plugin->enc.in_out_files ); + } + else if( cProfile->currentText() == i18n("Lossless") ) { + last = cFormat->currentText(); + cFormat->clear(); + sFormat = config->allLosslessEncodableFormats(); + sFormat += "wav"; + cFormat->insertStringList( sFormat ); + cFormat->setCurrentItem( formatIndex(last) ); + formatChanged(); + optionsDetailed->setReplayGainEnabled( true ); + ConvertPlugin* plugin = config->encoderForFormat( cFormat->currentText() ); + if( plugin != 0 ) { + optionsDetailed->setUserOptions( config->binaries[plugin->enc.bin] + " " + plugin->enc.in_out_files ); + } + } + else if( cProfile->currentText() == i18n("Hybrid")/* || cProfile->currentText() == "Hybrid"*/ ) { + last = cFormat->currentText(); + cFormat->clear(); + sFormat = config->allHybridEncodableFormats(); + cFormat->insertStringList( sFormat ); + cFormat->setCurrentItem( formatIndex(last) ); + formatChanged(); + optionsDetailed->setReplayGainEnabled( true ); + ConvertPlugin* plugin = config->encoderForFormat( cFormat->currentText() ); + optionsDetailed->setQualityMode( i18n("Hybrid") ); + if( plugin != 0 ) { + optionsDetailed->setUserOptions( config->binaries[plugin->enc.bin] + " " + plugin->enc.in_out_files ); + } + } + else if( cProfile->currentText() == i18n("User defined") ) { + last = cFormat->currentText(); + cFormat->clear(); + sFormat = config->allEncodableFormats(); + sFormat += "wav"; + cFormat->insertStringList( sFormat ); + cFormat->setCurrentItem( formatIndex(last) ); + formatChanged(); + } +} + +void OptionsSimple::formatChanged() +{ + optionsDetailed->setFormat( cFormat->currentText() ); +} + +void OptionsSimple::outputDirectoryModeChanged( OutputDirectory::Mode mode ) +{ + optionsDetailed->setOutputDirectoryMode( mode ); + if( cProfile->currentText() != i18n("User defined") && config->getAllProfiles().findIndex(cProfile->currentText()) != -1 ) { + ConversionOptions options = config->getProfile( cProfile->currentText() ); +// if( options.encodingOptions.sFormat.isEmpty() ) return; + if( outputDirectory->mode() != options.outputOptions.mode || outputDirectory->directory() != options.outputOptions.directory ) { + cProfile->setCurrentItem( profileIndex(i18n("User defined")) ); // NOTE not refill() ? + profileChanged(); + } +// refill(); + } +} + +void OptionsSimple::outputDirectoryPathChanged( const QString& path ) +{ + optionsDetailed->setOutputDirectoryPath( path ); + if( cProfile->currentText() != i18n("User defined") && config->getAllProfiles().findIndex(cProfile->currentText()) != -1 ) { + ConversionOptions options = config->getProfile( cProfile->currentText() ); +// if( options.encodingOptions.sFormat.isEmpty() ) return; + if( outputDirectory->mode() != options.outputOptions.mode || outputDirectory->directory() != options.outputOptions.directory ) { + cProfile->setCurrentItem( profileIndex(i18n("User defined")) ); // NOTE not refill() ? + profileChanged(); + } +// refill(); + } +} + +void OptionsSimple::setCurrentProfile( const QString& profile ) +{ + // TODO check profile (and don't change, if not available) + cProfile->setCurrentItem( profileIndex(profile) ); + profileChanged(); +} + +void OptionsSimple::setCurrentFormat( const QString& format ) +{ + cFormat->setCurrentItem( formatIndex(format) ); + formatChanged(); +} + +// TODO check for errors +void OptionsSimple::setCurrentOutputDirectory( const QString& directory ) +{ + outputDirectory->setMode( OutputDirectory::Specify ); + outputDirectory->setDirectory( directory ); + optionsDetailed->setOutputDirectoryMode( OutputDirectory::Specify ); + optionsDetailed->setOutputDirectoryPath( directory ); +} + +void OptionsSimple::somethingChanged() +{ + emit optionsChanged(); +} + +void OptionsSimple::refill() +{ + sProfile.clear(); + cProfile->clear(); + sProfile += i18n("Very low"); + sProfile += i18n("Low"); + sProfile += i18n("Medium"); + sProfile += i18n("High"); + sProfile += i18n("Very high"); + sProfile += i18n("Lossless"); + sProfile += i18n("Hybrid"); + sProfile += config->getAllProfiles(); + sProfile.remove( i18n("Last used") ); + sProfile.remove( "Last used" ); + sProfile += i18n("User defined"); + cProfile->insertStringList( sProfile ); + + cProfile->setCurrentItem( profileIndex(config->getProfileName(optionsDetailed->getCurrentOptions())) ); + + if( cProfile->currentText() == i18n("Very low") || cProfile->currentText() == i18n("Low") || + cProfile->currentText() == i18n("Medium") || cProfile->currentText() == i18n("High") || + cProfile->currentText() == i18n("Very high") ) { + cFormat->clear(); + sFormat = config->allLossyEncodableFormats(); + cFormat->insertStringList( sFormat ); + cFormat->setCurrentItem( formatIndex(optionsDetailed->getFormat()) ); + pProfileInfo->show(); + pProfileRemove->hide(); + } + else if( cProfile->currentText() == i18n("Lossless") ) { + cFormat->clear(); + sFormat = config->allLosslessEncodableFormats(); + sFormat += "wav"; + cFormat->insertStringList( sFormat ); + cFormat->setCurrentItem( formatIndex(optionsDetailed->getFormat()) ); + pProfileInfo->show(); + pProfileRemove->hide(); + } + else if( cProfile->currentText() == i18n("Hybrid") ) { + cFormat->clear(); + sFormat = config->allHybridEncodableFormats(); + cFormat->insertStringList( sFormat ); + cFormat->setCurrentItem( formatIndex(optionsDetailed->getFormat()) ); + pProfileInfo->show(); + pProfileRemove->hide(); + } + else if( cProfile->currentText() == i18n("User defined") ) { + cFormat->clear(); + sFormat = config->allEncodableFormats(); + sFormat += "wav"; + cFormat->insertStringList( sFormat ); + cFormat->setCurrentItem( formatIndex(optionsDetailed->getFormat()) ); + pProfileInfo->show(); + pProfileRemove->hide(); + } + else { + ConversionOptions options = config->getProfile( cProfile->currentText() ); + cFormat->clear(); + sFormat = options.encodingOptions.sFormat; + cFormat->insertStringList( sFormat ); + cFormat->setCurrentItem( formatIndex(optionsDetailed->getFormat()) ); + pProfileInfo->hide(); + pProfileRemove->show(); + } + + outputDirectory->setMode( optionsDetailed->getOutputDirectoryMode() ); + outputDirectory->setDirectory( optionsDetailed->getOutputDirectoryPath() ); +} + diff --git a/src/optionssimple.h b/src/optionssimple.h new file mode 100755 index 0000000..bb88d22 --- /dev/null +++ b/src/optionssimple.h @@ -0,0 +1,107 @@ + + +#ifndef OPTIONSSIMPLE_H +#define OPTIONSSIMPLE_H + +#include "outputdirectory.h" +#include "conversionoptions.h" + +#include + +class Config; +class ConversionOptions; +class OptionsDetailed; + +class KComboBox; +class KToolBarButton; +class KPushButton; + +/** + * @short The options widget for setting up the output options very easy + * @author Daniel Faust + * @version 0.3 + */ +class OptionsSimple : public QWidget +{ + Q_OBJECT +public: + /** + * Constructor + */ + OptionsSimple( Config*, OptionsDetailed*, const QString &text, QWidget* parent=0, const char* name=0 ); + + /** + * Detructor + */ + virtual ~OptionsSimple(); + + /** + * Set the current options + */ +// void setCurrentOptions( const ConversionOptions& ); + + /** + * Refills the whole form (e.g. after a config change) + */ + void refill(); // TODO syncronize with optionsDetailed + + void setCurrentProfile( const QString& profile ); + void setCurrentFormat( const QString& format ); + void setCurrentOutputDirectory( const QString& directory ); + +private: + KComboBox* cProfile; + KPushButton* pProfileRemove; + KPushButton* pProfileInfo; + KComboBox* cFormat; + KPushButton* pFormatInfo; + + OutputDirectory* outputDirectory; + + Config* config; + OptionsDetailed* optionsDetailed; + + QStringList sProfile; + QStringList sFormat; + + int profileIndex( const QString& string ); + int formatIndex( const QString& string ); + +//public slots: +// void setProfile( const QString &profile ); +// void setFormat( const QString &format ); + +private slots: + void profileInfo(); + void profileRemove(); + void formatInfo(); + void profileChanged(); + void formatChanged(); + void outputDirectoryModeChanged( OutputDirectory::Mode ); + void outputDirectoryPathChanged( const QString& ); + + void somethingChanged(); + +signals: +// void setFormat( const QString& format ); +// void setQualityMode( const QString& qualityMode ); +// void setQuality( int quality ); +// void setBitrateMode( const QString& bitrateMode ); +// void setBitrateRangeEnabled( bool enabled ); +// void setMinBitrate( int bitrate ); +// void setMaxBitrate( int bitrate ); +// void setSamplingrateEnabled( bool enabled ); +// void setSamplingrate( int sampleRate ); +// void setSamplingrate( const QString& sampleRate ); +// void setChannelsEnabled( bool enabled ); +// void setChannels( const QString& channels ); +// void setReplayGainEnabled( bool enabled ); +// void setOutputDirectoryMode( OutputDirectory::Mode ); +// void setOutputDirectoryPath( const QString& directory ); +// void setOptions( const ConversionOptions& options ); +// void setUserOptions( const QString& options ); + + void optionsChanged(); +}; + +#endif diff --git a/src/outputdirectory.cpp b/src/outputdirectory.cpp new file mode 100755 index 0000000..88a5466 --- /dev/null +++ b/src/outputdirectory.cpp @@ -0,0 +1,571 @@ + +#include "outputdirectory.h" +#include "filelist.h" +#include "conversionoptions.h" +#include "tagengine.h" +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +OutputDirectory::OutputDirectory( Config* _config, QWidget* parent, const char* name ) + : QWidget( parent, name ) +{ + config = _config; + + // create an icon loader object for loading icons + KIconLoader *iconLoader = new KIconLoader(); + + QGridLayout *grid = new QGridLayout( this, 1, 1, 0, 3, "grid" ); + + QHBoxLayout *box = new QHBoxLayout( ); + grid->addLayout( box, 0, 0 ); + + QLabel *lOutput = new QLabel( i18n("Output")+":", this, "lOutput" ); + box->addWidget(lOutput); + + cMode = new KComboBox( this ); +// cMode->insertItem( i18n("Default output directory") ); + cMode->insertItem( i18n("By meta data") ); + cMode->insertItem( i18n("Source directory") ); + cMode->insertItem( i18n("Specify output directory") ); + cMode->insertItem( i18n("Copy directory structure") ); + //QToolTip::add( cMode, i18n("Output all converted files into...") ); + box->addWidget( cMode ); + connect( cMode, SIGNAL(activated(int)), + this, SLOT(modeChangedSlot(int)) + ); + modeJustChanged = false; + /*pModeInfo = new KToolBarButton( "messagebox_info", 1010, this, "pModeInfo" ); + QToolTip::add( pModeInfo, i18n("Information about the output mode") ); + box->addWidget( pModeInfo ); + connect( pModeInfo, SIGNAL(clicked()), + this, SLOT(modeInfo()) + );*/ + pClear = new KToolBarButton( "locationbar_erase", 1001, this, "pClear" ); + QToolTip::add( pClear, i18n("Clear the directory input field") ); + box->addWidget( pClear ); + lDir = new KLineEdit( this, "lDir" ); + box->addWidget( lDir ); + connect( lDir, SIGNAL(textChanged(const QString&)), + this, SLOT(directoryChangedSlot(const QString&)) + ); + connect( pClear, SIGNAL(clicked()), + lDir, SLOT(setFocus()) + ); + connect( pClear, SIGNAL(clicked()), + lDir, SLOT(clear()) + ); + /*pDirInfo = new KToolBarButton( "messagebox_info", 1011, this, "pDirInfo" ); + QToolTip::add( pDirInfo, i18n("Information about the wildcards") ); + box->addWidget( pDirInfo ); + connect( pDirInfo, SIGNAL(clicked()), + this, SLOT(dirInfo()) + );*/ + pDirSelect = new KToolBarButton( "folder", 1012, this, "pDirSelect" ); + QToolTip::add( pDirSelect, i18n("Choose an output directory") ); + box->addWidget( pDirSelect ); + connect( pDirSelect, SIGNAL(clicked()), + this, SLOT(selectDir()) + ); + pDirGoto = new KToolBarButton( "konqueror", 1013, this, "pDirGoto" ); + QToolTip::add( pDirGoto, i18n("Open Konqueror with the output directory") ); + box->addWidget( pDirGoto ); + connect( pDirGoto, SIGNAL(clicked()), + this, SLOT(gotoDir()) + ); + + // delete the icon loader object + delete iconLoader; + + modeChangedSlot( MetaData ); // TODO implement proper + // save the current directory always on text change +} + +OutputDirectory::~OutputDirectory() +{} + +void OutputDirectory::disable() +{ + cMode->setEnabled( false ); + lDir->setEnabled( false ); + pClear->setEnabled( false ); + pDirSelect->setEnabled( false ); +} + +void OutputDirectory::enable() +{ + cMode->setEnabled( true ); + modeChangedSlot( cMode->currentItem() ); +} + +OutputDirectory::Mode OutputDirectory::mode() +{ + return (Mode)cMode->currentItem(); +} + +void OutputDirectory::setMode( OutputDirectory::Mode mode ) +{ + cMode->setCurrentItem( (int)mode ); + modeChangedSlot( (int)mode ); +} + +QString OutputDirectory::directory() +{ + if( /*(Mode)cMode->currentItem() != Default && */(Mode)cMode->currentItem() != Source ) return lDir->text(); + else return ""; +} + +void OutputDirectory::setDirectory( const QString& directory ) +{ + if( /*(Mode)cMode->currentItem() != Default && */(Mode)cMode->currentItem() != Source ) lDir->setText( directory ); +} + +QString OutputDirectory::calcPath( FileListItem* fileListItem, Config* config, QString extension ) +{ + // TODO replace '//' by '/' ??? + // FIXME test fvat names + QString path; + if( extension.isEmpty() ) extension = fileListItem->options.encodingOptions.sFormat; + + // FIXME file name + QString fileName; + if( fileListItem->track == -1 ) fileName = fileListItem->fileName; + else if( fileListItem->tags != 0 ) fileName = QString().sprintf("%02i",fileListItem->tags->track) + " - " + fileListItem->tags->title + "." + extension; + else fileName = "track" + QString::number(fileListItem->track) + "." + extension; // NOTE shouldn't be possible + + // if the user wants to change the output directory/file name per file! + if( !fileListItem->options.outputFilePathName.isEmpty() ) { +// path = uniqueFileName( changeExtension(fileListItem->options.outputFilePathName,extension) ); + path = changeExtension(fileListItem->options.outputFilePathName,extension); + if( config->data.general.useVFATNames ) path = vfatPath( path ); + return path; + } + + if( fileListItem->options.outputOptions.mode == Specify ) { +// path = uniqueFileName( changeExtension(fileListItem->options.outputOptions.directory+"/"+fileName,extension) ); + path = changeExtension(fileListItem->options.outputOptions.directory+"/"+fileName,extension); + if( config->data.general.useVFATNames ) path = vfatPath( path ); + return path; + } + else if( /*fileListItem->options.outputOptions.mode == Default || */fileListItem->options.outputOptions.mode == MetaData ) { + /*if( fileListItem->options.outputOptions.mode == Default ) path = config->data.general.defaultOutputDirectory; + else */path = fileListItem->options.outputOptions.directory; + + if( path.right(1) == "/" ) path += "%f"; + else if( path.findRev(QRegExp("%[aAbBcCdDfFgGnNpPtTyY]{1,1}")) < path.findRev("/") ) path += "/%f"; + + path.replace( "%a", "$replace_by_artist$" ); + path.replace( "%b", "$replace_by_album$" ); + path.replace( "%c", "$replace_by_comment$" ); + path.replace( "%d", "$replace_by_disc$" ); + path.replace( "%g", "$replace_by_genre$" ); + path.replace( "%n", "$replace_by_track$" ); + path.replace( "%p", "$replace_by_composer$" ); + path.replace( "%t", "$replace_by_title$" ); + path.replace( "%y", "$replace_by_year$" ); + path.replace( "%f", "$replace_by_filename$" ); + + QString artist = ( fileListItem->tags == 0 || fileListItem->tags->artist.isEmpty() ) ? i18n("Unknown Artist") : fileListItem->tags->artist; +/// artist.replace("/","\\"); + path.replace( "$replace_by_artist$", KURL::encode_string(artist).replace("/","%2f") ); + + QString album = ( fileListItem->tags == 0 || fileListItem->tags->album.isEmpty() ) ? i18n("Unknown Album") : fileListItem->tags->album; +/// album.replace("/","\\"); + path.replace( "$replace_by_album$", KURL::encode_string(album).replace("/","%2f") ); + + QString comment = ( fileListItem->tags == 0 || fileListItem->tags->comment.isEmpty() ) ? i18n("No Comment") : fileListItem->tags->comment; +/// comment.replace("/","\\"); + path.replace( "$replace_by_comment$", KURL::encode_string(comment).replace("/","%2f") ); + + QString disc = ( fileListItem->tags == 0 ) ? "0" : QString().sprintf("%i",fileListItem->tags->disc); + path.replace( "$replace_by_disc$", disc ); + + QString genre = ( fileListItem->tags == 0 || fileListItem->tags->genre.isEmpty() ) ? i18n("Unknown Genre") : fileListItem->tags->genre; +/// genre.replace("/","\\"); + path.replace( "$replace_by_genre$", KURL::encode_string(genre).replace("/","%2f") ); + + QString track = ( fileListItem->tags == 0 ) ? "00" : QString().sprintf("%02i",fileListItem->tags->track); + path.replace( "$replace_by_track$", track ); + + QString composer = ( fileListItem->tags == 0 || fileListItem->tags->composer.isEmpty() ) ? i18n("Unknown Composer") : fileListItem->tags->composer; +/// composer.replace("/","\\"); + path.replace( "$replace_by_composer$", KURL::encode_string(composer).replace("/","%2f") ); + + QString title = ( fileListItem->tags == 0 || fileListItem->tags->title.isEmpty() ) ? i18n("Unknown Title") : fileListItem->tags->title; +/// title.replace("/","\\"); + path.replace( "$replace_by_title$", KURL::encode_string(title).replace("/","%2f") ); + + QString year = ( fileListItem->tags == 0 ) ? "0000" : QString().sprintf("%04i",fileListItem->tags->year); + path.replace( "$replace_by_year$", year ); + + QString filename = fileName.left( fileName.findRev(".") ); +/// filename.replace("/","\\"); + path.replace( "$replace_by_filename$", filename ); + +// path = uniqueFileName( path + "." + extension ); + path = path + "." + extension; + if( config->data.general.useVFATNames ) path = vfatPath( path ); + return path; + } + else if( fileListItem->options.outputOptions.mode == CopyStructure ) { // TODO is that correct ??? + QString basePath = fileListItem->options.outputOptions.directory; + QString originalPath = fileListItem->options.filePathName; + QString cutted; + while( basePath.length() > 0 ) { + if( fileListItem->options.filePathName.find(basePath) == 0 ) { + originalPath.replace( basePath, "" ); + return uniqueFileName( changeExtension(basePath+cutted+originalPath,extension) ); + } + else { + cutted = basePath.right( basePath.length() - basePath.findRev("/") ) + cutted; + basePath = basePath.left( basePath.findRev("/") ); + } + } +// path = uniqueFileName( changeExtension(fileListItem->options.outputOptions.directory+"/"+fileListItem->options.filePathName,extension) ); + path = changeExtension(fileListItem->options.outputOptions.directory+"/"+fileListItem->options.filePathName,extension); + if( config->data.general.useVFATNames ) path = vfatPath( path ); + return path; + } + else { +// path = uniqueFileName( changeExtension(fileListItem->options.filePathName,extension) ); + path = changeExtension(fileListItem->options.filePathName,extension); + if( config->data.general.useVFATNames ) path = vfatPath( path ); + return path; + } +} + +QString OutputDirectory::changeExtension( const QString& filename, const QString& extension ) +{ + return filename.left( filename.findRev(".") + 1 ) + extension; +} + +QString OutputDirectory::uniqueFileName( const QString& filename ) +{ + QString filePathName; + + if( filename.left( 1 ) == "/" ) { + filePathName = filename; + } + else if( filename.left( 7 ) == "file://" ) { + filePathName = filename; + filePathName.remove( 0, 7 ); + } + else if( filename.left( 13 ) == "system:/home/" ) { + filePathName = filename; + filePathName.remove( 0, 13 ); + filePathName = QDir::homeDirPath() + "/" + filePathName; + } + else if( filename.left( 14 ) == "system:/users/" || filename.left( 6 ) == "home:/" ) { + int length = ( filename.left(6) == "home:/" ) ? 6 : 14; + QString username = filename; + username.remove( 0, length ); + username = username.left( username.find("/") ); + filePathName = filename; + filePathName.remove( 0, length + username.length() ); + KUser user( username ); + filePathName = user.homeDir() + filePathName; + } + else if( filename.left( 14 ) == "system:/media/" || filename.left( 7 ) == "media:/" ) { + int length = ( filename.left(7) == "media:/" ) ? 7 : 14; + QString device = filename; + device.remove( 0, length ); + device = "/dev/" + device.left( device.find( "/" ) ); + + KMountPoint::List mountPoints = KMountPoint::possibleMountPoints(); + + for( KMountPoint::List::ConstIterator jt = mountPoints.begin(); jt != mountPoints.end(); ++jt ) + { + const KSharedPtr mp = *jt; + if( mp->mountedFrom() == device ) + { + filePathName = ( mp->mountPoint() == "/" ) ? mp->mountPoint() : mp->mountPoint() + "/"; + filePathName += filename.right( filename.length() - device.length() - length + 4 ); + } + } + } + else { + filePathName = filename; + } + + QFileInfo fileInfo( KURL::decode_string(filePathName) ); + + // generate a unique file name + while( fileInfo.exists() ) { + fileInfo.setFile( fileInfo.filePath().left( fileInfo.filePath().findRev(".")+1 ) + i18n("new") + fileInfo.filePath().right( fileInfo.filePath().length() - fileInfo.filePath().findRev(".") ) ); + } + + return KURL::encode_string( fileInfo.filePath() ); // was: .replace( "//", "/" ) +} + +QString OutputDirectory::makePath( const QString& path ) +{ + QFileInfo fileInfo( path ); + + QStringList dirs = QStringList::split( "/", fileInfo.dirPath() ); + QString mkDir; + QDir dir; + for( QStringList::Iterator it = dirs.begin(); it != dirs.end(); ++it ) { + mkDir += "/" + KURL::decode_string(*it).replace("/","%2f"); + dir.setPath( mkDir ); + if( !dir.exists() ) dir.mkdir( mkDir ); + } + + return path; +} + +// copyright : (C) 2002 by Mark Kretschmann +// email : markey@web.de +// modified : 2008 Daniel Faust +QString OutputDirectory::vfatPath( const QString& path ) +{ + QString s = KURL::decode_string(path.right( path.length() - path.findRev("/") - 1 )); + QString p = KURL::decode_string(path.left( path.findRev("/") + 1 )); + + for( uint i = 0; i < s.length(); i++ ) + { + QChar c = s.ref( i ); + if( c < QChar(0x20) + || c=='*' || c=='?' || c=='<' || c=='>' + || c=='|' || c=='"' || c==':' || c=='/' + || c=='\\' ) + c = '_'; + s.ref( i ) = c; + } + + uint len = s.length(); + if( len == 3 || (len > 3 && s[3] == '.') ) + { + QString l = s.left(3).lower(); + if( l=="aux" || l=="con" || l=="nul" || l=="prn" ) + s = "_" + s; + } + else if( len == 4 || (len > 4 && s[4] == '.') ) + { + QString l = s.left(3).lower(); + QString d = s.mid(3,1); + if( (l=="com" || l=="lpt") && + (d=="0" || d=="1" || d=="2" || d=="3" || d=="4" || + d=="5" || d=="6" || d=="7" || d=="8" || d=="9") ) + s = "_" + s; + } + + while( s.startsWith( "." ) ) + s = s.mid(1); + + while( s.endsWith( "." ) ) + s = s.left( s.length()-1 ); + + s = s.left(255); + len = s.length(); + if( s[len-1] == ' ' ) + s[len-1] = '_'; + + return QString( p + s ).replace("%2f","_"); +// return p + s; +} + +void OutputDirectory::selectDir() +{ + QString startDir = lDir->text(); + int i = startDir.find( QRegExp("%[aAbBcCdDfFgGnNpPtTyY]{1,1}") ); + if( i != -1 ) { + i = startDir.findRev( "/", i ); + startDir = startDir.left( i ); + } + + QString directory = KFileDialog::getExistingDirectory( startDir, this, i18n("Choose an output directory") ); + if( !directory.isEmpty() ) { + QString dir = lDir->text(); + i = dir.find( QRegExp("%[aAbBcCdDfFgGnNpPtTyY]{1,1}") ); + if( i != -1 && (Mode)cMode->currentItem() == MetaData ) { + i = dir.findRev( "/", i ); + lDir->setText( directory + dir.mid(i) ); + } + else { + lDir->setText( directory ); + } + emit directoryChanged( directory ); + } +} + +void OutputDirectory::gotoDir() +{ + QString startDir = lDir->originalText(); + int i = startDir.find( QRegExp("%[aAbBcCdDfFgGnNpPtTyY]{1,1}") ); + if( i != -1 ) { + i = startDir.findRev( "/", i ); + startDir = startDir.left( i ); + } + + kfm.clearArguments(); + kfm << "kfmclient"; + kfm << "openURL"; + kfm << startDir; + kfm.start( KProcess::DontCare ); +} + +void OutputDirectory::modeChangedSlot( int mode ) +{ + modeJustChanged = true; + + /*if( (Mode)mode == Default ) { + pClear->setEnabled( false ); + lDir->setText( config->data.general.defaultOutputDirectory ); + lDir->setEnabled( true ); + lDir->setReadOnly( true ); + lDir->setEnableSqueezedText( true ); + pDirSelect->setEnabled( false ); + // TODO hide pDirSelect and show pDirEdit + pDirGoto->setEnabled( true ); + //pDirInfo->hide(); + QToolTip::remove( cMode ); + QToolTip::add( cMode, i18n("Output all converted files into the soundKonverter default output directory") ); + QToolTip::remove( lDir ); + } + else */ + if( (Mode)mode == MetaData ) { + pClear->setEnabled( true ); + if( config->data.general.metaDataOutputDirectory.isEmpty() ) config->data.general.metaDataOutputDirectory = QDir::homeDirPath() + "/soundKonverter/%b/%d - %n - %a - %t"; + lDir->setText( config->data.general.metaDataOutputDirectory ); + lDir->setEnabled( true ); + lDir->setReadOnly( false ); +// lDir->setEnableSqueezedText( false ); + pDirSelect->setEnabled( true ); + pDirGoto->setEnabled( true ); + //pDirInfo->show(); + QToolTip::remove( cMode ); + QToolTip::add( cMode, i18n("Name all converted files according to the specified pattern") ); + QToolTip::remove( lDir ); + QToolTip::add( lDir, i18n("

The following strings are wildcards, that will be replaced by the information in the meta data:

%a - Artist
%b - Album
%c - Comment
%d - Disc number
%g - Genre
%n - Track number
%p - Composer
%t - Title
%y - Year
%f - Original file name

") ); + } + else if( (Mode)mode == Source ) { + pClear->setEnabled( false ); + lDir->setText( "" ); + lDir->setEnabled( false ); + lDir->setReadOnly( false ); +// lDir->setEnableSqueezedText( false ); + pDirSelect->setEnabled( false ); + pDirGoto->setEnabled( false ); + //pDirInfo->hide(); + QToolTip::remove( cMode ); + QToolTip::add( cMode, i18n("Output all converted files into the same directory as the original files") ); + QToolTip::remove( lDir ); + } + else if( (Mode)mode == Specify ) { + pClear->setEnabled( true ); + if( config->data.general.specifyOutputDirectory.isEmpty() ) config->data.general.specifyOutputDirectory = QDir::homeDirPath() + "/soundKonverter"; + lDir->setText( config->data.general.specifyOutputDirectory ); + lDir->setEnabled( true ); + lDir->setReadOnly( false ); +// lDir->setEnableSqueezedText( false ); + pDirSelect->setEnabled( true ); + pDirGoto->setEnabled( true ); + //pDirInfo->hide(); + QToolTip::remove( cMode ); + QToolTip::add( cMode, i18n("Output all converted files into the specified output directory") ); + QToolTip::remove( lDir ); + } + else if( (Mode)mode == CopyStructure ) { + pClear->setEnabled( true ); + if( config->data.general.copyStructureOutputDirectory.isEmpty() ) config->data.general.copyStructureOutputDirectory = QDir::homeDirPath() + "/soundKonverter"; + lDir->setText( config->data.general.copyStructureOutputDirectory ); + lDir->setEnabled( true ); + lDir->setReadOnly( false ); +// lDir->setEnableSqueezedText( false ); + pDirSelect->setEnabled( true ); + pDirGoto->setEnabled( true ); + //pDirInfo->hide(); + QToolTip::remove( cMode ); + QToolTip::add( cMode, i18n("Copy the whole directory structure for all converted files") ); + QToolTip::remove( lDir ); + } + + emit modeChanged( (Mode)mode ); + + modeJustChanged = false; +} + +void OutputDirectory::directoryChangedSlot( const QString& directory ) +{ + if( modeJustChanged ) { + modeJustChanged = false; + return; + } + + Mode mode = (Mode)cMode->currentItem(); + + if( mode == MetaData ) { + config->data.general.metaDataOutputDirectory = directory; + } + else if( mode == Specify ) { + config->data.general.specifyOutputDirectory = directory; + } + else if( mode == CopyStructure ) { + config->data.general.copyStructureOutputDirectory = directory; + } + + emit directoryChanged( directory ); +} + +/*void OutputDirectory::modeInfo() +{ + int mode = cMode->currentItem(); + QString sModeString = cMode->currentText(); + + if( (Mode)mode == Default ) { + KMessageBox::information( this, + i18n("This will output each file into the soundKonverter default directory."), + QString(i18n("Mode")+": ").append(sModeString) ); + } + else if( (Mode)mode == Source ) { + KMessageBox::information( this, + i18n("This will output each file into the same directory as the original file."), + QString(i18n("Mode")+": ").append(sModeString) ); + } + else if( (Mode)mode == Specify ) { + KMessageBox::information( this, + i18n("This will output each file into the directory specified in the editbox behind."), + QString(i18n("Mode")+": ").append(sModeString) ); + } + else if( (Mode)mode == MetaData ) { + KMessageBox::information( this, + i18n("This will output each file into a directory, which is created based on the metadata in the audio files. Select a directory, where the new directories should be created."), + QString(i18n("Mode")+": ").append(sModeString) ); + } + else if( (Mode)mode == CopyStructure ) { + KMessageBox::information( this, + i18n("This will output each file into a directory, which is created based on the name of the original directory. So you can copy a whole directory structure, in one you have the original files, in the other the converted."), + QString(i18n("Mode")+": ").append(sModeString) ); + } + else { + KMessageBox::error( this, + i18n("This mode (%s) doesn't exist.", sModeString), + QString(i18n("Mode")+": ").append(sModeString) ); + } +}*/ + +/*void OutputDirectory::dirInfo() +{ + KMessageBox::information( this, + i18n("

The following strings are space holders, that will be replaced by the information in the metatags.

%a - Artist
%b - Album
%c - Comment
%d - Disc number
%g - Genre
%n - Track number
%p - Composer
%t - Title
%y - Year
%f - Original file name

"), + QString(i18n("Legend")) ); +}*/ + diff --git a/src/outputdirectory.h b/src/outputdirectory.h new file mode 100755 index 0000000..85b5236 --- /dev/null +++ b/src/outputdirectory.h @@ -0,0 +1,92 @@ + + +#ifndef OUTPUTDIRECTORY_H +#define OUTPUTDIRECTORY_H + +#include +#include + +class FileListItem; + +class Config; +class KComboBox; +class KLineEdit; +class KToolBarButton; + +/** + * @short The input area for the output directory + * @author Daniel Faust + * @version 0.3 + */ +class OutputDirectory : public QWidget +{ + Q_OBJECT +public: + enum Mode { +// Default, + MetaData, + Source, + Specify, + CopyStructure + }; + + /** + * Constructor + */ + OutputDirectory( Config*, QWidget* parent = 0, const char* name = 0 ); + + Mode mode(); + void setMode( Mode ); + QString directory(); + void setDirectory( const QString& ); + + static QString calcPath( FileListItem* fileListItem, Config* config, QString extension = "" ); + static QString changeExtension( const QString& filename, const QString& extension ); + static QString uniqueFileName( const QString& filename ); + static QString makePath( const QString& path ); + static QString vfatPath( const QString& path ); + + /** + * Destructor + */ + virtual ~OutputDirectory(); + +public slots: + //void setActive( bool ); + void enable(); + void disable(); + +private slots: + void modeChangedSlot( int ); + void directoryChangedSlot( const QString& ); + void selectDir(); + void gotoDir(); + //void modeInfo(); + //void dirInfo(); + //void savePaths(); + +private: + KComboBox* cMode; + //KToolBarButton* pModeInfo; + KLineEdit* lDir; + KToolBarButton* pDirSelect; + KToolBarButton* pDirGoto; + //KToolBarButton* pDirInfo; + KToolBarButton* pClear; + + bool modeJustChanged; + + KProcess kfm; + + Config* config; + +/* QString sharedDirPath; + QString metadataPath; + QString copyStructurePath; +*/ +signals: + void modeChanged( OutputDirectory::Mode ); + void directoryChanged( const QString& ); +}; + +#endif // OUTPUTDIRECTORY_H diff --git a/src/paranoia.cpp b/src/paranoia.cpp new file mode 100755 index 0000000..ef1048c --- /dev/null +++ b/src/paranoia.cpp @@ -0,0 +1,257 @@ +/*************************************************************************** + paranoia.cpp - description + ------------------- + copyright : (C) 2002-2006 by Christophe Thommeret + email : hftom@free.fr + modified : 2006 Daniel Faust + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +//#include +#include +#include +#include +#include +#include + + +#include "paranoia.h" + +#define DEFAULT_DRIVE "/dev/cdrom" + + + + +void paranoiaCallback( long, int ) +{ +} + + + +Paranoia::Paranoia() +{ + d = 0; + p = 0; +} + + + +bool Paranoia::init( QString dev ) +{ + QString s; + QFile f; + + if ( p!=0 ) paranoia_free( p ); + if ( d!=0 ) cdda_close( d ); + nTracks = 0; + + dev = dev.stripWhiteSpace(); + f.setName( dev ); + if ( !f.exists() ) { + /*if ( !findCdrom() ) { + d = cdda_find_a_cdrom( CDDA_MESSAGE_PRINTIT, 0 ); + if ( cdda_open( d )!=0 ) + return false; + }*/ + return false; + } + else { + d = cdda_identify( dev.ascii(), CDDA_MESSAGE_PRINTIT, 0 ); + if ( d==0 ) + return false; + if ( cdda_open( d )!=0 ) + return false; + } + p = paranoia_init( d ); + nTracks = cdda_tracks( d ); + return true; +} + + + +bool Paranoia::findCdrom() +{ + QFile *f; + QString c; + QString s=""; + int pos, i; + bool stop=false; + char dev[4][4]={"","","",""}; + + f = new QFile( "/proc/sys/dev/cdrom/info" ); + if ( !f->open(IO_ReadOnly) ) + return false; + + QTextStream t( f ); + while ( !t.eof() && !stop ) { + s = t.readLine(); + if ( s.contains("drive name:") ) + stop = true; + } + if ( !stop ) + return false; + + pos = s.find(":"); + c = s.right( s.length()-pos-1 ); + sscanf( c.latin1(), "%s %s %s %s", dev[0], dev[1], dev[2], dev[3] ); + + for ( i=0; i<4; i++ ) + if ( procCdrom( dev[i] ) ) + return true; + + f->close(); + return false; +} + + + +bool Paranoia::procCdrom( QString name ) +{ + int pos; + + if ( name.contains("sr") ) { + pos = name.find("r"); + name = name.right( name.length()-pos-1 ); + name = "/dev/scd"+name; + d = cdda_identify( name.ascii(), CDDA_MESSAGE_PRINTIT, 0 ); + if ( cdda_open( d )==0 ) + return true; + } + else if ( name.contains("hd") ) { + name = "/dev/"+name; + d = cdda_identify( name.ascii(), CDDA_MESSAGE_PRINTIT, 0 ); + if ( cdda_open( d )==0 ) + return true; + } + return false; +} + + + +void Paranoia::setMode( int mode ) +{ + switch ( mode ) { + case 0 : mode = PARANOIA_MODE_DISABLE; + break; + case 1 : mode = PARANOIA_MODE_FULL^PARANOIA_MODE_NEVERSKIP; + break; + case 2 : mode = PARANOIA_MODE_FULL; + } + paranoia_modeset( p, mode ); +} + + +bool Paranoia::initTrack( int t ) +{ + currentSector = cdda_track_firstsector( d, t ); + endOfTrack = cdda_track_lastsector( d, t ); + paranoia_seek( p, currentSector, SEEK_SET ); + return true; +} + + + + +int Paranoia::trackFirstSector( int t ) +{ + return cdda_track_firstsector( d, t ); +} + + + +int Paranoia::discFirstSector() +{ + return cdda_disc_firstsector( d ); +} + + + +int Paranoia::discLastSector() +{ + return cdda_disc_lastsector( d ); +} + + + +bool Paranoia::isAudio( int t ) +{ + if ( cdda_track_audiop( d, t+1 ) ) return true; + else return false; +} + + + +QString Paranoia::trackSize( int t ) +{ + QString s, c; + long total; + + total = CD_FRAMESIZE_RAW * (cdda_track_lastsector( d, t+1 )-cdda_track_firstsector( d, t+1 ) ); + if ( total>(1048576 ) ) s = c.setNum(total/1048576.0, 'f', 2)+" "+i18n("MB"); + else if ( total>1024 ) s = c.setNum(total/1024.0, 'f', 2)+" "+i18n("KB"); + else s = c.setNum(total*1.0, 'f', 2)+" "+i18n("Bytes"); + return s; +} + + + +long Paranoia::trackSectorSize( int t ) +{ + return cdda_track_lastsector( d, t )-cdda_track_firstsector( d, t ); +} + + + +long Paranoia::trackTime( int t ) +{ + QString c; + long total, time; +// int m, s; + + if ( t<0 ) total = CD_FRAMESIZE_RAW * (cdda_disc_lastsector( d )-cdda_disc_firstsector( d ) ); + else total = CD_FRAMESIZE_RAW * (cdda_track_lastsector( d, t+1 )-cdda_track_firstsector( d, t+1 ) ); + time = (8 * total) / (44100 * 2 * 16); +// m = time/60; +// s = time%60; +// c.sprintf( "%.2i:%.2i", m, s ); + return time; +} + + + +Paranoia::~Paranoia() +{ + if ( p!=0 ) paranoia_free( p ); + if (d!=0 ) cdda_close( d ); +} + + + +long Paranoia::getTracks() +{ + return nTracks; +} diff --git a/src/paranoia.h b/src/paranoia.h new file mode 100755 index 0000000..f1a5ae8 --- /dev/null +++ b/src/paranoia.h @@ -0,0 +1,59 @@ +/*************************************************************************** + paranoia.h - description + ------------------- + copyright : (C) 2002-2006 by Christophe Thommeret + email : hftom@free.fr + modified : 2006 Daniel Faust + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef PARANOIA_H +#define PARANOIA_H + +#include + +extern "C" +{ +#include +#include +} + + + +class Paranoia +{ +public: + Paranoia(); + bool init( QString dev ); + ~Paranoia(); + long getTracks(); + long trackTime( int t ); + int trackFirstSector( int t ); + int discFirstSector(); + int discLastSector(); + +private: + bool findCdrom(); + bool procCdrom( QString name ); + bool initTrack( int t ); + void setMode( int mode ); + bool isAudio( int t ); + QString trackSize( int t ); + long trackSectorSize( int t ); + + long nTracks; + cdrom_drive *d; + cdrom_paranoia *p; + long currentSector, endOfTrack; + int paraMode; + int progress; +}; +#endif diff --git a/src/pics/Makefile.am b/src/pics/Makefile.am new file mode 100755 index 0000000..4120423 --- /dev/null +++ b/src/pics/Makefile.am @@ -0,0 +1,7 @@ +picsdir = $(kde_datadir)/soundkonverter/pics +pics_DATA = ledgreen_legend.png \ + ledgreen.png \ + ledred_legend.png \ + ledred.png \ + ledyellow_legend.png \ + ledyellow.png diff --git a/src/pics/ledgreen.png b/src/pics/ledgreen.png new file mode 100755 index 0000000..f593745 Binary files /dev/null and b/src/pics/ledgreen.png differ diff --git a/src/pics/ledgreen_legend.png b/src/pics/ledgreen_legend.png new file mode 100755 index 0000000..f21384e Binary files /dev/null and b/src/pics/ledgreen_legend.png differ diff --git a/src/pics/ledred.png b/src/pics/ledred.png new file mode 100755 index 0000000..62a84cd Binary files /dev/null and b/src/pics/ledred.png differ diff --git a/src/pics/ledred_legend.png b/src/pics/ledred_legend.png new file mode 100755 index 0000000..9ae9c68 Binary files /dev/null and b/src/pics/ledred_legend.png differ diff --git a/src/pics/ledyellow.png b/src/pics/ledyellow.png new file mode 100755 index 0000000..725dc73 Binary files /dev/null and b/src/pics/ledyellow.png differ diff --git a/src/pics/ledyellow_legend.png b/src/pics/ledyellow_legend.png new file mode 100755 index 0000000..599499e Binary files /dev/null and b/src/pics/ledyellow_legend.png differ diff --git a/src/pluginloader/Makefile.am b/src/pluginloader/Makefile.am new file mode 100755 index 0000000..64ca193 --- /dev/null +++ b/src/pluginloader/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I$(top_srcdir)/src/metadata $(all_includes) -I$(top_srcdir)/src/ +METASOURCES = AUTO +noinst_HEADERS = pluginloaderbase.h convertpluginloader.h \ + replaygainpluginloader.h formatinfoloader.h ripperpluginloader.h + +noinst_LTLIBRARIES = libpluginloader.la +libpluginloader_la_SOURCES = pluginloaderbase.cpp \ + convertpluginloader.cpp replaygainpluginloader.cpp formatinfoloader.cpp \ + ripperpluginloader.cpp diff --git a/src/pluginloader/convertpluginloader.cpp b/src/pluginloader/convertpluginloader.cpp new file mode 100755 index 0000000..89996ba --- /dev/null +++ b/src/pluginloader/convertpluginloader.cpp @@ -0,0 +1,265 @@ + +#include "convertpluginloader.h" + +#include + +#include +#include + +// TODO check whether it is possible to implement presets in the lame plugin + +ConvertPlugin::ConvertPlugin() +{} + +ConvertPlugin::~ConvertPlugin() +{} + + +ConvertPluginLoader::ConvertPluginLoader() +{} + +ConvertPluginLoader::~ConvertPluginLoader() +{} + +int ConvertPluginLoader::verifyFile( QString fileName ) +{ + QFile opmlFile( fileName ); + if( !opmlFile.open( IO_ReadOnly ) ) { + return -1; + } + if( !domTree.setContent( &opmlFile ) ) { + return -1; + } + opmlFile.close(); + + QDomElement root = domTree.documentElement(); + if( root.attribute("type") != "converter" ) return -1; + int version; + QDomNode node; + node = root.firstChild(); + while( !node.isNull() ) { + if( node.isElement() && node.nodeName() == "info" ) { + version = node.toElement().attribute("version","0").toInt(); + break; + } + } + + return version; +} + +ConvertPlugin* ConvertPluginLoader::loadFile( QString fileName ) +{ + int t_int; + float t_float; + QString t_str; + + ConvertPlugin* plugin = new ConvertPlugin(); + plugin->info.version = -1; // if something goes wrong, we can see that by looking at plugin->info.version + plugin->filePathName = fileName; + + QFile opmlFile( fileName ); + if( !opmlFile.open( IO_ReadOnly ) ) { + return plugin; + } + if( !domTree.setContent( &opmlFile ) ) { + return plugin; + } + opmlFile.close(); + + QString language = KGlobal::locale()->languagesTwoAlpha().first(); + + QDomElement root = domTree.documentElement(); + if( root.attribute("type") != "converter" ) return plugin; + QDomNode node, sub1Node, sub2Node, sub3Node, sub4Node; + node = root.firstChild(); + + plugin->enc.enabled = false; + plugin->enc.strength.enabled = false; + plugin->enc.lossy.enabled = false; + plugin->enc.lossy.quality.enabled = false; + plugin->enc.lossy.bitrate.abr.enabled = false; + plugin->enc.lossy.bitrate.abr.bitrate_range.enabled = false; + plugin->enc.lossy.bitrate.cbr.enabled = false; + plugin->enc.lossy.samplingrate.enabled = false; + plugin->enc.lossy.channels.stereo_enabled = false; + plugin->enc.lossy.channels.joint_stereo_enabled = false; + plugin->enc.lossy.channels.forced_joint_stereo_enabled = false; + plugin->enc.lossy.channels.dual_channels_enabled = false; + plugin->enc.lossy.channels.mono_enabled = false; + plugin->enc.lossless.enabled = false; + plugin->enc.hybrid.enabled = false; + plugin->enc.replaygain.enabled = false; + plugin->enc.tag.enabled = false; + plugin->dec.enabled = false; + + while( !node.isNull() ) { + if( node.isElement() && node.nodeName() == "info" ) { + + plugin->info.name = node.toElement().attribute("name",i18n("Unknown Name")); + plugin->info.about = node.toElement().attribute("about_"+language); + if( plugin->info.about.isEmpty() ) plugin->info.about = node.toElement().attribute("about"); + if( plugin->info.about.isEmpty() ) plugin->info.about = i18n("Sorry, no information available!"); + plugin->info.author = node.toElement().attribute("author",i18n("Unknown Author")); + plugin->info.version = node.toElement().attribute("version","0").toInt(); + + } + else if( node.isElement() && node.nodeName() == "enc" ) { + + if(node.toElement().attribute("enabled") == "true") plugin->enc.enabled = true; + plugin->enc.rank = node.toElement().attribute("rank","10").toInt(); + plugin->enc.bin = node.toElement().attribute( "bin" ); + plugin->enc.param = node.toElement().attribute("param"); + plugin->enc.silent_param = node.toElement().attribute("silent_param"); + plugin->enc.mime_types = QStringList::split( ',', node.toElement().attribute("mime_types","application/octet-stream") ); + plugin->enc.in_out_files = node.toElement().attribute("in_out_files"); + plugin->enc.overwrite = node.toElement().attribute("overwrite"); + + sub1Node = node.toElement().firstChild(); + while( !sub1Node.isNull() ) { + if( sub1Node.isElement() && sub1Node.nodeName() == "strength" ) { + + if( sub1Node.toElement().attribute("enabled") == "true" ) plugin->enc.strength.enabled = true; + plugin->enc.strength.range_min = sub1Node.toElement().attribute("range_min").toFloat(); + plugin->enc.strength.range_max = sub1Node.toElement().attribute("range_max").toFloat(); + plugin->enc.strength.separator = sub1Node.toElement().attribute("separator").at(0); + plugin->enc.strength.param = sub1Node.toElement().attribute("param"); + plugin->enc.strength.step = sub1Node.toElement().attribute("step").toFloat(); + plugin->enc.strength.profiles = QStringList::split( ',', sub1Node.toElement().attribute("profiles") ); + plugin->enc.strength.default_value = sub1Node.toElement().attribute("default_value").toFloat(); + + } + else if( sub1Node.isElement() && sub1Node.nodeName() == "lossy" ) { + + if( sub1Node.toElement().attribute("enabled") == "true" ) plugin->enc.lossy.enabled = true; + + sub2Node = sub1Node.toElement().firstChild(); + while( !sub2Node.isNull() ) { + if( sub2Node.isElement() && sub2Node.nodeName() == "quality" ) { + + if( sub2Node.toElement().attribute("enabled") == "true" ) plugin->enc.lossy.quality.enabled = true; + plugin->enc.lossy.quality.range_min = sub2Node.toElement().attribute("range_min").toFloat(); + plugin->enc.lossy.quality.range_max = sub2Node.toElement().attribute("range_max").toFloat(); + plugin->enc.lossy.quality.separator = sub2Node.toElement().attribute("separator").at(0); + plugin->enc.lossy.quality.help = sub2Node.toElement().attribute("help"); + plugin->enc.lossy.quality.output = sub2Node.toElement().attribute("output"); + plugin->enc.lossy.quality.param = sub2Node.toElement().attribute("param"); + plugin->enc.lossy.quality.step = sub2Node.toElement().attribute("step").toFloat(); + plugin->enc.lossy.quality.profiles = QStringList::split( ',', sub2Node.toElement().attribute("profiles") ); + + } + else if( sub2Node.isElement() && sub2Node.nodeName() == "bitrate" ) { + sub3Node = sub2Node.toElement().firstChild(); + while( !sub3Node.isNull() ) { + if( sub3Node.isElement() && sub3Node.nodeName() == "abr" ) { + + if( sub3Node.toElement().attribute("enabled") == "true" ) plugin->enc.lossy.bitrate.abr.enabled = true; + plugin->enc.lossy.bitrate.abr.output = sub3Node.toElement().attribute("output"); + plugin->enc.lossy.bitrate.abr.param = sub3Node.toElement().attribute("param"); + + sub4Node = sub3Node.toElement().firstChild(); + while( !sub4Node.isNull() ) { + if( sub4Node.isElement() && sub4Node.nodeName() == "bitrate_range" ) { + + if( sub4Node.toElement().attribute("enabled") == "true" ) plugin->enc.lossy.bitrate.abr.bitrate_range.enabled = true; + plugin->enc.lossy.bitrate.abr.bitrate_range.param_min = sub4Node.toElement().attribute("min_param"); + plugin->enc.lossy.bitrate.abr.bitrate_range.param_max = sub4Node.toElement().attribute("max_param"); + + } + sub4Node = sub4Node.nextSibling(); + } + } + else if( sub3Node.isElement() && sub3Node.nodeName() == "cbr" ) { + + if( sub3Node.toElement().attribute("enabled") == "true" ) plugin->enc.lossy.bitrate.cbr.enabled = true; + plugin->enc.lossy.bitrate.cbr.output = sub3Node.toElement().attribute("output"); + plugin->enc.lossy.bitrate.cbr.param = sub3Node.toElement().attribute("param"); + + } + sub3Node = sub3Node.nextSibling(); + } + } + else if( sub2Node.isElement() && sub2Node.nodeName() == "samplingrate" ) { + + if( sub2Node.toElement().attribute("enabled") == "true" ) plugin->enc.lossy.samplingrate.enabled = true; + if( sub2Node.toElement().attribute("unit") == "Hz" ) plugin->enc.lossy.samplingrate.unit = PluginLoaderBase::Hz; + else plugin->enc.lossy.samplingrate.unit = PluginLoaderBase::KHz; + plugin->enc.lossy.samplingrate.param = sub2Node.toElement().attribute("param"); + + } + else if( sub2Node.isElement() && sub2Node.nodeName() == "channels" ) { + + if( sub2Node.toElement().attribute("stereo_enabled") == "true" ) plugin->enc.lossy.channels.stereo_enabled = true; + plugin->enc.lossy.channels.stereo_param = sub2Node.toElement().attribute("stereo_param"); + if( sub2Node.toElement().attribute("joint_stereo_enabled") == "true" ) plugin->enc.lossy.channels.joint_stereo_enabled = true; + plugin->enc.lossy.channels.joint_stereo_param = sub2Node.toElement().attribute("joint_stereo_param"); + if( sub2Node.toElement().attribute("forced_joint_stereo_enabled") == "true" ) plugin->enc.lossy.channels.forced_joint_stereo_enabled = true; + plugin->enc.lossy.channels.forced_joint_stereo_param = sub2Node.toElement().attribute("forced_joint_stereo_param"); + if( sub2Node.toElement().attribute("dual_channels_enabled") == "true" ) plugin->enc.lossy.channels.dual_channels_enabled = true; + plugin->enc.lossy.channels.dual_channels_param=sub2Node.toElement().attribute("dual_channels_param"); + if( sub2Node.toElement().attribute("mono_enabled") == "true" ) plugin->enc.lossy.channels.mono_enabled = true; + plugin->enc.lossy.channels.mono_param=sub2Node.toElement().attribute("mono_param"); + + } + sub2Node = sub2Node.nextSibling(); + } + } + else if( sub1Node.isElement() && sub1Node.nodeName() == "lossless" ) { + + if( sub1Node.toElement().attribute("enabled") == "true" ) plugin->enc.lossless.enabled = true; + plugin->enc.lossless.output = sub1Node.toElement().attribute("output"); + plugin->enc.lossless.param = sub1Node.toElement().attribute("param"); + + } + else if( sub1Node.isElement() && sub1Node.nodeName() == "hybrid" ) { + + if( sub1Node.toElement().attribute("enabled") == "true" ) plugin->enc.hybrid.enabled = true; + plugin->enc.hybrid.output = sub1Node.toElement().attribute("output"); + plugin->enc.hybrid.param = sub1Node.toElement().attribute("param"); + plugin->enc.hybrid.correction_file_mime_type = sub1Node.toElement().attribute("correction_file_mime_type","application/octet-stream"); + + } + else if( sub1Node.isElement() && sub1Node.nodeName() == "replay_gain" ) { + + if( sub1Node.toElement().attribute("enabled") == "true" ) plugin->enc.replaygain.enabled = true; + plugin->enc.replaygain.use = sub1Node.toElement().attribute("use"); + plugin->enc.replaygain.avoid = sub1Node.toElement().attribute("avoid"); + plugin->enc.replaygain.rank = sub1Node.toElement().attribute("rank","10").toInt(); + + } + else if( sub1Node.isElement() && sub1Node.nodeName() == "tag" ) { + + if( sub1Node.toElement().attribute("enabled") == "true" ) plugin->enc.tag.enabled = true; + plugin->enc.tag.param = sub1Node.toElement().attribute("param"); + plugin->enc.tag.artist = sub1Node.toElement().attribute("artist"); + plugin->enc.tag.composer = sub1Node.toElement().attribute("composer"); + plugin->enc.tag.album = sub1Node.toElement().attribute("album"); + plugin->enc.tag.disc = sub1Node.toElement().attribute("disc"); + plugin->enc.tag.title = sub1Node.toElement().attribute("title"); + plugin->enc.tag.genre = sub1Node.toElement().attribute("genre"); + plugin->enc.tag.comment = sub1Node.toElement().attribute("comment"); + plugin->enc.tag.track = sub1Node.toElement().attribute("track"); + plugin->enc.tag.year = sub1Node.toElement().attribute("year"); + + } + sub1Node = sub1Node.nextSibling(); + } + } + else if ( node.isElement() && node.nodeName() == "dec" ) { + + if(node.toElement().attribute("enabled") == "true") plugin->dec.enabled = true; + plugin->dec.rank = node.toElement().attribute("rank","10").toInt(); + plugin->dec.bin = node.toElement().attribute("bin"); + plugin->dec.output = node.toElement().attribute("output"); + plugin->dec.param = node.toElement().attribute("param"); + plugin->dec.overwrite = node.toElement().attribute("overwrite"); + plugin->dec.mime_types = QStringList::split( ',', node.toElement().attribute("mime_types","application/octet-stream") ); + plugin->dec.in_out_files = node.toElement().attribute("in_out_files"); + plugin->dec.silent_param = node.toElement().attribute("silent_param"); + + } + node = node.nextSibling(); + } + + return plugin; +} + diff --git a/src/pluginloader/convertpluginloader.h b/src/pluginloader/convertpluginloader.h new file mode 100755 index 0000000..ad09e12 --- /dev/null +++ b/src/pluginloader/convertpluginloader.h @@ -0,0 +1,190 @@ + + +#ifndef CONVERTPLUGINLOADER_H +#define CONVERTPLUGINLOADER_H + +#include "pluginloaderbase.h" + + +/** + * @short The complete data, how to use the backend + * @author Daniel Faust + * @version 0.3 + */ +class ConvertPlugin +{ +public: + /** + * Constructor + */ + ConvertPlugin(); + + /** + * Destructor + */ + virtual ~ConvertPlugin(); + + QString filePathName; // the file name of th plugin (needed to detect write permissions) + + struct Info + { + int version; // the version of our plugin (v0.2.1 = 201, v11.3 = 110300) + QString name; // the name of our plugin + QString author; // the author of the plugin + QString about; // a short information aboue the plugin + } info; + + struct Enc + { + bool enabled; + int rank; + QString bin; + QString param; + QString silent_param; + QStringList mime_types; + QString in_out_files; + QString overwrite; + + struct Strength { + bool enabled; + QString param; + float range_min; + float range_max; + float step; + QChar separator; + QStringList profiles; + float default_value; + } strength; + + struct Lossy { + bool enabled; + + struct Quality { + bool enabled; + QString param; + float range_min; + float range_max; + float step; + QChar separator; + QString help; + QString output; + QStringList profiles; // NOTE when using profiles, step must be 1 and range_min 0 + } quality; + + struct Bitrate { + struct Abr + { + bool enabled; + QString param; + QString output; + + struct BitrateRange { + bool enabled; + QString param_min; + QString param_max; + } bitrate_range; + + } abr; + + struct Cbr { + bool enabled; + QString param; + QString output; + } cbr; + + } bitrate; + + struct Samplingrate { + bool enabled; + QString param; + PluginLoaderBase::Unit unit; + } samplingrate; + + struct Channels { + bool stereo_enabled; + QString stereo_param; + bool joint_stereo_enabled; + QString joint_stereo_param; + bool forced_joint_stereo_enabled; + QString forced_joint_stereo_param; + bool dual_channels_enabled; + QString dual_channels_param; + bool mono_enabled; + QString mono_param; + } channels; + } lossy; + + struct Lossless { + bool enabled; + QString param; + QString output; + } lossless; + + struct Hybrid { + bool enabled; + QString param; + QString output; + QString correction_file_mime_type; + } hybrid; + + struct ReplayGain { + bool enabled; + QString use; + QString avoid; + int rank; + } replaygain; + + struct Tag { + bool enabled; + QString param; + QString artist; + QString composer; + QString album; + QString disc; + QString title; + QString genre; + QString comment; + QString track; + QString year; + } tag; + } enc; + + struct Dec { + bool enabled; + int rank; + QString bin; + QString param; + QString silent_param; + QStringList mime_types; + QString output; + QString in_out_files; + QString overwrite; + } dec; +}; + +/** + * @short The plugin loader for the converter plugins + * @author Daniel Faust + * @version 0.3 + */ +class ConvertPluginLoader : public PluginLoaderBase +{ + Q_OBJECT +public: + /** + * Constructor + */ + ConvertPluginLoader(); + + /** + * Destructor + */ + virtual ~ConvertPluginLoader(); + + /** is this file a converter plugin and loadable? */ + int verifyFile( QString ); + /** load a given file */ + ConvertPlugin* loadFile( QString ); +}; + +#endif // CONVERTPLUGINLOADER_H diff --git a/src/pluginloader/formatinfoloader.cpp b/src/pluginloader/formatinfoloader.cpp new file mode 100755 index 0000000..c585ed6 --- /dev/null +++ b/src/pluginloader/formatinfoloader.cpp @@ -0,0 +1,88 @@ + +#include "formatinfoloader.h" + +#include + +#include +#include + +FormatInfo::FormatInfo() +{} + +FormatInfo::~FormatInfo() +{} + + +FormatInfoLoader::FormatInfoLoader() +{} + +FormatInfoLoader::~FormatInfoLoader() +{} + +bool FormatInfoLoader::verifyFile( QString fileName ) +{ + QFile opmlFile( fileName ); + if( !opmlFile.open( IO_ReadOnly ) ) { + return false; + } + if( !domTree.setContent( &opmlFile ) ) { + return false; + } + opmlFile.close(); + + QDomElement root = domTree.documentElement(); + if( root.attribute("type") == "format_info" ) return true; + + return false; +} + +FormatInfo* FormatInfoLoader::loadFile( QString fileName ) +{ + int t_int; + float t_float; + QString t_str; + + FormatInfo* plugin = new FormatInfo(); + plugin->mime_types = "application/octet-stream"; // if something goes wrong, we can see that by looking at plugin->mimetype + + QFile opmlFile( fileName ); + if( !opmlFile.open( IO_ReadOnly ) ) { + return plugin; + } + if( !domTree.setContent( &opmlFile ) ) { + return plugin; + } + opmlFile.close(); + + QString language = KGlobal::locale()->languagesTwoAlpha().first(); + + QDomElement root = domTree.documentElement(); + if( root.attribute("type") != "format_info" ) return plugin; + QDomNode node; + node = root.firstChild(); + + while( !node.isNull() ) { + if( node.isElement() && node.nodeName() == "data" ) { + + plugin->mime_types = QStringList::split( ',',node.toElement().attribute("mime_types","application/octet-stream") ); + plugin->extensions = QStringList::split( ',',node.toElement().attribute("extensions") ); + plugin->description = node.toElement().attribute("description_"+language); + if( plugin->description.isEmpty() ) plugin->description = node.toElement().attribute("description"); + plugin->urls = QStringList::split( ',',node.toElement().attribute("urls_"+language) ); + if( plugin->urls.isEmpty() ) plugin->urls = QStringList::split( ',',node.toElement().attribute("urls") ); + QStringList compressionTypeList = QStringList::split( ',',node.toElement().attribute("compression_type") ); + plugin->compressionType = (FormatInfo::CompressionType)0x0000; + for( QStringList::Iterator it = compressionTypeList.begin(); it != compressionTypeList.end(); ++it ) { + if( *it == "lossy" ) plugin->compressionType = FormatInfo::CompressionType( plugin->compressionType | FormatInfo::lossy ); + else if( *it == "lossless" ) plugin->compressionType = FormatInfo::CompressionType( plugin->compressionType | FormatInfo::lossless ); + else if( *it == "hybrid" ) plugin->compressionType = FormatInfo::CompressionType( plugin->compressionType | FormatInfo::hybrid ); + } + plugin->size = node.toElement().attribute("size","15000").toInt(); + + } + node = node.nextSibling(); + } + + return plugin; +} + diff --git a/src/pluginloader/formatinfoloader.h b/src/pluginloader/formatinfoloader.h new file mode 100755 index 0000000..f36f7fe --- /dev/null +++ b/src/pluginloader/formatinfoloader.h @@ -0,0 +1,67 @@ + + +#ifndef FORMATINFOLOADER_H +#define FORMATINFOLOADER_H + +#include +#include +#include + +/** + * @short The complete information about that format + * @author Daniel Faust + * @version 0.3 + */ +class FormatInfo +{ +public: + /** + * Constructor + */ + FormatInfo(); + + /** + * Destructor + */ + virtual ~FormatInfo(); + + QStringList mime_types; + QStringList extensions; + QString description; + QStringList urls; + enum CompressionType { + lossy = 0x0001, // encode with loss + lossless = 0x0002, // encode without loss + hybrid = 0x0004 // encode a file with loss and a correction file + } compressionType; + int size; +}; + +/** + * @short The format info loader that provides information about the compression type and a format description + * @author Daniel Faust + * @version 0.3 + */ +class FormatInfoLoader : public QObject +{ + Q_OBJECT +public: + /** + * Constructor + */ + FormatInfoLoader(); + + /** + * Destructor + */ + virtual ~FormatInfoLoader(); + + /** is this file a converter plugin and loadable? */ + bool verifyFile( QString ); + /** load a given file */ + FormatInfo* loadFile( QString ); + /** the dom tree for loading the xml file */ + QDomDocument domTree; +}; + +#endif // FORMATINFOLOADER_H diff --git a/src/pluginloader/pluginloaderbase.cpp b/src/pluginloader/pluginloaderbase.cpp new file mode 100755 index 0000000..d9a8413 --- /dev/null +++ b/src/pluginloader/pluginloaderbase.cpp @@ -0,0 +1,17 @@ + +#include "pluginloaderbase.h" + +PluginLoaderBase::PluginLoaderBase() +{} + +PluginLoaderBase::~PluginLoaderBase() +{} + +void PluginLoaderBase::unloadAll() +{} + +void PluginLoaderBase::unload( QString pluginName ) +{} + +void PluginLoaderBase::remove( QString pluginName ) +{} diff --git a/src/pluginloader/pluginloaderbase.h b/src/pluginloader/pluginloaderbase.h new file mode 100755 index 0000000..c35bebe --- /dev/null +++ b/src/pluginloader/pluginloaderbase.h @@ -0,0 +1,86 @@ + + +#ifndef PLUGINLOADERBASE_H +#define PLUGINLOADERBASE_H + +#include +#include +#include + +#include "config.h" + +// TODO implement rank everywhere + +/** + * @short The base for all pluginloaders + * @author Daniel Faust + * @version 0.3 + */ +class PluginLoaderBase : public QObject +{ + Q_OBJECT +public: + /** + * Do we recommend this backend to the user + */ + enum FeatureLevel + { + Full, // the backend provides full support + Most, // most features are supported + Basic // we'll have just basic support + }; + + /** + * Just a small enum for our sampling rate units + */ + enum Unit + { + Hz, + KHz + }; + + /** + * Constructor + */ + PluginLoaderBase(); + + /** + * Destructor + */ + virtual ~PluginLoaderBase(); + + /** a list of all plugin files that are loaded at the moment */ +// QStringList openPluginFiles; + + /** the dom tree for loading the xml file */ + QDomDocument domTree; + +public slots: + /** + * Unload all plugins + */ + void unloadAll(); + + /** + * Unoad a specific plugin with name @p pluginName + */ + void unload( QString pluginName ); + + /** + * Unoad a specific plugin with name @p pluginName and delete the plugin file + */ + void remove( QString pluginName ); +}; + +#endif // PLUGINLOADERBASE_H + + +/** + +Each plugin package contains 3 files: + - The plugin file ( $KDE_DIR/share/apps/soundkonverter/plugins/'filename' ) + - The format info file ( $KDE_DIR/share/apps/soundkonverter/format_infos/'lang'/'plugin'_'filename' ) + - The service menu ( $KDE_DIR/share/apps/konqueror/servicemenus/'filename' ) + +*/ + diff --git a/src/pluginloader/replaygainpluginloader.cpp b/src/pluginloader/replaygainpluginloader.cpp new file mode 100755 index 0000000..7ac11f6 --- /dev/null +++ b/src/pluginloader/replaygainpluginloader.cpp @@ -0,0 +1,116 @@ + +#include "replaygainpluginloader.h" + +#include + +#include + + +ReplayGainPlugin::ReplayGainPlugin() +{} + +ReplayGainPlugin::~ReplayGainPlugin() +{} + + +ReplayGainPluginLoader::ReplayGainPluginLoader() +{} + +ReplayGainPluginLoader::~ReplayGainPluginLoader() +{} + +int ReplayGainPluginLoader::verifyFile( QString fileName ) +{ + QFile opmlFile( fileName ); + if( !opmlFile.open( IO_ReadOnly ) ) { + return -1; + } + if( !domTree.setContent( &opmlFile ) ) { + return -1; + } + opmlFile.close(); + + QDomElement root = domTree.documentElement(); + if( root.attribute("type") != "replaygain" ) return -1; + int version; + QDomNode node; + node = root.firstChild(); + while( !node.isNull() ) { + if( node.isElement() && node.nodeName() == "info" ) { + version = node.toElement().attribute("version","0").toInt(); + break; + } + } + + return version; +} + +ReplayGainPlugin* ReplayGainPluginLoader::loadFile( QString fileName ) +{ + //int t_int; + //float t_float; + //QString t_str; + + ReplayGainPlugin* plugin = new ReplayGainPlugin(); + plugin->info.version = -1; // if something goes wrong, we can see that by looking at plugin->info.version + plugin->filePathName = fileName; + + QFile opmlFile( fileName ); + if( !opmlFile.open( IO_ReadOnly ) ) { + return plugin; + } + if( !domTree.setContent( &opmlFile ) ) { + return plugin; + } + opmlFile.close(); + + QDomElement root = domTree.documentElement(); + if( root.attribute("type") != "replaygain" ) return plugin; + QDomNode node;//, sub1Node; + node = root.firstChild(); + + while( !node.isNull() ) { + if( node.isElement() && node.nodeName() == "info" ) { + + plugin->info.name = node.toElement().attribute("name",i18n("Unknown Name")); + plugin->info.about = node.toElement().attribute("about",i18n("Sorry, no information available!")); + plugin->info.author = node.toElement().attribute("author",i18n("Unknown Author")); + plugin->info.version = node.toElement().attribute("version","0").toInt(); + + } + else if( node.isElement() && node.nodeName() == "replaygain" ) { + + plugin->replaygain.rank = node.toElement().attribute("rank","10").toInt(); + plugin->replaygain.bin = node.toElement().attribute( "bin" ); + plugin->replaygain.param = node.toElement().attribute("param"); + plugin->replaygain.silent_param = node.toElement().attribute("silent_param"); + plugin->replaygain.in_files = node.toElement().attribute("in_files"); + plugin->replaygain.output_single = node.toElement().attribute("output_single"); + plugin->replaygain.output_multiple = node.toElement().attribute("output_multiple"); + plugin->replaygain.mime_types = QStringList::split( ',', node.toElement().attribute("mime_types","application/octet-stream") ); + plugin->replaygain.force = node.toElement().attribute("force"); + plugin->replaygain.skip = node.toElement().attribute("skip"); + plugin->replaygain.track = node.toElement().attribute("track"); + plugin->replaygain.album = node.toElement().attribute("album"); + plugin->replaygain.remove = node.toElement().attribute("remove"); + + /*sub1Node = node.toElement().firstChild(); // obsolete + while( !sub1Node.isNull() ) { + if( sub1Node.isElement() && sub1Node.nodeName() == "test" ) { + + if( sub1Node.toElement().attribute("enabled") == "true" ) plugin->replaygain.test.enabled = true; + else plugin->replaygain.test.enabled = false; + plugin->replaygain.test.param = sub1Node.toElement().attribute("param"); + plugin->replaygain.test.output_track = sub1Node.toElement().attribute("output_track"); + plugin->replaygain.test.output_album = sub1Node.toElement().attribute("output_album"); + + } + sub1Node = sub1Node.nextSibling(); + }*/ + } + node = node.nextSibling(); + } + + return plugin; +} + diff --git a/src/pluginloader/replaygainpluginloader.h b/src/pluginloader/replaygainpluginloader.h new file mode 100755 index 0000000..d1c1237 --- /dev/null +++ b/src/pluginloader/replaygainpluginloader.h @@ -0,0 +1,89 @@ + + +#ifndef REPLAYGAINPLUGINLOADER_H +#define REPLAYGAINPLUGINLOADER_H + +#include "pluginloaderbase.h" + + +/** + * @short The complete data, how to use the backend + * @author Daniel Faust + * @version 0.3 + */ +class ReplayGainPlugin +{ +public: + /** + * Constructor + */ + ReplayGainPlugin(); + + /** + * Destructor + */ + virtual ~ReplayGainPlugin(); + + QString filePathName; // the file name of th plugin (needed to detect write permissions) + + struct Info + { + int version; // the version of our plugin (v0.2.1 = 201, v11.3 = 110300) + QString name; // the name of our plugin + QString author; // the author of the plugin + QString about; // a short information aboue the plugin + } info; + + struct ReplayGain + { + //PluginLoaderBase::FeatureLevel level; + int rank; + QString bin; + QString param; + QString silent_param; + QStringList mime_types; + QString in_files; + QString output_single; + QString output_multiple; + QString force; + QString skip; + QString track; // TODO remove track and album (put them into param) + QString album; + QString remove; + + /*struct Test // obsolete + { + bool enabled; + QString param; + QString output_track; + QString output_album; + } test;*/ + } replaygain; +}; + +/** + * @short The plugin loader for the replaygain plugins + * @author Daniel Faust + * @version 0.3 + */ +class ReplayGainPluginLoader : public PluginLoaderBase +{ + Q_OBJECT +public: + /** + * Constructor + */ + ReplayGainPluginLoader(); + + /** + * Destructor + */ + virtual ~ReplayGainPluginLoader(); + + /** is this file a replaygain plugin and loadable? */ + int verifyFile( QString ); + /** load a given file */ + ReplayGainPlugin* loadFile( QString ); +}; + +#endif // REPLAYGAINPLUGINLOADER_H diff --git a/src/pluginloader/ripperpluginloader.cpp b/src/pluginloader/ripperpluginloader.cpp new file mode 100755 index 0000000..9c1f9d4 --- /dev/null +++ b/src/pluginloader/ripperpluginloader.cpp @@ -0,0 +1,111 @@ + +#include "ripperpluginloader.h" + +#include + +#include + + +RipperPlugin::RipperPlugin() +{} + +RipperPlugin::~RipperPlugin() +{} + + +RipperPluginLoader::RipperPluginLoader() +{} + +RipperPluginLoader::~RipperPluginLoader() +{} + +int RipperPluginLoader::verifyFile( QString fileName ) +{ + QFile opmlFile( fileName ); + if( !opmlFile.open( IO_ReadOnly ) ) { + return -1; + } + if( !domTree.setContent( &opmlFile ) ) { + return -1; + } + opmlFile.close(); + + QDomElement root = domTree.documentElement(); + if( root.attribute("type") != "ripper" ) return -1; + int version; + QDomNode node; + node = root.firstChild(); + while( !node.isNull() ) { + if( node.isElement() && node.nodeName() == "info" ) { + version = node.toElement().attribute("version","0").toInt(); + break; + } + } + + return version; +} + +RipperPlugin* RipperPluginLoader::loadFile( QString fileName ) +{ + int t_int; + float t_float; + QString t_str; + + RipperPlugin* plugin = new RipperPlugin(); + plugin->info.version = -1; // if something goes wrong, we can see that by looking at plugin->info.version + plugin->filePathName = fileName; + + QFile opmlFile( fileName ); + if( !opmlFile.open( IO_ReadOnly ) ) { + return plugin; + } + if( !domTree.setContent( &opmlFile ) ) { + return plugin; + } + opmlFile.close(); + + QDomElement root = domTree.documentElement(); + if( root.attribute("type") != "ripper" ) return plugin; + QDomNode node, sub1Node; + node = root.firstChild(); + + while( !node.isNull() ) { + if( node.isElement() && node.nodeName() == "info" ) { + + plugin->info.name = node.toElement().attribute("name",i18n("Unknown Name")); + plugin->info.about = node.toElement().attribute("about",i18n("Sorry, no information available!")); + plugin->info.author = node.toElement().attribute("author",i18n("Unknown Author")); + plugin->info.version = node.toElement().attribute("version","0").toInt(); + + } + else if( node.isElement() && node.nodeName() == "rip" ) { + + plugin->rip.rank = node.toElement().attribute("rank","10").toInt(); + plugin->rip.bin = node.toElement().attribute( "bin" ); + plugin->rip.param = node.toElement().attribute("param"); + plugin->rip.silent_param = node.toElement().attribute("silent_param"); + plugin->rip.out_file = node.toElement().attribute("out_file"); + plugin->rip.track = node.toElement().attribute("track"); + plugin->rip.device = node.toElement().attribute("device"); + plugin->rip.overwrite = node.toElement().attribute("overwrite"); + plugin->rip.output = node.toElement().attribute("output"); + + sub1Node = node.toElement().firstChild(); + while( !sub1Node.isNull() ) { + if( sub1Node.isElement() && sub1Node.nodeName() == "full_disc" ) { + + if( sub1Node.toElement().attribute("enabled") == "true" ) plugin->rip.full_disc.enabled = true; + else plugin->rip.full_disc.enabled = false; + plugin->rip.full_disc.param = sub1Node.toElement().attribute("param"); + plugin->rip.full_disc.output = sub1Node.toElement().attribute("output"); + + } + sub1Node = sub1Node.nextSibling(); + } + } + node = node.nextSibling(); + } + + return plugin; +} + diff --git a/src/pluginloader/ripperpluginloader.h b/src/pluginloader/ripperpluginloader.h new file mode 100755 index 0000000..6cf965e --- /dev/null +++ b/src/pluginloader/ripperpluginloader.h @@ -0,0 +1,84 @@ + + +#ifndef RIPPERPLUGINLOADER_H +#define RIPPERPLUGINLOADER_H + +#include "pluginloaderbase.h" + + +/** + * @short The complete data, how to use the backend + * @author Daniel Faust + * @version 0.3 + */ +class RipperPlugin +{ +public: + /** + * Constructor + */ + RipperPlugin(); + + /** + * Destructor + */ + virtual ~RipperPlugin(); + + QString filePathName; // the file name of th plugin (needed to detect write permissions) + + struct Info + { + int version; // the version of our plugin (v0.2.1 = 201, v11.3 = 110300) + QString name; // the name of our plugin + QString author; // the author of the plugin + QString about; // a short information aboue the plugin + } info; + + struct Rip + { + //PluginLoaderBase::FeatureLevel level; + int rank; + QString bin; + QString param; + QString silent_param; + QString out_file; + QString track; + QString device; + QString overwrite; + QString output; + + struct FullDisc + { + bool enabled; + QString param; + QString output; + } full_disc; + } rip; +}; + +/** + * @short The plugin loader for the ripper plugins + * @author Daniel Faust + * @version 0.3 + */ +class RipperPluginLoader : public PluginLoaderBase +{ + Q_OBJECT +public: + /** + * Constructor + */ + RipperPluginLoader(); + + /** + * Destructor + */ + virtual ~RipperPluginLoader(); + + /** is this file a ripper plugin and loadable? */ + int verifyFile( QString ); + /** load a given file */ + RipperPlugin* loadFile( QString ); +}; + +#endif // RIPPERPLUGINLOADER_H diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am new file mode 100755 index 0000000..f3dea7a --- /dev/null +++ b/src/plugins/Makefile.am @@ -0,0 +1,5 @@ + +pluginsdir = $(kde_datadir)/soundkonverter/plugins +format_infos_endir = $(kde_datadir)/soundkonverter/format_infos/en + +SUBDIRS = format_infos mime_types plugins diff --git a/src/plugins/format_infos/3gp.xml b/src/plugins/format_infos/3gp.xml new file mode 100755 index 0000000..ff6a621 --- /dev/null +++ b/src/plugins/format_infos/3gp.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/Makefile.am b/src/plugins/format_infos/Makefile.am new file mode 100644 index 0000000..3f45bea --- /dev/null +++ b/src/plugins/format_infos/Makefile.am @@ -0,0 +1,5 @@ +format_infosdir = $(kde_datadir)/soundkonverter/format_infos +format_infos_DATA = 3gp.xml aac.xml ac3.xml aiff.xml amr.xml ape.xml au.xml \ + avi.xml bonk.xml flac.xml la.xml m4a.xml mid.xml mod.xml mp2.xml mp3.xml \ + mpc.xml ofc.xml ofr.xml ofs.xml ogg.xml pac.xml qt.xml ra.xml shn.xml spx.xml \ + tta.xml wma.xml wv.xml wvc.xml diff --git a/src/plugins/format_infos/aac.xml b/src/plugins/format_infos/aac.xml new file mode 100755 index 0000000..ad24c96 --- /dev/null +++ b/src/plugins/format_infos/aac.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/ac3.xml b/src/plugins/format_infos/ac3.xml new file mode 100755 index 0000000..d4249b7 --- /dev/null +++ b/src/plugins/format_infos/ac3.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/aiff.xml b/src/plugins/format_infos/aiff.xml new file mode 100644 index 0000000..ca572d6 --- /dev/null +++ b/src/plugins/format_infos/aiff.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/amr.xml b/src/plugins/format_infos/amr.xml new file mode 100755 index 0000000..2ce353e --- /dev/null +++ b/src/plugins/format_infos/amr.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/ape.xml b/src/plugins/format_infos/ape.xml new file mode 100755 index 0000000..de0d7da --- /dev/null +++ b/src/plugins/format_infos/ape.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/au.xml b/src/plugins/format_infos/au.xml new file mode 100755 index 0000000..cf98e76 --- /dev/null +++ b/src/plugins/format_infos/au.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/avi.xml b/src/plugins/format_infos/avi.xml new file mode 100755 index 0000000..24836e6 --- /dev/null +++ b/src/plugins/format_infos/avi.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/bonk.xml b/src/plugins/format_infos/bonk.xml new file mode 100755 index 0000000..e2f18f2 --- /dev/null +++ b/src/plugins/format_infos/bonk.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/flac.xml b/src/plugins/format_infos/flac.xml new file mode 100755 index 0000000..e03e0ce --- /dev/null +++ b/src/plugins/format_infos/flac.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/la.xml b/src/plugins/format_infos/la.xml new file mode 100755 index 0000000..eb2759b --- /dev/null +++ b/src/plugins/format_infos/la.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/m4a.xml b/src/plugins/format_infos/m4a.xml new file mode 100755 index 0000000..ec437f3 --- /dev/null +++ b/src/plugins/format_infos/m4a.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/mid.xml b/src/plugins/format_infos/mid.xml new file mode 100755 index 0000000..bf1b613 --- /dev/null +++ b/src/plugins/format_infos/mid.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/mod.xml b/src/plugins/format_infos/mod.xml new file mode 100755 index 0000000..cfc3443 --- /dev/null +++ b/src/plugins/format_infos/mod.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/mp2.xml b/src/plugins/format_infos/mp2.xml new file mode 100755 index 0000000..bfa4740 --- /dev/null +++ b/src/plugins/format_infos/mp2.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/mp3.xml b/src/plugins/format_infos/mp3.xml new file mode 100755 index 0000000..f57d0c6 --- /dev/null +++ b/src/plugins/format_infos/mp3.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/mpc.xml b/src/plugins/format_infos/mpc.xml new file mode 100755 index 0000000..2d8dda1 --- /dev/null +++ b/src/plugins/format_infos/mpc.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/ofc.xml b/src/plugins/format_infos/ofc.xml new file mode 100755 index 0000000..edeee6f --- /dev/null +++ b/src/plugins/format_infos/ofc.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/ofr.xml b/src/plugins/format_infos/ofr.xml new file mode 100755 index 0000000..f48581d --- /dev/null +++ b/src/plugins/format_infos/ofr.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/ofs.xml b/src/plugins/format_infos/ofs.xml new file mode 100755 index 0000000..b533c44 --- /dev/null +++ b/src/plugins/format_infos/ofs.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/ogg.xml b/src/plugins/format_infos/ogg.xml new file mode 100755 index 0000000..4bacbc9 --- /dev/null +++ b/src/plugins/format_infos/ogg.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/pac.xml b/src/plugins/format_infos/pac.xml new file mode 100755 index 0000000..a1b863c --- /dev/null +++ b/src/plugins/format_infos/pac.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/qt.xml b/src/plugins/format_infos/qt.xml new file mode 100755 index 0000000..19a2ae8 --- /dev/null +++ b/src/plugins/format_infos/qt.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/ra.xml b/src/plugins/format_infos/ra.xml new file mode 100755 index 0000000..4c7a822 --- /dev/null +++ b/src/plugins/format_infos/ra.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/shn.xml b/src/plugins/format_infos/shn.xml new file mode 100755 index 0000000..db33e81 --- /dev/null +++ b/src/plugins/format_infos/shn.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/spx.xml b/src/plugins/format_infos/spx.xml new file mode 100755 index 0000000..7f97476 --- /dev/null +++ b/src/plugins/format_infos/spx.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/tta.xml b/src/plugins/format_infos/tta.xml new file mode 100755 index 0000000..0d9bb7c --- /dev/null +++ b/src/plugins/format_infos/tta.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/wma.xml b/src/plugins/format_infos/wma.xml new file mode 100755 index 0000000..53ccbb8 --- /dev/null +++ b/src/plugins/format_infos/wma.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/wv.xml b/src/plugins/format_infos/wv.xml new file mode 100755 index 0000000..d4fab5a --- /dev/null +++ b/src/plugins/format_infos/wv.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/format_infos/wvc.xml b/src/plugins/format_infos/wvc.xml new file mode 100755 index 0000000..33698b7 --- /dev/null +++ b/src/plugins/format_infos/wvc.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/plugins/mime_types/Makefile.am b/src/plugins/mime_types/Makefile.am new file mode 100755 index 0000000..cedeba7 --- /dev/null +++ b/src/plugins/mime_types/Makefile.am @@ -0,0 +1,11 @@ +audio_mimedir = $(kde_mimedir)/audio +application_mimedir = $(kde_mimedir)/application +video_mimedir = $(kde_mimedir)/video +audio_mime_DATA = amr.soundkonverter.desktop x-ape.soundkonverter.desktop x-bonk.soundkonverter.desktop x-pac.soundkonverter.desktop \ + x-tta.soundkonverter.desktop x-wavpack-correction.soundkonverter.desktop x-wavpack.soundkonverter.desktop +application_mime_DATA = x-la.soundkonverter.desktop \ + x-ofc.soundkonverter.desktop \ + x-ofr.soundkonverter.desktop \ + x-ofs.soundkonverter.desktop \ + x-shorten.soundkonverter.desktop +video_mime_DATA = x-flv.soundkonverter.desktop diff --git a/src/plugins/mime_types/amr.soundkonverter.desktop b/src/plugins/mime_types/amr.soundkonverter.desktop new file mode 100755 index 0000000..fc572cf --- /dev/null +++ b/src/plugins/mime_types/amr.soundkonverter.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Comment=Adaptive Multirate audio file +Hidden=false +Icon=audio +MimeType=audio/amr +Patterns=*.amr;*.AMR;*.Amr +Type=MimeType +X-KDE-AutoEmbed=false diff --git a/src/plugins/mime_types/x-ape.soundkonverter.desktop b/src/plugins/mime_types/x-ape.soundkonverter.desktop new file mode 100755 index 0000000..cda24b6 --- /dev/null +++ b/src/plugins/mime_types/x-ape.soundkonverter.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Comment=Monkey's Audio file +Hidden=false +Icon=audio +MimeType=audio/x-ape +Patterns=*.ape;*.APE;*.mac;*.MAC;*.ApE;*.aPE;*.APe;*.apE;*.APe;*.aPe +Type=MimeType +X-KDE-AutoEmbed=false diff --git a/src/plugins/mime_types/x-bonk.soundkonverter.desktop b/src/plugins/mime_types/x-bonk.soundkonverter.desktop new file mode 100755 index 0000000..7e2fc78 --- /dev/null +++ b/src/plugins/mime_types/x-bonk.soundkonverter.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Comment=BONK +Hidden=false +Icon=audio +MimeType=audio/x-bonk +Patterns=*.bonk;*.BONK;*.Bonk;*.BOnk +Type=MimeType +X-KDE-AutoEmbed=false diff --git a/src/plugins/mime_types/x-flv.soundkonverter.desktop b/src/plugins/mime_types/x-flv.soundkonverter.desktop new file mode 100755 index 0000000..d220911 --- /dev/null +++ b/src/plugins/mime_types/x-flv.soundkonverter.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Comment=Flash Video +Hidden=false +Icon=video +MimeType=video/x-flv +Patterns=*.flv;*.FLV +Type=MimeType +X-KDE-AutoEmbed=false diff --git a/src/plugins/mime_types/x-la.soundkonverter.desktop b/src/plugins/mime_types/x-la.soundkonverter.desktop new file mode 100755 index 0000000..27edf9f --- /dev/null +++ b/src/plugins/mime_types/x-la.soundkonverter.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Comment=Lossless Audio file +Hidden=false +Icon=audio +MimeType=application/x-la +Patterns=*.la;*.LA;*.La;*.lA +Type=MimeType +X-KDE-AutoEmbed=false diff --git a/src/plugins/mime_types/x-ofc.soundkonverter.desktop b/src/plugins/mime_types/x-ofc.soundkonverter.desktop new file mode 100755 index 0000000..7f62e25 --- /dev/null +++ b/src/plugins/mime_types/x-ofc.soundkonverter.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Comment=OptimFROG DualStream correction file +Hidden=false +Icon=audio +MimeType=application/x-ofc +Patterns=*.ofc;*.OFC +Type=MimeType +X-KDE-AutoEmbed=false diff --git a/src/plugins/mime_types/x-ofr.soundkonverter.desktop b/src/plugins/mime_types/x-ofr.soundkonverter.desktop new file mode 100755 index 0000000..f757caa --- /dev/null +++ b/src/plugins/mime_types/x-ofr.soundkonverter.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Comment=OptimFROG file +Hidden=false +Icon=audio +MimeType=application/x-ofr +Patterns=*.ofr;*.OFR;*.OfR;*.OFr;*.oFR;*.ofR +Type=MimeType +X-KDE-AutoEmbed=false diff --git a/src/plugins/mime_types/x-ofs.soundkonverter.desktop b/src/plugins/mime_types/x-ofs.soundkonverter.desktop new file mode 100755 index 0000000..cecf374 --- /dev/null +++ b/src/plugins/mime_types/x-ofs.soundkonverter.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Comment=OptimFROG DualStream file +Hidden=false +Icon=audio +MimeType=application/x-ofs +Patterns=*.ofs;*.OFS;*.OfS;*.OFs;*.oFS;*.ofS +Type=MimeType +X-KDE-AutoEmbed=false diff --git a/src/plugins/mime_types/x-pac.soundkonverter.desktop b/src/plugins/mime_types/x-pac.soundkonverter.desktop new file mode 100755 index 0000000..7cef430 --- /dev/null +++ b/src/plugins/mime_types/x-pac.soundkonverter.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Comment=Pac file +Hidden=false +Icon=audio +MimeType=audio/x-pac +Patterns=*.pac;*.PAC;*.lpac;*.LPAC;*.PaC;*.PAc;*.pAC;*.paC;*.LPaC;*.LPAc +Type=MimeType +X-KDE-AutoEmbed=false diff --git a/src/plugins/mime_types/x-shorten.soundkonverter.desktop b/src/plugins/mime_types/x-shorten.soundkonverter.desktop new file mode 100755 index 0000000..01e5d47 --- /dev/null +++ b/src/plugins/mime_types/x-shorten.soundkonverter.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Comment=Shorten file +Hidden=false +Icon=audio +MimeType=application/x-shorten +Patterns=*.shn;*.SHN;*.ShN;*.sHN;*.SHn;*.shN;*.sHn +Type=MimeType +X-KDE-AutoEmbed=false diff --git a/src/plugins/mime_types/x-tta.soundkonverter.desktop b/src/plugins/mime_types/x-tta.soundkonverter.desktop new file mode 100755 index 0000000..65050a5 --- /dev/null +++ b/src/plugins/mime_types/x-tta.soundkonverter.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Comment=The True Audio Codec +Hidden=false +Icon=audio +MimeType=audio/x-tta +Patterns=*.tta;*.TTA +Type=MimeType +X-KDE-AutoEmbed=false diff --git a/src/plugins/mime_types/x-wavpack-correction.soundkonverter.desktop b/src/plugins/mime_types/x-wavpack-correction.soundkonverter.desktop new file mode 100755 index 0000000..a032b0b --- /dev/null +++ b/src/plugins/mime_types/x-wavpack-correction.soundkonverter.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Comment=WavPack file +Hidden=false +Icon=audio +MimeType=audio/x-wavpack-correction +Patterns=*.wvc;*.WVC +Type=MimeType +X-KDE-AutoEmbed=false diff --git a/src/plugins/mime_types/x-wavpack.soundkonverter.desktop b/src/plugins/mime_types/x-wavpack.soundkonverter.desktop new file mode 100755 index 0000000..14ae9b0 --- /dev/null +++ b/src/plugins/mime_types/x-wavpack.soundkonverter.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Comment=WavPack file +Hidden=false +Icon=audio +MimeType=audio/x-wavpack +Patterns=*.wv;*.WV;*.wV;*.Wv +Type=MimeType +X-KDE-AutoEmbed=false diff --git a/src/plugins/plugins/110.oggvorbis.soundkonverter.xml b/src/plugins/plugins/110.oggvorbis.soundkonverter.xml new file mode 100755 index 0000000..592fa5c --- /dev/null +++ b/src/plugins/plugins/110.oggvorbis.soundkonverter.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/plugins/120.lame.soundkonverter.xml b/src/plugins/plugins/120.lame.soundkonverter.xml new file mode 100755 index 0000000..eb2adba --- /dev/null +++ b/src/plugins/plugins/120.lame.soundkonverter.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/plugins/122.twolame.soundkonverter.xml b/src/plugins/plugins/122.twolame.soundkonverter.xml new file mode 100755 index 0000000..da081c7 --- /dev/null +++ b/src/plugins/plugins/122.twolame.soundkonverter.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/plugins/plugins/123.toolame.soundkonverter.xml b/src/plugins/plugins/123.toolame.soundkonverter.xml new file mode 100755 index 0000000..c4a7e2a --- /dev/null +++ b/src/plugins/plugins/123.toolame.soundkonverter.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/plugins/plugins/125.gogo.soundkonverter.xml b/src/plugins/plugins/125.gogo.soundkonverter.xml new file mode 100755 index 0000000..ebe351c --- /dev/null +++ b/src/plugins/plugins/125.gogo.soundkonverter.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/plugins/plugins/127.faac.soundkonverter.xml b/src/plugins/plugins/127.faac.soundkonverter.xml new file mode 100755 index 0000000..1018d60 --- /dev/null +++ b/src/plugins/plugins/127.faac.soundkonverter.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/plugins/plugins/130.musepack.soundkonverter.xml b/src/plugins/plugins/130.musepack.soundkonverter.xml new file mode 100755 index 0000000..6fd61e1 --- /dev/null +++ b/src/plugins/plugins/130.musepack.soundkonverter.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/plugins/plugins/132.aften.soundkonverter.xml b/src/plugins/plugins/132.aften.soundkonverter.xml new file mode 100755 index 0000000..1561006 --- /dev/null +++ b/src/plugins/plugins/132.aften.soundkonverter.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/plugins/plugins/135.flac.soundkonverter.xml b/src/plugins/plugins/135.flac.soundkonverter.xml new file mode 100755 index 0000000..8d5c0c7 --- /dev/null +++ b/src/plugins/plugins/135.flac.soundkonverter.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/plugins/plugins/136.flake.soundkonverter.xml b/src/plugins/plugins/136.flake.soundkonverter.xml new file mode 100755 index 0000000..1ec9b0d --- /dev/null +++ b/src/plugins/plugins/136.flake.soundkonverter.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/plugins/plugins/137.mac.soundkonverter.xml b/src/plugins/plugins/137.mac.soundkonverter.xml new file mode 100755 index 0000000..f0421c7 --- /dev/null +++ b/src/plugins/plugins/137.mac.soundkonverter.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/plugins/plugins/140.mplayer.soundkonverter.xml b/src/plugins/plugins/140.mplayer.soundkonverter.xml new file mode 100755 index 0000000..d2bdc2d --- /dev/null +++ b/src/plugins/plugins/140.mplayer.soundkonverter.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/plugins/plugins/145.ffmpeg.soundkonverter.xml b/src/plugins/plugins/145.ffmpeg.soundkonverter.xml new file mode 100755 index 0000000..e2613c4 --- /dev/null +++ b/src/plugins/plugins/145.ffmpeg.soundkonverter.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/plugins/plugins/146.ffmpeg-lossless.soundkonverter.xml b/src/plugins/plugins/146.ffmpeg-lossless.soundkonverter.xml new file mode 100755 index 0000000..d33ae6a --- /dev/null +++ b/src/plugins/plugins/146.ffmpeg-lossless.soundkonverter.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/plugins/plugins/150.shorten.soundkonverter.xml b/src/plugins/plugins/150.shorten.soundkonverter.xml new file mode 100755 index 0000000..8e64a13 --- /dev/null +++ b/src/plugins/plugins/150.shorten.soundkonverter.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/plugins/plugins/151.tta.soundkonverter.xml b/src/plugins/plugins/151.tta.soundkonverter.xml new file mode 100755 index 0000000..27a3f97 --- /dev/null +++ b/src/plugins/plugins/151.tta.soundkonverter.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/plugins/plugins/153.bonk.soundkonverter.xml b/src/plugins/plugins/153.bonk.soundkonverter.xml new file mode 100755 index 0000000..ca3d8c2 --- /dev/null +++ b/src/plugins/plugins/153.bonk.soundkonverter.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/plugins/plugins/155.optimfrog.soundkonverter.xml b/src/plugins/plugins/155.optimfrog.soundkonverter.xml new file mode 100755 index 0000000..800c881 --- /dev/null +++ b/src/plugins/plugins/155.optimfrog.soundkonverter.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/plugins/plugins/156.optimfrog-dualstream.soundkonverter.xml b/src/plugins/plugins/156.optimfrog-dualstream.soundkonverter.xml new file mode 100755 index 0000000..80ba27a --- /dev/null +++ b/src/plugins/plugins/156.optimfrog-dualstream.soundkonverter.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/plugins/plugins/158.wavpack.soundkonverter.xml b/src/plugins/plugins/158.wavpack.soundkonverter.xml new file mode 100755 index 0000000..96a5842 --- /dev/null +++ b/src/plugins/plugins/158.wavpack.soundkonverter.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/plugins/plugins/160.lac.soundkonverter.xml b/src/plugins/plugins/160.lac.soundkonverter.xml new file mode 100755 index 0000000..65f0a16 --- /dev/null +++ b/src/plugins/plugins/160.lac.soundkonverter.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/plugins/plugins/165.lpac.soundkonverter.xml b/src/plugins/plugins/165.lpac.soundkonverter.xml new file mode 100755 index 0000000..2a368b9 --- /dev/null +++ b/src/plugins/plugins/165.lpac.soundkonverter.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/plugins/plugins/170.speex.soundkonverter.xml b/src/plugins/plugins/170.speex.soundkonverter.xml new file mode 100755 index 0000000..24b1f5d --- /dev/null +++ b/src/plugins/plugins/170.speex.soundkonverter.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/plugins/plugins/180.timidity.soundkonverter.xml b/src/plugins/plugins/180.timidity.soundkonverter.xml new file mode 100755 index 0000000..8f8c918 --- /dev/null +++ b/src/plugins/plugins/180.timidity.soundkonverter.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/plugins/plugins/190.sox.soundkonverter.xml b/src/plugins/plugins/190.sox.soundkonverter.xml new file mode 100644 index 0000000..4de2401 --- /dev/null +++ b/src/plugins/plugins/190.sox.soundkonverter.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/plugins/plugins/210.vorbisgain.soundkonverter.xml b/src/plugins/plugins/210.vorbisgain.soundkonverter.xml new file mode 100755 index 0000000..7848503 --- /dev/null +++ b/src/plugins/plugins/210.vorbisgain.soundkonverter.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/plugins/plugins/220.mp3gain.soundkonverter.xml b/src/plugins/plugins/220.mp3gain.soundkonverter.xml new file mode 100755 index 0000000..7058439 --- /dev/null +++ b/src/plugins/plugins/220.mp3gain.soundkonverter.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/plugins/plugins/225.aacgain.soundkonverter.xml b/src/plugins/plugins/225.aacgain.soundkonverter.xml new file mode 100755 index 0000000..84f1774 --- /dev/null +++ b/src/plugins/plugins/225.aacgain.soundkonverter.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/plugins/plugins/230.replaygain.soundkonverter.xml b/src/plugins/plugins/230.replaygain.soundkonverter.xml new file mode 100755 index 0000000..1a0a0f6 --- /dev/null +++ b/src/plugins/plugins/230.replaygain.soundkonverter.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/plugins/plugins/240.metaflac.soundkonverter.xml b/src/plugins/plugins/240.metaflac.soundkonverter.xml new file mode 100755 index 0000000..25d5c7d --- /dev/null +++ b/src/plugins/plugins/240.metaflac.soundkonverter.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/plugins/plugins/250.wvgain.soundkonverter.xml b/src/plugins/plugins/250.wvgain.soundkonverter.xml new file mode 100755 index 0000000..fa502c5 --- /dev/null +++ b/src/plugins/plugins/250.wvgain.soundkonverter.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/plugins/plugins/310.cdda2wav.soundkonverter.xml b/src/plugins/plugins/310.cdda2wav.soundkonverter.xml new file mode 100755 index 0000000..1df26a8 --- /dev/null +++ b/src/plugins/plugins/310.cdda2wav.soundkonverter.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/plugins/plugins/320.cdparanoia.soundkonverter.xml b/src/plugins/plugins/320.cdparanoia.soundkonverter.xml new file mode 100755 index 0000000..177f9c4 --- /dev/null +++ b/src/plugins/plugins/320.cdparanoia.soundkonverter.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/plugins/plugins/Makefile.am b/src/plugins/plugins/Makefile.am new file mode 100644 index 0000000..8471ac6 --- /dev/null +++ b/src/plugins/plugins/Makefile.am @@ -0,0 +1,14 @@ +pluginsdir = $(kde_datadir)/soundkonverter/plugins + +plugins_DATA = 110.oggvorbis.soundkonverter.xml 120.lame.soundkonverter.xml \ + 122.twolame.soundkonverter.xml 123.toolame.soundkonverter.xml 125.gogo.soundkonverter.xml \ + 127.faac.soundkonverter.xml 130.musepack.soundkonverter.xml 132.aften.soundkonverter.xml \ + 135.flac.soundkonverter.xml 136.flake.soundkonverter.xml 137.mac.soundkonverter.xml \ + 140.mplayer.soundkonverter.xml 145.ffmpeg.soundkonverter.xml 146.ffmpeg-lossless.soundkonverter.xml \ + 150.shorten.soundkonverter.xml 151.tta.soundkonverter.xml 153.bonk.soundkonverter.xml \ + 155.optimfrog.soundkonverter.xml 156.optimfrog-dualstream.soundkonverter.xml \ + 158.wavpack.soundkonverter.xml 160.lac.soundkonverter.xml 165.lpac.soundkonverter.xml \ + 170.speex.soundkonverter.xml 180.timidity.soundkonverter.xml 190.sox.soundkonverter.xml \ + 210.vorbisgain.soundkonverter.xml 220.mp3gain.soundkonverter.xml 225.aacgain.soundkonverter.xml \ + 230.replaygain.soundkonverter.xml 240.metaflac.soundkonverter.xml 250.wvgain.soundkonverter.xml \ + 310.cdda2wav.soundkonverter.xml 320.cdparanoia.soundkonverter.xml diff --git a/src/plugins/rohling/Makefile.am b/src/plugins/rohling/Makefile.am new file mode 100755 index 0000000..a346d10 --- /dev/null +++ b/src/plugins/rohling/Makefile.am @@ -0,0 +1,6 @@ +pluginsdir = $(kde_datadir)/soundkonverter/plugins +format_infos_endir = $(kde_datadir)/soundkonverter/format_infos/en +plugins_DATA = 127.faac-280.soundkonverter.xml +format_infos_en_DATA = faac_3gp.280.xml \ + faac_aac.280.xml \ + faac_m4a.280.xml diff --git a/src/progressindicator.cpp b/src/progressindicator.cpp new file mode 100755 index 0000000..91a40a2 --- /dev/null +++ b/src/progressindicator.cpp @@ -0,0 +1,144 @@ + +#include "progressindicator.h" + +#include +#include +#include +#include + +#include +#include +//#include +//#include +// #include + + +ProgressIndicator::ProgressIndicator( KSystemTray* _systemTray, QWidget* parent, const char* name ) + : QWidget( parent, name ) +{ + systemTray = _systemTray; + + time = processedTime = 0; + + QGridLayout *grid = new QGridLayout( this, 1, 1, 0, 6, "grid" ); + + QHBoxLayout *box = new QHBoxLayout( ); + grid->addLayout( box, 0, 0 ); + + pBar = new QProgressBar( this, "pBar" ); + box->addWidget( pBar ); + + QGridLayout *statusChildGrid = new QGridLayout( box, 2, 2, 6, "statusChildGrid" ); + + QLabel *lSpeedText = new QLabel( i18n("Speed")+":", this, "lSpeedText" ); + statusChildGrid->addWidget( lSpeedText, 0, 0, Qt::AlignVCenter ); + + lSpeed = new QLabel( "0.0x", this, "lSpeed" ); + lSpeed->setFont( QFont( "Courier" ) ); + statusChildGrid->addWidget( lSpeed, 0, 1, Qt::AlignVCenter | Qt::AlignRight ); + speedTime.setHMS( 24, 0, 0 ); + + QLabel *lTimeText = new QLabel( i18n("Time remaining")+":", this, "lTimeText" ); + statusChildGrid->addWidget( lTimeText, 1, 0, Qt::AlignVCenter ); + + lTime = new QLabel( "00:00", this, "lTime" ); + lTime->setFont( QFont( "Courier" ) ); + statusChildGrid->addWidget( lTime, 1, 1, Qt::AlignVCenter | Qt::AlignRight ); + elapsedTime.setHMS( 24, 0, 0 ); + + QToolTip::add( systemTray, i18n("Waiting") ); +} + +ProgressIndicator::~ProgressIndicator() +{} + +void ProgressIndicator::increaseTime( float t ) +{ + time += t; +// kdDebug() << "increaseTime: " << time << " (" << t << ")" << endl; +} + +void ProgressIndicator::decreaseTime( float t ) +{ + time -= t; +// kdDebug() << "decreaseTime: " << time << " (" << t << ")" << endl; +} + +void ProgressIndicator::countTime( float t ) +{ + processedTime += t; +// kdDebug() << "countTime: " << processedTime << " (" << t << ")" << endl; +} + +void ProgressIndicator::uncountTime( float t ) +{ + processedTime -= t; +// kdDebug() << "uncountTime: " << processedTime << " (" << t << ")" << endl; +} + +void ProgressIndicator::setTime( float t ) +{ + time = t; +// kdDebug() << "setTime: " << time << " (" << t << ")" << endl; +} + +void ProgressIndicator::finished( float t ) +{ + time = t; +// kdDebug() << "finished: " << time << " (" << t << ")" << endl; + processedTime = 0; + pBar->setProgress( 100, 100 ); + elapsedTime.setHMS( 24, 0, 0 ); + lTime->setText( "00:00" ); + speedTime.setHMS( 24, 0, 0 ); + lSpeed->setText( "0.0x" ); + QToolTip::add( systemTray, i18n("Finished") ); + emit setTitle( i18n("Finished") ); +} + +void ProgressIndicator::update( float t ) +{ +// kdDebug() << "update: " << (processedTime + t) << " / " << time << endl; + pBar->setProgress( int(processedTime + t), int(time) ); + float fPercent; +// if( pBar->totalSteps() > 0 ) fPercent = pBar->progress() * 100 / pBar->totalSteps(); + if( pBar->totalSteps() > 0 ) fPercent = (processedTime+t)*100.0f / time; + else fPercent = 0.1f; + + if( !elapsedTime.isValid() ) elapsedTime.start(); + if( !speedTime.isValid() ) speedTime.start(); + if( speedTime.elapsed() > 1000 ) { + if( elapsedTime.elapsed() > 10000 ) { +// int tim = (int)( 1 + ((100/fPercent)-1) * (elapsedTime.elapsed()/1000) ); + int tim = (int)(( 1.0f + ((100.0f/fPercent)-1.0f) * (elapsedTime.elapsed()/1000.0f) )); + //float fPercent = pBar->progress() / pBar->totalSteps(); + //int tim = (int)( 1 + (elapsedTime.elapsed()/fPercent - elapsedTime.elapsed()) / 1000 ); + if( tim >= 0 && tim < 1000000 ) { + int sec = tim % 60; + int min = ( tim / 60 ) % 60; + int hou = tim / 3600; + QString timeLeft; + if( hou > 0 ) + timeLeft.sprintf( "%d:%02d:%02d", hou, min, sec ); + else + timeLeft.sprintf( "%02d:%02d", min, sec ); + lTime->setText( timeLeft ); + } + } + + int tim = speedTime.restart() / 1000; + float speed = ( processedTime + t - speedProcessedTime ) / tim; + speedProcessedTime = processedTime + t; + if( speed >= 0.0f && speed < 100000.0f ) { + QString actSpeed; + actSpeed.sprintf( "%.1fx", speed ); + lSpeed->setText( actSpeed ); + } + } + + QString percent; + percent.sprintf( "%i%%", (int)fPercent ); + emit setTitle( percent ); + QToolTip::add( systemTray, percent ); +} + diff --git a/src/progressindicator.h b/src/progressindicator.h new file mode 100755 index 0000000..873a4f9 --- /dev/null +++ b/src/progressindicator.h @@ -0,0 +1,61 @@ + + +#ifndef PROGRESSINDICATOR_H +#define PROGRESSINDICATOR_H + +#include +#include + +class QProgressBar; +class QLabel; +class KSystemTray; + +/** + * @short Displays the current progress + * @author Daniel Faust + * @version 0.3 + */ +class ProgressIndicator : public QWidget +{ + Q_OBJECT +public: + /** + * Constructor + */ + ProgressIndicator( KSystemTray* _systemTray, QWidget* parent = 0, const char* name = 0 ); + + /** + * Destructor + */ + virtual ~ProgressIndicator(); + +public slots: + void increaseTime( float ); + void decreaseTime( float ); + void countTime( float ); + void uncountTime( float ); + void setTime( float ); + void finished( float ); + + void update( float ); + +//private slots: + +private: + QProgressBar* pBar; + QLabel* lSpeed; + QLabel* lTime; + KSystemTray* systemTray; + + QTime elapsedTime; + QTime speedTime; + float speedProcessedTime; + + float time; + float processedTime; + +signals: + void setTitle( const QString& ); +}; + +#endif // PROGRESSINDICATOR_H diff --git a/src/replaygain.cpp b/src/replaygain.cpp new file mode 100755 index 0000000..f815a21 --- /dev/null +++ b/src/replaygain.cpp @@ -0,0 +1,96 @@ + +#include "replaygain.h" +#include "config.h" +#include "logger.h" +#include "replaygainpluginloader.h" + +#include + +#include +#include +#include + +ReplayGain::ReplayGain( Config* _config, Logger* _logger ) +{ + config = _config; + logger = _logger; +} + +ReplayGain::~ReplayGain() +{} + +bool ReplayGain::apply( QStringList files, const QString& format, KProcess* proc, int logID, Mode mode ) +{ + QStringList params; + QString param, paramSplinter; + + proc->clearArguments(); + + ReplayGainPlugin* plugin = config->replaygainForFormat( format ); + if( plugin == 0 ) { // shouldn't happen + logger->log( logID, " NULL POINTER: ReplayGain::replaygain( ... ) / plugin" ); + return false; + } + + param = QString::null; + if( plugin->replaygain.param ) param.append( " " + plugin->replaygain.param ); + if( mode & remove ) { + if( plugin->replaygain.remove ) param.append( " " + plugin->replaygain.remove ); + } + else { + if( (mode & calc_track) && plugin->replaygain.track ) param.append( " " + plugin->replaygain.track ); + if( (mode & calc_album) && plugin->replaygain.album ) param.append( " " + plugin->replaygain.album ); + if( mode & force ) { + if( plugin->replaygain.force ) param.append( " " + plugin->replaygain.force ); + } + else { + if( plugin->replaygain.skip ) param.append( " " + plugin->replaygain.skip ); + } + } + +// if( plugin->replaygain.in_files.find("%p") != -1 ) { +// QString t_str = plugin->replaygain.in_files; +// t_str.replace( "%p", param ); +// param = plugin->replaygain.bin + " " + t_str; +// } +// else { +// param = plugin->replaygain.bin + param + " " + plugin->replaygain.in_files; +// } + + QString t_str = plugin->replaygain.in_files; + t_str.replace( "%p", param ); + param = config->binaries[plugin->replaygain.bin] + " " + t_str; + + // cosmetic surgery + param.simplifyWhiteSpace(); + + params = QStringList::split( ' ', param ); + + for( QStringList::Iterator it = params.begin(); it != params.end(); ++it ) + { + paramSplinter = *it; + if( paramSplinter == "%i" ) { + for( QStringList::Iterator b = files.begin(); b != files.end(); ++b ) { + *(proc) << KURL::decode_string( *b ); + } + } + else { + *(proc) << paramSplinter; + } + } + + for( QStringList::Iterator it = files.begin(); it != files.end(); ++it ) + { + *it = KURL::decode_string( *it ); + } + + param.replace( "%i", "\""+files.join("\" \"")+"\"" ); + logger->log( logID, " " + i18n("Executing") + ": `" + param + "'" ); + + proc->setPriority( config->data.general.priority ); + proc->start( KProcess::NotifyOnExit, KProcess::AllOutput ); + + return true; +} + +//QValueList ReplayGain::getReplayGain( QString file ) {} // obsolete diff --git a/src/replaygain.h b/src/replaygain.h new file mode 100755 index 0000000..ff9e38a --- /dev/null +++ b/src/replaygain.h @@ -0,0 +1,58 @@ + + +#ifndef REPLAYGAIN_H +#define REPLAYGAIN_H + +#include +#include + +class Config; +class Logger; +class KProcess; + +/** + * @short Starts a process to add/remove Replay Gain tags to/from a given file + * @author Daniel Faust + * @version 0.3 + */ +class ReplayGain : public QObject +{ + Q_OBJECT +public: + enum Mode { + calc_track = 0x0001, + calc_album = 0x0002, + remove = 0x0004, + force = 0x0008 + }; + + /** + * Constructor + */ + ReplayGain( Config*, Logger* ); + + /** + * Destructor + */ + virtual ~ReplayGain(); + + /** + * Add/remove Replay Gain + * @param files a list of files (of the same format) + * @param format the format of the file/files (extension or mime type) + * @param prc a pointer to a KProcess + * @param remove if true the Replay Gain tags are being removed, if false (default) the tags are calculated and added + */ + bool apply( QStringList files, const QString& format, KProcess* proc, int logID, Mode mode = Mode(calc_track|calc_album) ); // NOTE const QStringList& ? + + /* + * Returns the track and the album gain (in this order) of the @p file + */ + //static QValueList getReplayGain( QString file ); // obsolete + +private: + Config* config; + Logger* logger; +}; + +#endif // REPLAYGAIN_H diff --git a/src/replaygainfilelist.cpp b/src/replaygainfilelist.cpp new file mode 100755 index 0000000..2d71806 --- /dev/null +++ b/src/replaygainfilelist.cpp @@ -0,0 +1,1262 @@ + +#include "replaygainfilelist.h" +#include "tagengine.h" +#include "logger.h" +#include "config.h" +#include "replaygain.h" +#include "replaygainpluginloader.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// TODO move listDir, addFiles, addDir, etc -- done? + +// ### soundkonverter 0.4: give the 'track' and 'album' column a minimum width and fill the rest of the space with the 'file' column - make some margins, too + + +ReplayGainFileListItem::ReplayGainFileListItem( QListView* parent ) + : KListViewItem( parent ) +{ + m_type = File; + mimeType = "application/octet-stream"; + addingReplayGain = false; + queued = false; +} + +// ReplayGainFileListItem::ReplayGainFileListItem( QListView* parent, QListViewItem* after ) +// : KListViewItem( parent, after ) +// { +// m_type = File; +// mimeType = "application/octet-stream"; +// addingReplayGain = false; +// queued = false; +// } + +ReplayGainFileListItem::ReplayGainFileListItem( ReplayGainFileListItem* parent ) + : KListViewItem( parent ) +{ + m_type = File; + mimeType = "application/octet-stream"; + addingReplayGain = false; + queued = false; +} + +ReplayGainFileListItem::~ReplayGainFileListItem() +{} + +void ReplayGainFileListItem::paintCell( QPainter *p, const QColorGroup &cg, int column, int width, int alignment ) +{ + // NOTE speed up this function + // NOTE calculate the red color + + QColorGroup _cg( cg ); + QColor c; + + if( column == ((ReplayGainFileList*)listView())->columnByName(i18n("File")) ) + { + int margin = listView()->itemMargin(); + int w = width - 2*margin; + int h = height(); + QRect textRect = p->boundingRect( margin, 0, w, h, alignment, text(column) ); + + if( textRect.width() > w ) { + alignment = Qt::AlignRight | Qt::SingleLine; + } + } + + if( isSelected() && addingReplayGain ) { + _cg.setColor( QColorGroup::Highlight, QColor( 215, 62, 62 ) ); + QListViewItem::paintCell( p, _cg, column, width, alignment ); + return; + } + else if( addingReplayGain && column != listView()->sortColumn() ) { + _cg.setColor( QColorGroup::Base, QColor( 255, 234, 234 ) ); + QListViewItem::paintCell( p, _cg, column, width, alignment ); + return; + } + else if( addingReplayGain && column == listView()->sortColumn() ) { + _cg.setColor( QColorGroup::Base, QColor( 247, 227, 227 ) ); + QListViewItem::paintCell( p, _cg, column, width, alignment ); + return; + } + + if( isSelected() && queued ) { + _cg.setColor( QColorGroup::Highlight, QColor( 230, 232, 100 ) ); + QListViewItem::paintCell( p, _cg, column, width, alignment ); + return; + } + else if( queued && column != listView()->sortColumn() ) { + _cg.setColor( QColorGroup::Base, QColor( 255, 255, 190 ) ); + QListViewItem::paintCell( p, _cg, column, width, alignment ); + return; + } + else if( queued && column == listView()->sortColumn() ) { + _cg.setColor( QColorGroup::Base, QColor( 255, 243, 168 ) ); + QListViewItem::paintCell( p, _cg, column, width, alignment ); + return; + } + + KListViewItem::paintCell( p, _cg, column, width, alignment ); +} + +void ReplayGainFileListItem::setType( Type type ) +{ + if( type == m_type ) return; + + m_type = type; + + if( type == Album ) { + setOpen( true ); + setPixmap( 0, KGlobal::iconLoader()->loadIcon("cdrom_unmount",KIcon::Small) ); + } +} + +void ReplayGainFileListItem::updateReplayGainCells( TagData* tags ) +{ + if( !tags ) { + setText( ((ReplayGainFileList*)listView())->columnByName(i18n("Track")), i18n("Unknown") ); + setText( ((ReplayGainFileList*)listView())->columnByName(i18n("Album")), i18n("Unknown") ); + } + else { + if( tags->track_gain != 210588 ) { + setText( ((ReplayGainFileList*)listView())->columnByName(i18n("Track")), QString().sprintf("%+.2f dB",tags->track_gain) ); + } + else { + setText( ((ReplayGainFileList*)listView())->columnByName(i18n("Track")), i18n("Unknown") ); + } + if( tags->album_gain != 210588 ) { + setText( ((ReplayGainFileList*)listView())->columnByName(i18n("Album")), QString().sprintf("%+.2f dB",tags->album_gain) ); + } + else { + setText( ((ReplayGainFileList*)listView())->columnByName(i18n("Album")), i18n("Unknown") ); + } + } +} + +int ReplayGainFileListItem::compare( QListViewItem* item, int column, bool ascending ) const +{ + // NOTE looking at the types, not the strings would be better + if( text(1) == "" && item->text(1) != "" ) return -1; + else if( text(1) != "" && item->text(1) == "" ) return 1; + else return KListViewItem::compare( item, column, ascending ); +} + +ReplayGainFileList::ReplayGainFileList( TagEngine* _tagEngine, Config* _config, Logger* _logger, QWidget *parent, const char *name ) + : KListView( parent, name ) +{ + tagEngine = _tagEngine; + config = _config; + logger = _logger; + + processing = false; + queue = false; + + time = 0; + processedTime = 0; + + addColumn( i18n("File"), 390 ); + setColumnWidthMode( 0, QListView::Manual ); + addColumn( i18n("Track"), 90 ); + setColumnAlignment( 1, Qt::AlignRight ); + addColumn( i18n("Album"), 90 ); + setColumnAlignment( 2, Qt::AlignRight ); + + setSelectionMode( QListView::Extended ); + setAllColumnsShowFocus( true ); + setResizeMode( QListView::LastColumn ); + setShowSortIndicator( true ); + setSorting( 0 ); + setRootIsDecorated( true ); + + setDragEnabled( true ); + setAcceptDrops( true ); + + QGridLayout* grid = new QGridLayout( this, 2, 1, 11, 6 ); + grid->setRowStretch( 0, 1 ); + grid->setRowStretch( 2, 1 ); + grid->setColStretch( 0, 1 ); + grid->setColStretch( 2, 1 ); + pScanStatus = new KProgress( this, "pScanStatus" ); + pScanStatus->setMinimumHeight( pScanStatus->height() ); + pScanStatus->setFormat( "%v / %m" ); + pScanStatus->hide(); + grid->addWidget( pScanStatus, 1, 1 ); + grid->setColStretch( 1, 2 ); + + contextMenu = new KPopupMenu( this ); + connect( this, SIGNAL(contextMenuRequested(QListViewItem*,const QPoint&,int)), + this, SLOT(showContextMenu(QListViewItem*,const QPoint&,int)) + ); + + // we haven't got access to the action collection of soundKonverter, so let's create a new one + actionCollection = new KActionCollection( this ); + + calc_gain = new KAction( i18n("Calculate Replay Gain tags"), "apply", 0, this, SLOT(calcSelectedItemsGain()), actionCollection, "calc_album" ); + remove_gain = new KAction( i18n("Remove Replay Gain tags"), "cancel", 0, this, SLOT(removeSelectedItemsGain()), actionCollection, "remove_gain" ); + remove = new KAction( i18n("Remove"), "edittrash", Key_Delete, this, SLOT(removeSelectedItems()), actionCollection, "remove" ); + paste = new KAction( i18n("Paste"), "editpaste", 0, this, 0, actionCollection, "paste" ); + newalbum = new KAction( i18n("New album"), "filenew", 0, this, SLOT(createNewAlbum()), actionCollection, "newalbum" ); + open_albums = new KAction( i18n("Open all albums"), "view_tree", 0, this, SLOT(openAlbums()), actionCollection, "open_albums" ); + close_albums = new KAction( i18n("Cloase all albums"), "view_text", 0, this, SLOT(closeAlbums()), actionCollection, "close_albums" ); + + replayGain = new ReplayGain( config, logger ); + + bubble = new QSimpleRichText( i18n( "

" + "

Replay Gain Tool

" + "With this tool you can add Replay Gain tags to your audio files and remove them." + //"
Replay Gain adds a volume correction information to the files for playing them at the same volume." + //"Replay Gain allows you to play all audio files at the same volume level without modifying the audio data." + "
Replay Gain adds a volume correction information to the files so that they can be played at an equal volume level." +// "
Learn more about Replay Gain ...
" + "
" ), QApplication::font() ); + + connect( header(), SIGNAL(sizeChange( int, int, int )), + SLOT(columnResizeEvent( int, int, int )) + ); + connect( this, SIGNAL( dropped(QDropEvent*, QListViewItem*, QListViewItem*) ), + SLOT( slotDropped(QDropEvent*, QListViewItem*, QListViewItem*) ) + ); + + process = new KProcess(); + connect( process, SIGNAL(receivedStdout(KProcess*,char*,int)), + this, SLOT(processOutput(KProcess*,char*,int)) + ); + connect( process, SIGNAL(receivedStderr(KProcess*,char*,int)), + this, SLOT(processOutput(KProcess*,char*,int)) + ); + connect( process, SIGNAL(processExited(KProcess*)), + this, SLOT(processExit(KProcess*)) + ); + + tUpdateProgress = new QTimer( this, "tUpdateProgress" ); + connect( tUpdateProgress, SIGNAL(timeout()), + this, SLOT(update()) + ); +} + +ReplayGainFileList::~ReplayGainFileList() +{ + delete replayGain; +} + +int ReplayGainFileList::columnByName( const QString& name ) +{ + for( int i = 0; i < columns(); ++i ) { + if( columnText( i ) == name ) return i; + } + return -1; +} + +void ReplayGainFileList::viewportPaintEvent( QPaintEvent* e ) +{ + KListView::viewportPaintEvent( e ); + + // the bubble help + if( childCount() == 0 ) { + QPainter p( viewport() ); + + bubble->setWidth( width() - 50 ); + + const uint w = bubble->width() + 20; + const uint h = bubble->height() + 20; + + p.setBrush( colorGroup().background() ); + p.drawRoundRect( 15, 15, w, h, (8*200)/w, (8*200)/h ); + bubble->draw( &p, 20, 20, QRect(), colorGroup() ); + } +} + +void ReplayGainFileList::viewportResizeEvent( QResizeEvent* ) +{ + // needed for correct redraw of bubble help + triggerUpdate(); +} + +void ReplayGainFileList::columnResizeEvent( int, int, int ) +{ + // needed for correct redraw of bubble help + triggerUpdate(); +} + +bool ReplayGainFileList::acceptDrag( QDropEvent* e ) const +{ + return ( e->source() == viewport() || KURLDrag::canDecode(e) ); // TODO verify the files +} + +void ReplayGainFileList::slotDropped( QDropEvent* e, QListViewItem*, QListViewItem* ) +{ + QString file; + KURL::List list; + if( KURLDrag::decode( e, list ) ) + { + for( KURL::List::Iterator it = list.begin(); it != list.end(); ++it ) + { + // TODO verify the files (necessary when multiple files are being dropped) + file = QDir::convertSeparators( (*it).pathOrURL() ); + QFileInfo fileInfo( file ); + if( fileInfo.isDir() ) + { + addDir( file ); + } + else + { + addFile( (*it).url() ); + } + } + } +} + +void ReplayGainFileList::contentsDragEnterEvent( QDragEnterEvent *e ) +{ + e->accept( e->source() == viewport() || KURLDrag::canDecode(e) ); +} + +void ReplayGainFileList::contentsDragMoveEvent( QDragMoveEvent *e ) +{ // the mouse has moved while dragging some stuff + + // if the file is added from an external app, don't let the user select the position to drop + if( e->source() != viewport() ) { + setDropHighlighter( false ); + setDropVisualizer( false ); + cleanItemHighlighter(); + cleanDropVisualizer(); + + // the rest is handled by KListView + KListView::contentsDragMoveEvent( e ); + + return; + } + + // translate the coordinates of the mouse pointer + QPoint vp = contentsToViewport( e->pos() ); + // and get the list view item below the pointer + ReplayGainFileListItem* item = itemAt( vp ); + + if( item && item->type() == ReplayGainFileListItem::Album ) { // the pointer is above an 'album' element + // draw a nice rect around the item + setDropHighlighter( true ); + setDropVisualizer( false ); + cleanDropVisualizer(); + } + else if( item ) { // the pointer is above an 'file' element + // draw a line above or below the item + setDropVisualizer( true ); + setDropHighlighter( false ); + cleanItemHighlighter(); + } + + // the rest is handled by KListView + KListView::contentsDragMoveEvent( e ); +} + +void ReplayGainFileList::contentsDropEvent( QDropEvent *e ) +{ // the stuff has been dropped + + emit dropped( e, 0, 0 ); // NOTE it works this way + + bool formatError = false; + + cleanDropVisualizer(); + cleanItemHighlighter(); + + // get the item below the mouse pointer, where the stuff has been dropped + QPoint vp = contentsToViewport( e->pos() ); + ReplayGainFileListItem* newParent = itemAt( vp ); + + // if the item is a 'file', use the parent item + if( newParent && newParent->type() != ReplayGainFileListItem::Album ) { + newParent = newParent->parent(); + } + + // TODO if the mouse is on the left side under the parent but not under the sibling item, use the parent +/* if( newParent == 0 && vp.x() >= 2*treeStepSize() ) { + QPoint p = vp; + int height = 0; + if( firstChild() ) { + height = firstChild()->height(); + } + p.setY( p.y() - height ); + ReplayGainFileListItem* it = itemAt( p ); + if( it && it->type() != ReplayGainFileListItem::Album ) { + newParent = it->parent(); + } + else if( it ) { + newParent = it; + } + }*/ + + ReplayGainFileListItem* i; + + // iterate through all items and move all selected ones + for( ReplayGainFileListItem* item = firstChild(); item != 0; ) { + if( item->type() == ReplayGainFileListItem::File ) { + if( newParent == 0 ) { + item = item->nextSibling(); + continue; + } + if( item->isSelected() ) { + if( newParent == 0 || newParent->mimeType == item->mimeType || newParent->mimeType == "application/octet-stream" ) { + if( newParent->mimeType == "application/octet-stream" ) newParent->mimeType = item->mimeType; + i = item; + item = item->nextSibling(); + takeItem( i ); + if( newParent ) newParent->insertItem( i ); + else insertItem( i ); + } + else { + item = item->nextSibling(); + formatError = true; + } + } + else { + item = item->nextSibling(); + } + } + else { + if( item == newParent ) { + item = item->nextSibling(); + continue; + } + if( item->isSelected() ) { + if( newParent == 0 || newParent->mimeType == item->mimeType || newParent->mimeType == "application/octet-stream" ) { + if( newParent->mimeType == "application/octet-stream" ) newParent->mimeType = item->mimeType; + for( ReplayGainFileListItem* sub_item = item->firstChild(); sub_item != 0; ) { + i = sub_item; + sub_item = sub_item->nextSibling(); + item->takeItem( i ); + if( newParent ) newParent->insertItem( i ); + else insertItem( i ); + } + i = item; + item = item->nextSibling(); + delete i; + } + else { + item = item->nextSibling(); + formatError = true; + } + } + else { + for( ReplayGainFileListItem* sub_item = item->firstChild(); sub_item != 0; ) { + if( sub_item->isSelected() ) { + if( newParent == 0 || newParent->mimeType == item->mimeType || newParent->mimeType == "application/octet-stream" ) { + if( newParent && newParent->mimeType == "application/octet-stream" ) newParent->mimeType = item->mimeType; + i = sub_item; + sub_item = sub_item->nextSibling(); + item->takeItem( i ); + if( newParent ) newParent->insertItem( i ); + else insertItem( i ); + } + else { + sub_item = sub_item->nextSibling(); + formatError = true; + } + } + else { + sub_item = sub_item->nextSibling(); + } + } + if( item->childCount() == 0 ) { + i = item; + item = item->nextSibling(); + delete i; + } + else { + item = item->nextSibling(); + } + } + } + } + + // FIXME make the mouse pointer look normal + + if( formatError ) { + KMessageBox::information( this, + i18n("You can't place files of different formats in the same \'album\'."), i18n("Different file formats") ); + } +} + +int ReplayGainFileList::listDir( const QString& directory, QStringList filter, bool recursive, bool fast, int count ) +{ // NOTE speed up? + QDir dir( directory ); + dir.setFilter( QDir::Files | QDir::Dirs | QDir::NoSymLinks | QDir::Readable ); + + QStringList list = dir.entryList(); + + for( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { + if( *it == "." || *it == ".." ) continue; + QFileInfo fileInfo( directory + "/" + *it ); + if( fast ) { + if( fileInfo.isDir() && recursive ) { + count = listDir( directory + "/" + *it, filter, recursive, fast, count ); + } + else if( !fileInfo.isDir() || !recursive ) { // NOTE checking for isFile may not work with all file names + // NOTE filter feature + for( QStringList::Iterator jt = filter.begin(); jt != filter.end(); ++jt ) { + if( (*it).endsWith("."+(*jt),false) ) { + count++; + pScanStatus->setTotalSteps( count ); + break; + } + } + if( filter.first() == "" ) { + count++; + pScanStatus->setTotalSteps( count ); + } + } + } + else { + if( fileInfo.isDir() && recursive ) { + count = listDir( directory + "/" + *it, filter, recursive, fast, count ); + } + else if( !fileInfo.isDir() || !recursive ) { // NOTE checking for isFile may not work with all file names + // NOTE filter feature + for( QStringList::Iterator jt = filter.begin(); jt != filter.end(); ++jt ) { + if( (*it).endsWith("."+(*jt),false) ) { + addFile( KURL::encode_string(directory + "/" + *it) ); + count++; + pScanStatus->setProgress( count ); + break; + } + } + if( filter.first() == "" ) { + addFile( KURL::encode_string(directory + "/" + *it) ); + count++; + pScanStatus->setProgress( count ); + } + } + } + } + + return count; +} + +void ReplayGainFileList::showContextMenu( QListViewItem* item, const QPoint& point, int ) +{ + // remove all items from the context menu + contextMenu->clear(); + + // add a tilte to our context manu + //contextMenu->insertTitle( static_cast(item)->fileName ); + + // if item is null, we can abort here + if( item ) { + if( !processing ) { + calc_gain->plug( contextMenu ); + if( item->text(columnByName(i18n("Track"))) != i18n("Unknown") || item->text(columnByName(i18n("Album"))) != i18n("Unknown") ) { + remove_gain->plug( contextMenu ); + } + } + newalbum->plug( contextMenu ); + remove->plug( contextMenu ); + } + else { + newalbum->plug( contextMenu ); + } + paste->plug( contextMenu ); + contextMenu->insertSeparator(); + open_albums->plug( contextMenu ); + close_albums->plug( contextMenu ); + + // show the popup menu + contextMenu->popup( point ); +} + +void ReplayGainFileList::addFile( const QString& file ) +{ + QString filename = file; + QString filePathName; + QString device; + + if( filename.left( 1 ) == "/" ) { + filePathName = filename; + } + else if( filename.left( 7 ) == "file://" ) { + filePathName = filename; + filePathName.remove( 0, 7 ); + } + else if( filename.left( 13 ) == "system:/home/" ) { + filePathName = filename; + filePathName.remove( 0, 13 ); + filePathName = QDir::homeDirPath() + "/" + filePathName; + } + else if( filename.left( 14 ) == "system:/users/" || filename.left( 6 ) == "home:/" ) { + int length = ( filename.left(6) == "home:/" ) ? 6 : 14; + QString username = filename; + username.remove( 0, length ); + username = username.left( username.find("/") ); + filePathName = filename; + filePathName.remove( 0, length + username.length() ); + KUser user( username ); + filePathName = user.homeDir() + filePathName; + } + else if( filename.left( 14 ) == "system:/media/" || filename.left( 7 ) == "media:/" ) { + int length = ( filename.left(7) == "media:/" ) ? 7 : 14; + device = filename; + device.remove( 0, length ); + device = "/dev/" + device.left( device.find( "/" ) ); + + KMountPoint::List mountPoints = KMountPoint::possibleMountPoints(); + + for( KMountPoint::List::ConstIterator jt = mountPoints.begin(); jt != mountPoints.end(); ++jt ) + { + const KSharedPtr mp = *jt; + if( mp->mountedFrom() == device ) + { + filePathName = ( mp->mountPoint() == "/" ) ? mp->mountPoint() : mp->mountPoint() + "/"; + filePathName += filename.right( filename.length() - device.length() - length + 4 ); + } + } + } + else { + return; + } + + TagData* tags = tagEngine->readTags( KURL::decode_string(filePathName) ); + if( !tags || tags->album.isEmpty() ) { + ReplayGainFileListItem* item = new ReplayGainFileListItem( this ); + item->originalFileFormat = filePathName.right( filePathName.length() - filePathName.findRev(".") - 1 ); + item->mimeType = KMimeType::findByFileContent( filePathName )->name(); + item->fileFormat = KMimeType::findByFileContent( filePathName )->patterns().first(); + if( item->mimeType.isEmpty() || item->mimeType == "application/octet-stream" || item->mimeType == "text/plain" ) { + item->mimeType = KMimeType::findByURL( filePathName.lower() )->name(); + item->fileFormat = KMimeType::findByURL( filePathName.lower() )->patterns().first(); + } + // check whether the mime type has a decoder registered + if( !config->acceptReplayGainFile( item->mimeType ) ) { + delete item; + return; + } + item->filePathName = filePathName; + if( tags ) item->time = tags->length; + else { + FormatItem* formatItem = config->getFormatItem( item->mimeType ); + if( formatItem && formatItem->size > 0 ) { + QFileInfo fileInfo( filePathName ); + item->time = fileInfo.size() / formatItem->size; + } + else { + item->time = 210; + } + } + item->setText( columnByName(i18n("File")), KURL::decode_string(filePathName).replace("%2f","/").replace("%%","%") ); + if( tags && tags->track_gain != 210588 ) { + item->setText( columnByName(i18n("Track")), QString().sprintf("%+.2f dB",tags->track_gain) ); + } + else { + item->setText( columnByName(i18n("Track")), i18n("Unknown") ); + } + if( tags && tags->album_gain != 210588 ) { + item->setText( columnByName(i18n("Album")), QString().sprintf("%+.2f dB",tags->album_gain) ); + } + else { + item->setText( columnByName(i18n("Album")), i18n("Unknown") ); + } + } + else { + QString mimeType = KMimeType::findByFileContent( filePathName )->name(); + QString fileFormat = KMimeType::findByFileContent( filePathName )->patterns().first(); + if( mimeType.isEmpty() || mimeType == "application/octet-stream" || mimeType == "text/plain" ) { + mimeType = KMimeType::findByURL( filePathName.lower() )->name(); + fileFormat = KMimeType::findByURL( filePathName.lower() )->patterns().first(); + } + // check whether the mime type has a decoder registered + if( !config->acceptReplayGainFile( mimeType ) ) { + return; + } + + for( ReplayGainFileListItem* it = firstChild(); it != 0; it = it->nextSibling() ) { + //if( it->text(0) == QString(tags->artist+" - "+tags->album) ) { + if( it->text(columnByName(i18n("File"))) == tags->album && it->type() == ReplayGainFileListItem::Album && it->mimeType == mimeType ) { + ReplayGainFileListItem* item = new ReplayGainFileListItem( it ); + item->originalFileFormat = filePathName.right( filePathName.length() - filePathName.findRev(".") - 1 ); + item->filePathName = filePathName; + item->mimeType = mimeType; + item->fileFormat = fileFormat; + item->time = tags->length; + item->setText( columnByName(i18n("File")), KURL::decode_string(filePathName).replace("%2f","/").replace("%%","%") ); + if( tags->track_gain != 210588 ) { + item->setText( columnByName(i18n("Track")), QString().sprintf("%+.2f dB",tags->track_gain) ); + } + else { + item->setText( columnByName(i18n("Track")), i18n("Unknown") ); + } + if( tags->album_gain != 210588 ) { + item->setText( columnByName(i18n("Album")), QString().sprintf("%+.2f dB",tags->album_gain) ); + } + else { + item->setText( columnByName(i18n("Album")), i18n("Unknown") ); + } + tags = 0; // <--, + break; // | + } // | + } // | + if( tags ) { // <--' + ReplayGainFileListItem* parent = new ReplayGainFileListItem( this ); + //parent->setText( 0, tags->artist+" - "+tags->album ); + parent->setText( columnByName(i18n("File")), tags->album ); + parent->setType( ReplayGainFileListItem::Album ); + parent->mimeType = mimeType; + parent->fileFormat = fileFormat; + ReplayGainFileListItem* item = new ReplayGainFileListItem( parent ); + item->originalFileFormat = filePathName.right( filePathName.length() - filePathName.findRev(".") - 1 ); + item->filePathName = filePathName; + item->mimeType = mimeType; + item->fileFormat = fileFormat; + item->time = tags->length; + item->setText( columnByName(i18n("File")), KURL::decode_string(filePathName).replace("%2f","/").replace("%%","%") ); + if( tags->track_gain != 210588 ) { + item->setText( columnByName(i18n("Track")), QString().sprintf("%+.2f dB",tags->track_gain) ); + } + else { + item->setText( columnByName(i18n("Track")), i18n("Unknown") ); + } + if( tags->album_gain != 210588 ) { + item->setText( columnByName(i18n("Album")), QString().sprintf("%+.2f dB",tags->album_gain) ); + } + else { + item->setText( columnByName(i18n("Album")), i18n("Unknown") ); + } + } + } +} + +void ReplayGainFileList::addDir( const QString& directory, const QStringList& filter, bool recursive ) +{ + pScanStatus->setProgress( 0 ); + pScanStatus->setTotalSteps( 0 ); + pScanStatus->show(); // show the status while scanning the directories + kapp->processEvents(); + + int count = listDir( directory, filter, recursive, true ); + listDir( directory, filter, recursive ); + + pScanStatus->hide(); // hide the status bar, when the scan is done +} + +void ReplayGainFileList::openAlbums() +{ + // iterate through all items and open all albums + for( ReplayGainFileListItem* item = firstChild(); item != 0; item = item->nextSibling() ) { + if( item->type() == ReplayGainFileListItem::Album ) { + item->setOpen( true ); + } + } +} + +void ReplayGainFileList::closeAlbums() +{ + // iterate through all items and close all albums + for( ReplayGainFileListItem* item = firstChild(); item != 0; item = item->nextSibling() ) { + if( item->type() == ReplayGainFileListItem::Album ) { + item->setOpen( false ); + } + } +} + +void ReplayGainFileList::removeSelectedItems() +{ + ReplayGainFileListItem* i; + + // iterate through all items and remove all selected ones + for( ReplayGainFileListItem* item = firstChild(); item != 0; ) { + if( item->type() == ReplayGainFileListItem::File ) { + if( item->isSelected() ) { + i = item; + item = item->nextSibling(); + delete i; + } + else { + item = item->nextSibling(); + } + } + else { + if( item->isSelected() ) { + i = item; + item = item->nextSibling(); + delete i; + } + else { + for( ReplayGainFileListItem* sub_item = item->firstChild(); sub_item != 0; ) { + if( sub_item->isSelected() ) { + i = sub_item; + sub_item = sub_item->nextSibling(); + delete i; + } + else { + sub_item = sub_item->nextSibling(); + } + } + if( item->childCount() == 0 ) { + i = item; + item = item->nextSibling(); + delete i; + } + else { + item = item->nextSibling(); + } + } + } + } +} + +void ReplayGainFileList::createNewAlbum() +{ + ReplayGainFileListItem* item = new ReplayGainFileListItem( this ); + item->setText( columnByName(i18n("File")), i18n("New album") ); + item->setType( ReplayGainFileListItem::Album ); + item->mimeType = "application/octet-stream"; +} + +void ReplayGainFileList::calcSelectedItemsGain() +{ + if( processing ) return; + + // iterate through all items and remove the replay gain from all selected ones + for( ReplayGainFileListItem* item = firstChild(); item != 0; item = item->nextSibling() ) { + if( item->type() == ReplayGainFileListItem::File ) { + if( item->isSelected() ) { + item->queued = true; + item->repaint(); + item->mode = ReplayGainFileListItem::force; + } + } + else { + if( item->isSelected() ) { + item->queued = true; + item->repaint(); + item->mode = ReplayGainFileListItem::force; + for( ReplayGainFileListItem* sub_item = item->firstChild(); sub_item != 0; sub_item = sub_item->nextSibling() ) { + sub_item->queued = true; + sub_item->repaint(); + sub_item->mode = ReplayGainFileListItem::force; + } + } + else { + for( ReplayGainFileListItem* sub_item = item->firstChild(); sub_item != 0; sub_item = sub_item->nextSibling() ) { + if( sub_item->isSelected() ) { + item->queued = true; + item->repaint(); + item->mode = ReplayGainFileListItem::force; + for( ReplayGainFileListItem* sub_item2 = item->firstChild(); sub_item2 != 0; sub_item2 = sub_item2->nextSibling() ) { + sub_item2->queued = true; + sub_item2->repaint(); + sub_item2->mode = ReplayGainFileListItem::force; + } + break; + } + } + } + } + } + startProcess(); +} + +void ReplayGainFileList::removeSelectedItemsGain() +{ + // iterate through all items and remove the replay gain from all selected ones + for( ReplayGainFileListItem* item = firstChild(); item != 0; item = item->nextSibling() ) { + if( item->type() == ReplayGainFileListItem::File ) { + if( item->isSelected() && !item->addingReplayGain ) { + item->queued = true; + item->repaint(); + item->mode = ReplayGainFileListItem::remove; + } + } + else { + if( item->isSelected() && !item->addingReplayGain ) { + item->queued = true; + item->repaint(); + item->mode = ReplayGainFileListItem::remove; + for( ReplayGainFileListItem* sub_item = item->firstChild(); sub_item != 0; sub_item = sub_item->nextSibling() ) { + sub_item->queued = true; + sub_item->repaint(); + sub_item->mode = ReplayGainFileListItem::remove; + } + } + else { + for( ReplayGainFileListItem* sub_item = item->firstChild(); sub_item != 0; sub_item = sub_item->nextSibling() ) { + if( sub_item->isSelected() && !sub_item->addingReplayGain ) { + sub_item->queued = true; + sub_item->repaint(); + sub_item->mode = ReplayGainFileListItem::remove; + } + } + } + } + } + startProcess(); +} + +void ReplayGainFileList::calcReplayGain( ReplayGainFileListItem* item ) +{ + logID = logger->registerProcess( KURL::encode_string(item->text(columnByName(i18n("File")))) ); + logger->log( logID, "Mime Type: " + item->mimeType ); + logger->log( logID, i18n("Applying Replay Gain") ); + + QStringList fileList; + bool force = false; + if( mode & ReplayGainFileListItem::force ) force = true; + QString album_gain = ""; + bool skip = true; + + timeCount = 0; + file = 0; + files = 0; + + if( item->type() == ReplayGainFileListItem::Album ) { + item->queued = false; + item->addingReplayGain = true; + item->repaint(); + for( ReplayGainFileListItem* sub_item = item->firstChild(); sub_item != 0; sub_item = sub_item->nextSibling() ) { + if( sub_item->queued && sub_item->mode & ReplayGainFileListItem::force ) force = true; // NOTE can this be replaced by checking item? + sub_item->queued = false; + sub_item->addingReplayGain = true; + sub_item->repaint(); + + fileList += sub_item->filePathName; + files++; + timeCount += sub_item->time; + + QString current_gain = sub_item->text( columnByName(i18n("Album")) ); + if( album_gain == "" ) album_gain = current_gain; + else if( album_gain != current_gain ) skip = false; + } + + if( !skip || album_gain == i18n("Unknown") || force ) { + if( force ) { + replayGain->apply( fileList, item->mimeType, process, logID, ReplayGain::Mode(ReplayGain::calc_album|ReplayGain::force) ); + } + else { + replayGain->apply( fileList, item->mimeType, process, logID ); + } + } + else { + logger->processCompleted( logID, 0 ); + item->addingReplayGain = false; + item->repaint(); + for( ReplayGainFileListItem* sub_item = item->firstChild(); sub_item != 0; sub_item = sub_item->nextSibling() ) { + sub_item->addingReplayGain = false; + sub_item->repaint(); + } + processNextFile(); + } + } + else { + if( item->queued && item->mode & ReplayGainFileListItem::force ) force = true; + + item->queued = false; + item->addingReplayGain = true; + item->repaint(); + + files = 1; + timeCount = item->time; + + if( force ) { + replayGain->apply( item->filePathName, item->mimeType, process, logID, ReplayGain::Mode(ReplayGain::calc_album|ReplayGain::force) ); + } + else { + replayGain->apply( item->filePathName, item->mimeType, process, logID ); + } + } +} + +void ReplayGainFileList::removeReplayGain( ReplayGainFileListItem* item ) +{ + logID = logger->registerProcess( KURL::encode_string(item->text(columnByName(i18n("File")))) ); + logger->log( logID, "Mime Type: " + item->mimeType ); + logger->log( logID, i18n("Removing Replay Gain") ); + + if( item->type() == ReplayGainFileListItem::File ) { + item->queued = false; + item->addingReplayGain = true; + item->repaint(); + timeCount = item->time; + replayGain->apply( item->filePathName, item->mimeType, process, logID, ReplayGain::remove ); + } + else { + item->queued = false; + item->repaint(); + processNextFile(); + } +} + +void ReplayGainFileList::calcAllReplayGain( bool force ) +{ + queue = true; + if( force ) mode = ReplayGainFileListItem::force; + else mode = ReplayGainFileListItem::Mode(0x0000); + startProcess(); +} + +void ReplayGainFileList::removeAllReplayGain() +{ + queue = true; + mode = ReplayGainFileListItem::remove; + startProcess(); +} + +void ReplayGainFileList::cancelProcess() +{ + queue = false; + if( process->isRunning() ) + { + bool ret = process->kill( SIGKILL ); + if( ret ) { + logger->log( logID, i18n("Killing process ...") ); + } + else { + logger->log( logID, i18n("Killing process failed. Stopping after files are completed ...") ); + } + } +} + +void ReplayGainFileList::startProcess() +{ + emit processStarted(); + processing = true; + time = 0; + + for( ReplayGainFileListItem* item = firstChild(); item != 0; item = item->nextSibling() ) { + if( item->type() == ReplayGainFileListItem::File ) { + if( queue ) { + time += item->time; + } + else if( item->queued ) { + time += item->time; + } + } + else { + for( ReplayGainFileListItem* sub_item = item->firstChild(); sub_item != 0; sub_item = sub_item->nextSibling() ) { + if( queue ) { + time += sub_item->time; + } + else if( sub_item->queued ) { + time += sub_item->time; + } + } + } + } + + emit updateProgress( 0, 100 ); + if( !tUpdateProgress->isActive() ) { + tUpdateProgress->start( 200 ); // TODO use config value + } + + currentItem = 0; + processNextFile(); +} + +void ReplayGainFileList::processNextFile() +{ + percent = 0; + lastPercent = 0; + + ReplayGainFileListItem* currentSubItem = 0; + + if( !currentItem ) { currentItem = firstChild(); } + else if( currentItem->type() == ReplayGainFileListItem::File && currentItem->parent() == 0 ) { currentItem = currentItem->nextSibling(); } + else if( currentItem->type() == ReplayGainFileListItem::Album ) { currentItem = currentItem->nextSibling(); } + else { currentSubItem = currentItem->nextSibling(); currentItem = currentItem->parent(); if( !currentSubItem ) { currentItem = currentItem->nextSibling(); } } + + for( ReplayGainFileListItem* item = currentItem; item != 0; item = item->nextSibling() ) { + if( item->type() == ReplayGainFileListItem::File ) { + if( queue ) { + currentItem = item; + if( mode & ReplayGainFileListItem::remove ) removeReplayGain( item ); + else calcReplayGain( item ); + return; + } + else if( item->queued ) { + currentItem = item; + if( item->mode & ReplayGainFileListItem::remove ) removeReplayGain( item ); + else calcReplayGain( item ); + return; + } + } + else { + if( queue ) { + currentItem = item; + if( mode & ReplayGainFileListItem::remove ) {} + else { calcReplayGain( item ); return; } + } + else if( item->queued ) { + currentItem = item; + if( item->mode & ReplayGainFileListItem::remove ) { item->queued = false; } + else { calcReplayGain( item ); return; } + } + + if( !currentSubItem ) currentSubItem = item->firstChild(); + for( ReplayGainFileListItem* sub_item = currentSubItem; sub_item != 0; sub_item = sub_item->nextSibling() ) { + if( queue ) { + currentItem = sub_item; + if( mode & ReplayGainFileListItem::remove ) removeReplayGain( sub_item ); + return; + } + else if( sub_item->queued ) { + currentItem = sub_item; + if( sub_item->mode & ReplayGainFileListItem::remove ) removeReplayGain( sub_item ); + return; + } + } + + currentSubItem = 0; + } + } + queue = false; + tUpdateProgress->stop(); + processedTime = 0; + processing = false; + emit processStopped(); +} + +void ReplayGainFileList::processOutput( KProcess* proc, char* data, int ) +{ + int iPercent = 0, iTime = 0, iPos = 0, iNum = 0; + + QString log_data = data; + log_data.replace("\n","\\n"); + log_data.replace("\t","\\t"); + log_data.replace("\r","\\r"); + log_data.replace("\b","\\b"); + logger->log( logID, " " + i18n("Output") + ": " + log_data ); + + ReplayGainPlugin* plugin = config->replaygainForFormat( currentItem->mimeType ); + if( plugin == 0 ) { // shouldn't happen + logger->log( logID, " NULL POINTER: ReplayGainScanner::processOutput( ... ) / plugin" ); + return; + } + if( plugin->info.name == i18n("built-in") ) { // shouldn't happen // TODO implement a check for this + logger->log( logID, " Backend is an encoder" ); + return; + } + + QString outputPattern = ( files > 1 ) ? plugin->replaygain.output_multiple : plugin->replaygain.output_single; + //outputPattern.replace( "%i", "%p" ); // for compatibility with old plugins + + if( outputPattern.find("%p") != -1 || outputPattern.find("%a") != -1 ) { + outputPattern.replace( "%p", "%i" ); + //outputPattern.replace( "%a", "%i" ); // for compatibility with old plugins + sscanf( data, outputPattern, &iPercent ); + } + /*else if( outputPattern.find("%t") != -1 ) { // NOTE a little bit complicated and not necessary + outputPattern.replace( "%t", "%i" ); + sscanf( data, outputPattern, &iTime ); + iPercent = iTime * 100 / currentItem->time; + }*/ + else if( outputPattern.find("%0") != -1 && outputPattern.find("%1") != -1 ) { + if( outputPattern.find("%0") < outputPattern.find("%1") ) { + outputPattern.replace( "%0", "%i" ); + outputPattern.replace( "%1", "%i" ); + sscanf( data, outputPattern, &iPos, &iNum ); + } + else { + outputPattern.replace( "%0", "%i" ); + outputPattern.replace( "%1", "%i" ); + sscanf( data, outputPattern, &iNum, &iPos ); + } + if( iPos != 0 && iNum != 0 ) iPercent = iPos * 100 / iNum; + } + + if( iPercent > 0 && iPercent <= 100 ) + { + // TODO guess progress, when no signal is received + //lastOutputTimer.start(); + if( files > 1 ) { + if( iPercent < lastPercent ) file++; + lastPercent = iPercent; + percent = file * 100 / files + iPercent / files; + } + else { + percent = iPercent; + } + } +} + +void ReplayGainFileList::processExit( KProcess* proc ) +{ + logger->processCompleted( logID, ( proc->signalled() ) ? -1 : 0 ); + + for( ReplayGainFileListItem* item = firstChild(); item != 0; item = item->nextSibling() ) { + if( item->type() == ReplayGainFileListItem::File ) { + if( item->addingReplayGain ) { + processedTime += item->time; + item->addingReplayGain = false; + item->repaint(); + item->updateReplayGainCells( tagEngine->readTags(KURL::decode_string(item->filePathName)) ); + } + if( item->queued && proc->signalled() ) { + item->queued = false; + item->repaint(); + } + } + else { + if( item->addingReplayGain ) { + item->addingReplayGain = false; + item->repaint(); + for( ReplayGainFileListItem* sub_item = item->firstChild(); sub_item != 0; sub_item = sub_item->nextSibling() ) { + processedTime += sub_item->time; + sub_item->addingReplayGain = false; + sub_item->repaint(); + sub_item->updateReplayGainCells( tagEngine->readTags(KURL::decode_string(sub_item->filePathName)) ); + } + } + if( item->queued && proc->signalled() ) { + item->queued = false; + item->repaint(); + for( ReplayGainFileListItem* sub_item = item->firstChild(); sub_item != 0; sub_item = sub_item->nextSibling() ) { + sub_item->queued = false; + sub_item->repaint(); + } + } + for( ReplayGainFileListItem* sub_item = item->firstChild(); sub_item != 0; sub_item = sub_item->nextSibling() ) { + if( sub_item->addingReplayGain ) { + processedTime += sub_item->time; + sub_item->addingReplayGain = false; + sub_item->repaint(); + sub_item->updateReplayGainCells( tagEngine->readTags(KURL::decode_string(sub_item->filePathName)) ); + } + if( sub_item->queued && proc->signalled() ) { + sub_item->queued = false; + sub_item->repaint(); + } + } + } + } + if( proc->signalled() ) { + queue = false; + tUpdateProgress->stop(); + processedTime = 0; + processing = false; + emit processStopped(); + return; + } + else { + processNextFile(); + } +} + +void ReplayGainFileList::update() +{ + emit updateProgress( int(processedTime) + percent * int(timeCount) / 100, int(time) ); +} + diff --git a/src/replaygainfilelist.h b/src/replaygainfilelist.h new file mode 100755 index 0000000..a147c44 --- /dev/null +++ b/src/replaygainfilelist.h @@ -0,0 +1,242 @@ + + +#ifndef REPLAYGAINFILELIST_H +#define REPLAYGAINFILELIST_H + +#include + +#include + + +class TagEngine; +class TagData; +class ReplayGain; +class Config; +class Logger; + +class QSimpleRichText; +class KProgress; + +class KPopupMenu; +class KAction; +class KActionCollection; +class KProcess; + +// FIXME differ diffrent sampling rates, too! + +/** + * @short The items for the file list of the Replay Gain scanner + * @author Daniel Faust + * @version 0.3 + */ +class ReplayGainFileListItem : public KListViewItem +{ +public: + enum Type { + File, + Album + }; + + enum Mode { + remove = 0x0001, + force = 0x0002 + }; + + /** + * Constructor + * @param parent The parent list view + */ + ReplayGainFileListItem( QListView* parent ); + + /* + * Constructor + * @param parent The parent list view + * @param after The item, the new item should be placed after + */ + //ReplayGainFileListItem( QListView* parent, QListViewItem* after ); + + /** + * Constructor + * @param parent The parent list view item + */ + ReplayGainFileListItem( ReplayGainFileListItem* parent ); + + /** + * Destructor + */ + virtual ~ReplayGainFileListItem(); + + virtual void paintCell( QPainter* p, const QColorGroup& cg, int column, int width, int alignment ); + + int compare( QListViewItem* item, int column, bool ascending ) const; + + void updateReplayGainCells( TagData* ); + + ReplayGainFileListItem* firstChild() const { return static_cast( KListViewItem::firstChild() ); } + ReplayGainFileListItem* nextSibling() const { return static_cast( KListViewItem::nextSibling() ); } + //ReplayGainFileListItem* itemBelow() { return static_cast( KListViewItem::itemBelow() ); } + ReplayGainFileListItem* parent() const { return static_cast( KListViewItem::parent() ); } + + Type type() { return m_type; } + void setType( Type ); + + // FIXME file list + + /* TODO check sampling rate, too + * metaflac: 8, 11.025, 12, 16, 22.05, 24, 32, 44.1, or 48 kHz. + */ + + QString filePathName; // the path and name of the file + //QString fileName; // just the _name_ of the file + QString mimeType; // the mime type of the file / the mime type of all files in this album + QString fileFormat; // just the _format_ of the file / the format of all files in this album (for easier use) + QString originalFileFormat; // after renaming we need to re-rename the file + bool addingReplayGain; // are we adding replay gain tags at the moment? + bool queued; // is this item queued for adding/removing replay gain? + Mode mode; + float time; // the duration of the track, used for the calculation of the progress bar + +private: + Type m_type; +}; + + +/** + * @short The file list of the Replay Gain scanner + * @author Daniel Faust + * @version 0.3 + */ +class ReplayGainFileList : public KListView +{ + Q_OBJECT +public: + /** + * Constructor + * @param parent The parent widget + * @param name The name of the file list + */ + ReplayGainFileList( TagEngine*, Config*, Logger*, QWidget *parent=0, const char *name=0 ); + + /** + * Destructor + */ + virtual ~ReplayGainFileList(); + + ReplayGainFileListItem* firstChild() const { return static_cast( KListView::firstChild() ); } + ReplayGainFileListItem* itemAt( const QPoint& point ) const { return static_cast( KListView::itemAt(point) ); } + + int columnByName( const QString& name ); + +protected: + virtual bool acceptDrag( QDropEvent *e ) const; + +private slots: + void columnResizeEvent( int, int, int ); + void openAlbums(); + void closeAlbums(); + void update(); + +public slots: + void addFile( const QString& ); + void addDir( const QString&, const QStringList& filter = "", bool recursive = true ); + void calcAllReplayGain( bool force ); + void removeAllReplayGain(); + void cancelProcess(); + +private: + /** Lists all file in a directory and adds them to the file list, if @p fast is false. The number of listed files is returned */ + int listDir( const QString& directory, QStringList filter, bool recursive = true, bool fast = false, int count = 0 ); + + /** A progressbar, that is shown, when a directory is added recursive */ + KProgress* pScanStatus; + + TagEngine* tagEngine; + Config* config; + Logger* logger; + + KProcess* process; + ReplayGain* replayGain; + int logID; + + void contentsDragEnterEvent( QDragEnterEvent *e ); + void contentsDragMoveEvent( QDragMoveEvent *e ); + void contentsDropEvent( QDropEvent *e ); + + void viewportPaintEvent( QPaintEvent* ); + void viewportResizeEvent( QResizeEvent* ); + + QSimpleRichText* bubble; + + void startProcess(); + + void processNextFile(); + + void calcReplayGain( ReplayGainFileListItem* ); + void removeReplayGain( ReplayGainFileListItem* ); + + bool queue; + ReplayGainFileListItem::Mode mode; + ReplayGainFileListItem* currentItem; + + QTimer* tUpdateProgress; + bool processing; // true, if the progress is active (hide some options in the context menu) + int percent; // the progress of the current file / album + int lastPercent; // cache the last percent in order to record a 'track change' + float time; // track length of all files + float processedTime; // the sum of all track lengths of the processed files + int files; // the number of files in the current album + int file; // the file that is being 'replay gained' + float timeCount; // the sum of all track lengths in the current album / the track length of the current file + + /** The context menu for editing or starting the files */ + KPopupMenu* contextMenu; + + KActionCollection* actionCollection; + KAction* calc_gain; + KAction* remove_gain; + KAction* newalbum; + KAction* remove; + KAction* paste; + KAction* open_albums; + KAction* close_albums; + +private slots: + void showContextMenu( QListViewItem*, const QPoint&, int ); + + /** + * Remove selected items from the file list + */ + void removeSelectedItems(); + + /** + * Creates a new 'album' item in the list view + */ + void createNewAlbum(); + + /** + * Calculates the replay gain tags of the selected items + */ + void calcSelectedItemsGain(); + + /** + * Remove the replay gain tags of the selected items + */ + void removeSelectedItemsGain(); + + void slotDropped( QDropEvent*, QListViewItem*, QListViewItem* ); // NOTE rename? + + void processOutput( KProcess*, char*, int ); + void processExit( KProcess* ); + +signals: + //void calcGain(); + //void removeGain(); +// void addFile( const QString& filename ); + + void processStarted(); + void processStopped(); + void updateProgress( int, int ); + +}; + +#endif // REPLAYGAINFILELIST_H diff --git a/src/replaygainscanner.cpp b/src/replaygainscanner.cpp new file mode 100755 index 0000000..9eb0bcd --- /dev/null +++ b/src/replaygainscanner.cpp @@ -0,0 +1,233 @@ + +#include "replaygainscanner.h" +#include "logger.h" +#include "combobutton.h" +#include "config.h" +#include "dirdialog.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +// FIXME file name encoding !!! + + +ReplayGainScanner::ReplayGainScanner( TagEngine* _tagEngine, Config* _config, Logger* _logger, QWidget *parent, const char *name, bool modal, WFlags f ) + : KDialog( parent, name, modal, f ) +{ + tagEngine = _tagEngine; + config = _config; + logger = _logger; + + // create an icon loader object for loading icons + KIconLoader* iconLoader = new KIconLoader(); + + setCaption( i18n("Replay Gain Tool") ); + resize( 600, 400 ); + setIcon( iconLoader->loadIcon("soundkonverter_replaygain",KIcon::Small) ); + + QGridLayout* grid = new QGridLayout( this, 4, 1, 11, 6 ); + + QHBoxLayout* filterBox = new QHBoxLayout(); + grid->addLayout( filterBox, 0, 0 ); + + cAdd = new ComboButton( this, "cAdd" ); + cAdd->insertItem( iconLoader->loadIcon("folder",KIcon::Small),i18n("Add Folder ...") ); + cAdd->insertItem( iconLoader->loadIcon("sound",KIcon::Small),i18n("Add Files ...") ); + filterBox->addWidget( cAdd ); + connect( cAdd, SIGNAL(clicked(int)), + this, SLOT(addClicked(int)) + ); + + filterBox->addStretch(); + + cForce = new QCheckBox( i18n("Force recalculation"), this, "cForce" ); + QToolTip::add( cForce, i18n("Recalculate Replay Gain tag for files that already have a Replay Gain tag set.") ); + filterBox->addWidget( cForce ); + + /*QLabel *lFilter=new QLabel(i18n("Show:"),this,"lFilter"); + filterBox->addWidget(lFilter); + + cFilter=new QComboBox(this,"cFilter"); + cFilter->insertItem(i18n("All")); + cFilter->insertItem(i18n("With Replay Gain")); + cFilter->insertItem(i18n("Without Replay Gain")); + cFilter->insertItem(i18n("Unknown")); + filterBox->addWidget(cFilter);*/ + + lList = new ReplayGainFileList( tagEngine, config, logger, this, "lList" ); + grid->addWidget( lList, 1, 0 ); + connect( this, SIGNAL(addFile(const QString&)), + lList, SLOT(addFile(const QString&)) + ); + connect( this, SIGNAL(addDir(const QString&,const QStringList&,bool)), + lList, SLOT(addDir(const QString&,const QStringList&,bool)) + ); + connect( this, SIGNAL(calcAllReplayGain(bool)), + lList, SLOT(calcAllReplayGain(bool)) + ); + connect( this, SIGNAL(removeAllReplayGain()), + lList, SLOT(removeAllReplayGain()) + ); + connect( this, SIGNAL(cancelProcess()), + lList, SLOT(cancelProcess()) + ); + connect( lList, SIGNAL(processStarted()), + this, SLOT(processStarted()) + ); + connect( lList, SIGNAL(processStopped()), + this, SLOT(processStopped()) + ); + connect( lList, SIGNAL(updateProgress(int,int)), + this, SLOT(updateProgress(int,int)) + ); + + QHBoxLayout* progressBox = new QHBoxLayout(); + grid->addLayout( progressBox, 2, 0 ); + + pProgressBar = new KProgress( this, "pProgressBar" ); + progressBox->addWidget( pProgressBar ); + + QHBoxLayout* buttonBox = new QHBoxLayout(); + grid->addLayout( buttonBox, 3, 0 ); + + pTagVisible = new KPushButton( iconLoader->loadIcon("apply",KIcon::Small), i18n("Tag untagged"), this, "pTagVisible" ); + QToolTip::add( pTagVisible, i18n("Calculate Replay Gain tag for all files in the file list without Replay Gain tag.") ); + buttonBox->addWidget( pTagVisible ); + connect( pTagVisible, SIGNAL(clicked()), + this, SLOT(calcReplayGainClicked()) + ); + + pRemoveTag = new KPushButton( iconLoader->loadIcon("cancel",KIcon::Small), i18n("Untag tagged"), this, "pRemoveTag" ); + QToolTip::add( pRemoveTag, i18n("Remove the Replay Gain tag from all files in the file list.") ); + buttonBox->addWidget( pRemoveTag ); + connect( pRemoveTag, SIGNAL(clicked()), + this, SLOT(removeReplayGainClicked()) + ); + + pCancel = new KPushButton( iconLoader->loadIcon("cancel",KIcon::Small),i18n("Cancel"), this, "pCancel" ); + pCancel->hide(); + buttonBox->addWidget( pCancel ); + connect( pCancel, SIGNAL(clicked()), + this, SLOT(cancelClicked()) + ); + + buttonBox->addStretch(); + + pOk = new KPushButton( iconLoader->loadIcon("exit",KIcon::Small), i18n("Close"), this, "pOk" ); + pOk->setFocus(); + buttonBox->addWidget( pOk ); + connect( pOk, SIGNAL(clicked()), + this, SLOT(accept()) + ); + + // delete the icon loader object + delete iconLoader; +} + +ReplayGainScanner::~ReplayGainScanner() +{} + +void ReplayGainScanner::addClicked( int index ) +{ + if( index == 1 ) { + showFileDialog(); + } + else { + showDirDialog(); + } +} + +void ReplayGainScanner::showFileDialog() +{ + KFileDialog* dialog = new KFileDialog( ":file_open", config->replayGainFilter(), this, i18n("Choose files!"), true ); + dialog->setMode ( KFile::Files | KFile::ExistingOnly ); + if( dialog->exec() == KDialog::Accepted ) { + QStringList urls = dialog->selectedURLs().toStringList(); + for( QStringList::Iterator it = urls.begin(); it != urls.end(); ++it ) { + emit addFile( *it ); + } + } +} + +void ReplayGainScanner::showDirDialog() +{ +// QString directory = KFileDialog::getExistingDirectory( ":file_open", this, i18n("Choose a directory!") ); +// if( directory != NULL ) +// { +// emit addDir( directory ); +// } + + DirDialog *dialog = new DirDialog( config, DirDialog::ReplayGain, this, "DirDialog" ); + + Q_CHECK_PTR( dialog ); + + if( dialog->exec() ) { + emit addDir( dialog->directory, dialog->selectedFileTypes, dialog->recursive ); + } + + delete dialog; +} + +void ReplayGainScanner::addFiles( QStringList files ) +{ + for( QStringList::Iterator it = files.begin(); it != files.end(); ++it ) { + emit addFile( *it ); + } +} + +void ReplayGainScanner::calcReplayGainClicked() +{ + emit calcAllReplayGain( cForce->isChecked() ); +} + +void ReplayGainScanner::removeReplayGainClicked() +{ + emit removeAllReplayGain(); +} + +void ReplayGainScanner::cancelClicked() +{ + emit cancelProcess(); +} + +void ReplayGainScanner::processStarted() +{ + pTagVisible->hide(); + pRemoveTag->hide(); + pCancel->show(); +} + +void ReplayGainScanner::processStopped() +{ + pTagVisible->show(); + pRemoveTag->show(); + pCancel->hide(); + pProgressBar->setProgress( 100 ); + pProgressBar->setTotalSteps( 100 ); + setCaption( i18n("Finished") + " - " + i18n("Replay Gain Tool") ); +} + +void ReplayGainScanner::updateProgress( int progress, int totalSteps ) +{ +/* pProgressBar->setProgress( int(processedTime) + percent * int(timeCount) / 100 ); + pProgressBar->setTotalSteps( int(time) );*/ + pProgressBar->setProgress( progress ); + pProgressBar->setTotalSteps( totalSteps ); + float fPercent; + if( pProgressBar->totalSteps() > 0 ) fPercent = pProgressBar->progress() * 100 / pProgressBar->totalSteps(); + else fPercent = 0; + + QString percent; + percent.sprintf( "%i%%", (int)fPercent ); + setCaption( percent + " - " + i18n("Replay Gain Tool") ); +} + diff --git a/src/replaygainscanner.h b/src/replaygainscanner.h new file mode 100755 index 0000000..6b2bfdc --- /dev/null +++ b/src/replaygainscanner.h @@ -0,0 +1,77 @@ + + +#ifndef REPLAYGAINSCANNER_H +#define REPLAYGAINSCANNER_H + +#include + +#include "replaygainfilelist.h" + +class Config; +class Logger; +class ComboButton; + +class QCheckBox; + +class KPushButton; +class KProgress; + + +/** + * @short The Replay Gain Tool + * @author Daniel Faust + * @version 0.3 + */ +class ReplayGainScanner : public KDialog +{ + Q_OBJECT +public: + /** + * Constructor + */ + ReplayGainScanner( TagEngine*, Config*, Logger*, QWidget* parent=0, const char* name=0, bool modal=true, WFlags f=0 ); + + /** + * Destructor + */ + virtual ~ReplayGainScanner(); + + void addFiles( QStringList ); + +private slots: + void addClicked( int ); + void showDirDialog(); + void showFileDialog(); + void calcReplayGainClicked(); + void removeReplayGainClicked(); + void cancelClicked(); + void processStarted(); + void processStopped(); + void updateProgress( int, int ); + +private: + ComboButton* cAdd; + QCheckBox* cForce; + //QComboBox* cFilter; + ReplayGainFileList* lList; + KProgress* pProgressBar; + KPushButton* pTagVisible; + KPushButton* pRemoveTag; + KPushButton* pCancel; + KPushButton* pOk; + + TagEngine* tagEngine; + Config* config; + Logger* logger; + + QTime elapsedTime; + +signals: + void addFile( const QString& ); + void addDir( const QString&, const QStringList& filter = "", bool recursive = true ); + void calcAllReplayGain( bool force ); + void removeAllReplayGain(); + void cancelProcess(); +}; + +#endif // REPLAYGAINSCANNER_H diff --git a/src/soundkonverter.cpp b/src/soundkonverter.cpp new file mode 100755 index 0000000..692f898 --- /dev/null +++ b/src/soundkonverter.cpp @@ -0,0 +1,780 @@ + +#include "soundkonverter.h" +#include "config.h" +#include "configdialog.h" +#include "logger.h" +#include "logviewer.h" +#include "options.h" +#include "filelist.h" +#include "progressindicator.h" +#include "cdmanager.h" +#include "cdopener.h" +#include "tagengine.h" +#include "combobutton.h" +#include "convert.h" +#include "progressindicator.h" +#include "replaygainscanner.h" +#include "cuesheeteditor.h" +// ### #include "aboutplugins.h" delayed to a future soundkonverter version +#include "optionsrequester.h" +#include "dirdialog.h" + +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +// TODO stop all processes on exit / clean tmp up + +// ### soundkonverter 0.4: save file list when kde session gets terminated + +soundKonverter::soundKonverter() + : KMainWindow( 0, "soundkonverter-mainwindow", WType_TopLevel | WDestructiveClose | WStyle_ContextHelp ), + DCOPObject( "soundkonverter-app" ) +{ + // this is our first startup, set instances to zero + instances = 0; + + replayGainScanner = 0; + cuesheetEditor = 0; + logViewer = 0; + + device = ""; + visible = true; + autoclose = false; + configStartPage = ConfigDialog::GeneralPage; + + logger = new Logger(); + logger->log( 1000, "This is soundKonverter 0.3.7" ); + #ifdef HAVE_MP4V2 + logger->log( 1000, "MP4v2 is enabled" ); + #else + logger->log( 1000, "MP4v2 is disabled" ); + #endif + + config = new Config( logger ); + config->read(); + + // (re)move the 0.2 config file + if( config->data.app.configVersion < 280 ) { + KIO::rename( locateLocal("config","soundkonverterrc"), locateLocal("config","soundkonverterrc.back"), true ); +// KMessageBox::information( this, "You are using a pre-release of soundKonverter. This version is designed for testing only.\nThere are a few things not implemented at the moment but it should run without crashes and big problems. So feel free to report such an error if you find one.\nPlease have a look at the README.\n\nYour old configuration file has been moved to soundkonverterrc.back." ); + } +// if( config->data.app.configVersion < 290 ) { +// QFile plugin_dir( locateLocal("data","soundkonverter/plugins") ); +// if( plugin_dir.exists() ) { +// KIO::rename( locateLocal("data","soundkonverter/plugins"), locateLocal("data","soundkonverter/plugins.back"), true ); +// int ret = KMessageBox::questionYesNo( this, i18n("soundKonverter has cleaned up it's old installation. It seems to be necessary to restart soundKonverter!\n\nDo you want to restart soundKonverter now?") ); +// if( ret == KMessageBox::Yes ) { +// config->write(); +// // TODO parameters are lost +// KProcess restart; +// restart << "soundkonverter"; +// restart.start( KProcess::DontCare ); +// kapp->quit(); +// return; +// } +// } +// } + + cdManager = new CDManager(); + tagEngine = new TagEngine(); + + resize( 640, 470 ); + + systemTray = new KSystemTray( this, "systemTray" ); + systemTray->hide(); + + // create an icon loader object for loading icons + KIconLoader *iconLoader = new KIconLoader(); + + QWidget* widget = new QWidget( this, "widget" ); + setCentralWidget( widget ); + + // NOTE created here because of some dependences + options = new Options( config, i18n("Choose your prefered output options and click on \"Add files ...\"!"), widget, "options" ); + fileList = new FileList( cdManager, tagEngine, config, options, logger, widget, "fileList" ); + + startAction = new KAction( i18n("&Start conversion"), "run", 0, fileList, SLOT(startConversion()), actionCollection(), "start" ); + startAction->setEnabled( false ); + new KAction( i18n("&Replay Gain Tool ..."), "soundkonverter_replaygain", CTRL+Key_R, this, SLOT(showReplayGainScanner()), actionCollection(), "replaygainscanner" ); + //new KAction( i18n("R&epair Tool ..."), "soundkonverter_repair", CTRL+Key_E, this, SLOT(showRepairTool()), actionCollection(), "repairtool" ); + new KAction( i18n("C&uesheet Editor ..."), "kwrite", CTRL+Key_U, this, SLOT(showCuesheetEditor()), actionCollection(), "cuesheeteditor" ); + new KAction( i18n("Show &Log ..."), "view_text", CTRL+Key_L, this, SLOT(showLogViewer()), actionCollection(), "log" ); +// new KAction( i18n("About &Plugins ..."), "connect_creating", CTRL+Key_P, this, SLOT(showAboutPlugins()), actionCollection(), "about_plugins" ); + + stopAction = new KAction( i18n("S&top after current file is complete"), "stop", CTRL+Key_O, fileList, SLOT(stopConversion()), actionCollection(), "stop" ); + continueAction = new KAction( i18n("&Continue after current file is complete"), "run", CTRL+Key_T, fileList, SLOT(continueConversion()), actionCollection(), "continue" ); + killAction = new KAction( i18n("Stop &immediately"), "exit", CTRL+Key_K, fileList, SLOT(killConversion()), actionCollection(), "kill" ); + stopActionMenu = new KActionMenu( i18n("Stop"), "stop", actionCollection(), "stopMenu" ); + stopActionMenu->setDelayed( false ); + stopActionMenu->setEnabled( false ); +// stopActionMenu->insert( stopAction ); +// stopActionMenu->insert( continueAction ); +// stopActionMenu->insert( killAction ); + +/* veryHighPriorityAction = new KToggleAction( i18n("Very hi&gh"), CTRL+Key_1, this, SLOT(priorityChanged()), actionCollection(), "veryhigh" ); + veryHighPriorityAction->setExclusiveGroup("priorityActionMenu"); + highPriorityAction = new KToggleAction( i18n("&High"), CTRL+Key_2, this, SLOT(priorityChanged()), actionCollection(), "high" ); + highPriorityAction->setExclusiveGroup("priorityActionMenu"); + normalPriorityAction = new KToggleAction( i18n("&Normal"), CTRL+Key_3, this, SLOT(priorityChanged()), actionCollection(), "nomal" ); + normalPriorityAction->setExclusiveGroup("priorityActionMenu"); + normalPriorityAction->setChecked(true); + lowPriorityAction = new KToggleAction( i18n("&Low"), CTRL+Key_4, this, SLOT(priorityChanged()), actionCollection(), "low" ); + lowPriorityAction->setExclusiveGroup("priorityActionMenu"); + veryLowPriorityAction = new KToggleAction( i18n("Very lo&w"), CTRL+Key_5, this, SLOT(priorityChanged()), actionCollection(), "verylow" ); + veryLowPriorityAction->setExclusiveGroup("priorityActionMenu"); + priorityActionMenu = new KActionMenu( i18n("En-/Decoder priority"), "ksysguard", actionCollection(), "priorityMenu" ); + priorityActionMenu->setDelayed( false ); + priorityActionMenu->insert(veryHighPriorityAction); + priorityActionMenu->insert(highPriorityAction); + priorityActionMenu->insert(normalPriorityAction); + priorityActionMenu->insert(lowPriorityAction); + priorityActionMenu->insert(veryLowPriorityAction);*/ + //priorityChanged(); + + new KAction( i18n("A&dd Files ..."), "sound", CTRL+Key_D, this, SLOT(showFileDialog()), actionCollection(), "add_files" ); + new KAction( i18n("Add &Folder ..."), "folder", CTRL+Key_F, this, SLOT(showDirDialog()), actionCollection(), "add_folder" ); + new KAction( i18n("Add CD &tracks ..."), "cdaudio_unmount", CTRL+Key_T, this, SLOT(showCdDialog()), actionCollection(), "add_audiocd" ); + new KAction( i18n("Add &URL ..."), "browser", CTRL+Key_U, this, SLOT(showUrlDialog()), actionCollection(), "add_url" ); + KStdAction::quit(this, SLOT(close()), actionCollection()); + + new KAction( i18n("L&oad file list"), "fileopen", 0, fileList, SLOT(load()), actionCollection(), "load" ); + new KAction( i18n("Sa&ve file list"), "filesave", 0, fileList, SLOT(save()), actionCollection(), "save" ); + + // TODO //KStdAction::paste( this, SLOT(pasteFiles()), actionCollection() ); + + KStdAction::preferences( this, SLOT(showConfigDialog()), actionCollection() ); + + showToolBarAction = KStdAction::showToolbar( this, SLOT(showToolbar()), actionCollection() ); + //KStdAction::showStatusbar( 0, 0, actionCollection() ); + KStdAction::configureToolbars( this, SLOT(editToolbar()), actionCollection() ); + + createGUI(); + + if( config->data.general.showToolBar ) { + toolBar()->show(); + showToolBarAction->setChecked( true ); + } + else { + toolBar()->hide(); + showToolBarAction->setChecked( false ); + } + + // the grid for all widgets in the main window + QGridLayout* gridLayout = new QGridLayout( widget, 1, 1, 6, 6, "gridLayout" ); + + // generate the options input area + // NOTE created above because of some dependences + //options = new Options( config, i18n("Choose your prefered output options and click on \"Add files ...\"!"), this, "options" ); + connect( options, SIGNAL(showConfigPluginsPage()), + this, SLOT(showConfigPluginsPage()) + ); + connect( options, SIGNAL(showConfigEnvironmentPage()), + this, SLOT(showConfigEnvironmentPage()) + ); + gridLayout->addWidget( options, 0, 0 ); + + // generate the list view for the file list + // NOTE created above because of some dependences + //fileList = new FileList( cdManager, tagEngine, config, options, this, "fileList" ); + gridLayout->addWidget( fileList, 1, 0 ); + gridLayout->setRowStretch( 1, 1 ); + /*connect( this, SIGNAL(windowMoved(int,int)), + fileList, SLOT(moveOptionsEditor(int,int)) + );*/ + connect( fileList, SIGNAL(fileCountChanged(int)), + this, SLOT(fileCountChanged(int)) + ); + connect( fileList, SIGNAL(startedConversion()), + this, SLOT(startedConversion()) + ); + connect( fileList, SIGNAL(stopClicked()), + this, SLOT(stopClicked()) + ); + connect( fileList, SIGNAL(continueClicked()), + this, SLOT(continueClicked()) + ); + connect( fileList, SIGNAL(stoppedConversion()), + this, SLOT(stoppedConversion()) + ); + + convert = new Convert( config, tagEngine, cdManager, fileList, logger ); +// connect( this, SIGNAL(setPriority(int)), +// convert, SLOT(priorityChanged(int)) +// ); + + // add a horizontal box layout for the add combobutton to the grid + QHBoxLayout *addBox = new QHBoxLayout( -1, "addBox" ); + gridLayout->addLayout( addBox, 2, 0 ); + + // create the combobutton for adding files to the file list + cAdd = new ComboButton( widget, "cAdd" ); + QFont font = cAdd->font(); + //font.setWeight( QFont::DemiBold ); + font.setPointSize( font.pointSize() + 1 ); + cAdd->setFont( font ); + cAdd->insertItem( iconLoader->loadIcon("sound",KIcon::Toolbar), i18n("Add files ...") ); + cAdd->insertItem( iconLoader->loadIcon("folder",KIcon::Toolbar), i18n("Add folder ...") ); + cAdd->insertItem( iconLoader->loadIcon("cdaudio_unmount",KIcon::Toolbar), i18n("Add CD tracks ...") ); + cAdd->insertItem( iconLoader->loadIcon("browser",KIcon::Toolbar), i18n("Add URL ...") ); + addBox->addWidget( cAdd ); + connect( cAdd, SIGNAL(clicked(int)), + this, SLOT(addClicked(int)) + ); + + addBox->addSpacing( 18 ); + + pStart = new KPushButton( iconLoader->loadIcon("run",KIcon::Small), i18n("Start"), widget, "pStart" ); + pStart->setFixedHeight( pStart->size().height() ); + pStart->setEnabled( false ); + addBox->addWidget( pStart ); + connect( pStart, SIGNAL(clicked()), + fileList, SLOT(startConversion()) + ); + + pStop = new KPushButton( iconLoader->loadIcon("stop",KIcon::Small), i18n("Stop"), widget, "pStop" ); + pStop->setFixedHeight( pStop->size().height() ); + pStop->hide(); + pStop->setPopup( stopActionMenu->popupMenu() ); + addBox->addWidget( pStop ); + + addBox->addSpacing( 8 ); + + progressIndicator = new ProgressIndicator( systemTray, widget, "progressIndicator" ); + addBox->addWidget( progressIndicator ); + connect( fileList, SIGNAL(increaseTime(float)), + progressIndicator, SLOT(increaseTime(float)) + ); + connect( fileList, SIGNAL(decreaseTime(float)), + progressIndicator, SLOT(decreaseTime(float)) + ); + /*connect( fileList, SIGNAL(setTime(float)), + progressIndicator, SLOT(setTime(float)) + );*/ + connect( fileList, SIGNAL(finished(float)), + progressIndicator, SLOT(finished(float)) + ); + connect( convert, SIGNAL(countTime(float)), + progressIndicator, SLOT(countTime(float)) + ); + connect( convert, SIGNAL(uncountTime(float)), + progressIndicator, SLOT(uncountTime(float)) + ); + connect( convert, SIGNAL(update(float)), + progressIndicator, SLOT(update(float)) + ); + connect( progressIndicator, SIGNAL(setTitle(const QString&)), + this, SLOT(setTitle(const QString&)) + ); + + cAdd->increaseHeight( /*progressIndicator->height() - cAdd->height()*/ 10 ); // FIXME detect the height automaticly + cAdd->adjustSize(); + + // delete the icon loader object + delete iconLoader; + + fileList->load( true ); // restore file list after a crash +} + +soundKonverter::~soundKonverter() +{ + // TODO clean tmp dir (stop all running processes) + delete replayGainScanner; + delete cuesheetEditor; + delete logViewer; +} + +void soundKonverter::increaseInstances() +{ + // a new instance should be created, so this isn't the initial startup no longer + instances++; +} + +bool soundKonverter::queryClose() +{ + config->removeProfile( i18n("Last used") ); + config->addProfile( i18n("Last used"), options->getCurrentOptions() ); + + config->write( false ); + + convert->cleanUp(); + logger->cleanUp(); + + QFile::remove( locateLocal("data","soundkonverter/filelist.autosave.xml") ); + + return true; +} + +void soundKonverter::setNotify( const QString& cmd ) +{ + fileList->setNotify( cmd ); +} + +/*void soundKonverter::moveEvent( QMoveEvent* e ) +{ +// emit windowMoved( pos().x(), pos().y() + height() ); +}*/ + +void soundKonverter::openArgFiles( const QStringList &files ) +{ + if( ( instances <= 1 || config->data.general.askForNewOptions ) && ( profile == "" || format == "" || directory == "" ) ) + { + OptionsRequester* dialog = new OptionsRequester( config, files, this ); + + connect( dialog, SIGNAL(setCurrentOptions(const ConversionOptions&)), + options, SLOT(setCurrentOptions(const ConversionOptions&)) + ); + connect( dialog, SIGNAL(addFiles(QStringList)), + fileList, SLOT(addFiles(QStringList)) + ); + + Q_CHECK_PTR( dialog ); + + if( profile != "" ) { + dialog->setProfile( profile ); + profile = ""; + } + if( format != "" ) { + dialog->setFormat( format ); + format = ""; + } + if( directory != "" ) { + dialog->setOutputDirectory( directory ); + directory = ""; + } + + dialog->exec(); + + disconnect( dialog, SIGNAL(setCurrentOptions(const ConversionOptions&)), 0, 0 ); + disconnect( dialog, SIGNAL(addFiles(QStringList)), 0, 0 ); + + delete dialog; + } + else + { + ConversionOptions conversionOptions = options->getCurrentOptions(); + + if( profile != "" ) { + options->setProfile( profile ); + profile = ""; + } + if( format != "" ) { + options->setFormat( format ); + format = ""; + } + if( directory != "" ) { + options->setOutputDirectory( directory ); + directory = ""; + } + fileList->addFiles( files ); + + options->setCurrentOptions( conversionOptions ); + } + + if( !visible ) fileList->startConversion(); // NOTE should be save! +} + +void soundKonverter::openArgReplayGainFiles( const QStringList &files ) +{ + showReplayGainScanner(); + if( replayGainScanner ) replayGainScanner->addFiles( files ); +} + +// void soundKonverter::openArgRepairFiles( const QStringList &files ) +// {} + +void soundKonverter::startedConversion() +{ + pStart->hide(); + if( fileList->queueEnabled() ) + { + startAction->setEnabled( false ); + startAction->setText( i18n("&Start conversion") ); + stopActionMenu->remove( startAction ); + stopActionMenu->remove( stopAction ); + stopActionMenu->remove( continueAction ); + stopActionMenu->remove( killAction ); + stopActionMenu->insert( stopAction ); + stopActionMenu->insert( continueAction ); + stopActionMenu->insert( killAction ); + } + else + { + startAction->setEnabled( true ); + startAction->setText( i18n("&Start queue") ); + stopActionMenu->remove( startAction ); + stopActionMenu->remove( stopAction ); + stopActionMenu->remove( continueAction ); + stopActionMenu->remove( killAction ); + stopActionMenu->insert( killAction ); + stopActionMenu->insert( startAction ); + } + pStop->show(); + stopActionMenu->setEnabled( true ); + stopAction->setEnabled( true ); + continueAction->setEnabled( false ); + killAction->setEnabled( true ); +} + +void soundKonverter::stopClicked() +{ + stopAction->setEnabled( false ); + continueAction->setEnabled( true ); +} + +void soundKonverter::continueClicked() +{ + stopAction->setEnabled( true ); + continueAction->setEnabled( false ); +} + +void soundKonverter::stoppedConversion() +{ + pStart->show(); + startAction->setEnabled( true ); + startAction->setText( i18n("&Start conversion") ); + pStop->hide(); + stopActionMenu->setEnabled( false ); + + if( autoclose ) kapp->quit(); // NOTE close app on conversion stop (may irritate the user when stopping the conversion) +} + +// void soundKonverter::priorityChanged() +// { +// int priority = 0; +// +// //if( veryHighPriorityAction->isChecked() ) priority=-19; +// //else if( highPriorityAction->isChecked() ) priority=-10; +// if( lowPriorityAction->isChecked() ) priority = 10; +// else if( veryLowPriorityAction->isChecked() ) priority = 20; +// +// emit setPriority( priority ); +// } + +void soundKonverter::addClicked( int index ) +{ + fileList->save( true ); + + if( index == 0 ) { + showFileDialog(); + } + else if( index == 1 ) { + showDirDialog(); + } + else if( index == 2 ) { + showCdDialog( true ); + } + else { + showUrlDialog(); + } + + fileList->save( true ); +} + +void soundKonverter::showFileDialog() +{ + QStringList urls = KFileDialog::getOpenURLs( ":file_open", config->fileFilter(), this, i18n("Choose files to convert") ).toStringList(); + if( !urls.empty() ) { +/* for( QStringList::Iterator it = urls.begin(); it != urls.end(); ++it ) { + *it = KURL::decode_string( *it ); + }*/ + fileList->addFiles( urls ); + } +} + +void soundKonverter::showDirDialog() +{ +// QString directory = KFileDialog::getExistingDirectory( ":file_open", this, i18n("Choose a directory") ); +// if( !directory.isEmpty() ) +// { +// fileList->addDir( directory ); +// } + + DirDialog *dialog = new DirDialog( config, DirDialog::Convert, this, "DirDialog" ); + + Q_CHECK_PTR( dialog ); + + if( dialog->exec() ) { + fileList->addDir( dialog->directory, dialog->selectedFileTypes, dialog->recursive ); + } + + delete dialog; +} + +void soundKonverter::showCdDialog( bool intern ) +{ + ConversionOptions conversionOptions = options->getCurrentOptions(); + + if( ( instances <= 1 || config->data.general.askForNewOptions ) && ( profile == "" || format == "" || directory == "" ) && !intern ) + { + OptionsRequester* dialog = new OptionsRequester( config, "", this ); + + connect( dialog, SIGNAL(setCurrentOptions(const ConversionOptions&)), + options, SLOT(setCurrentOptions(const ConversionOptions&)) + ); +// connect( dialog, SIGNAL(addFiles(QStringList)), +// fileList, SLOT(addFiles(QStringList)) +// ); + + Q_CHECK_PTR( dialog ); + + if( profile != "" ) { + dialog->setProfile( profile ); + profile = ""; + } + if( format != "" ) { + dialog->setFormat( format ); + format = ""; + } + if( directory != "" ) { + dialog->setOutputDirectory( directory ); + directory = ""; + } + + dialog->exec(); + + disconnect( dialog, SIGNAL(setCurrentOptions(const ConversionOptions&)), 0, 0 ); +// disconnect( dialog, SIGNAL(addFiles(QStringList)), 0, 0 ); + + delete dialog; + } + else + { + if( profile != "" ) { + options->setProfile( profile ); + profile = ""; + } + if( format != "" ) { + options->setFormat( format ); + format = ""; + } + if( directory != "" ) { + options->setOutputDirectory( directory ); + directory = ""; + } + } + + // support for media:/ and system:/ urls + if( !device.isEmpty() ) { + device.replace( "system:/media", "/dev" ); + device.replace( "media:", "/dev" ); + device.replace( "devices:", "/dev" ); // NOTE obsolete, since soundkonverter 0.3 won't run on KDE < 3.5 + } + if( device.left(5) != "/dev/" || device == "auto" ) { + device = ""; + } + + kapp->eventLoop()->exitLoop(); + + // create a new CDOpener object for letting the user add some tracks from a CD + CDOpener *dialog = new CDOpener( config, cdManager, tagEngine, device, this, "CDOpener" ); + + device = ""; + + Q_CHECK_PTR( dialog ); + + if( !dialog->noCD ) + { + connect( dialog, SIGNAL(addTracks(const QString&,QValueList)), + fileList, SLOT(addTracks(const QString&,QValueList)) + ); + connect( dialog, SIGNAL(addDisc(const QString&)), + fileList, SLOT(addDisc(const QString&)) + ); + /*connect( dialog, SIGNAL(openCuesheetEditor(const QString&)), + this, SLOT(openCuesheetEditor(const QString&)) + );*/ + + dialog->exec(); + + disconnect( dialog, SIGNAL(addTracks(const QString&,QValueList)), 0, 0 ); + disconnect( dialog, SIGNAL(addDisc(const QString&)), 0, 0 ); + //disconnect( dialog, SIGNAL(openCuesheetEditor(const QString&)), 0, 0 ); + } + delete dialog; + + kapp->eventLoop()->enterLoop(); + + options->setCurrentOptions( conversionOptions ); +} + +void soundKonverter::showUrlDialog() +{ + bool ok; + QString url = KInputDialog::getText( i18n("Open URL"), i18n("Enter a URL:"), "", &ok ); + if( ok ) + { + // if it isn't a local file and no protocol is given, we assume, it's http + if( url.left(1) != "/" && !url.contains(":/") ) + url.prepend( "http://" ); + + fileList->addFiles( url ); + } +} + +void soundKonverter::showReplayGainScanner() +{ + if( replayGainScanner == 0 ) { + replayGainScanner = new ReplayGainScanner( tagEngine, config, logger, 0, "replayGainScanner", false ); + if( replayGainScanner == 0 ) { + // TODO error message + return; + } +// connect( this, SIGNAL(addFilesToReplayGainScanner(QStringList)), +// replayGainScanner, SLOT(addFiles(QStringList)) +// ); + } + replayGainScanner->show(); + replayGainScanner->raise(); +} + +void soundKonverter::showRepairTool() +{} + +void soundKonverter::showCuesheetEditor() +{ + if( cuesheetEditor == 0 ) { + cuesheetEditor = new CuesheetEditor( 0, "cuesheetEditor", false ); + if( cuesheetEditor == 0 ) { + // TODO error message + return; + } + } + cuesheetEditor->show(); + cuesheetEditor->raise(); +} + +/*void soundKonverter::openCuesheetEditor( const QString& content ) +{ + if( cuesheetEditor == 0 ) { + cuesheetEditor = new CuesheetEditor( 0, "cuesheetEditor", false ); + if( cuesheetEditor == 0 ) { + // TODO error message + return; + } + } + cuesheetEditor->setContent( content ); + cuesheetEditor->show(); +}*/ + +void soundKonverter::showLogViewer() +{ + if( logViewer == 0 ) { + logViewer = new LogViewer( logger, 0, "logViewer", false ); + if( logViewer == 0 ) { + // TODO error message + return; + } +// connect( convert, SIGNAL(finishedProcess(int,int)), +// logViewer, SLOT(processCompleted(int,int)) +// ); + } + logViewer->show(); + logViewer->raise(); +} + +void soundKonverter::showConfigDialog() +{ + ConfigDialog *dialog = new ConfigDialog( config, this, "ConfigDialog", ConfigDialog::Page(configStartPage) ); + + Q_CHECK_PTR( dialog ); + + //dialog->setGeometry( frameGeometry() ); + dialog->resize( size() ); + + dialog->exec(); + + delete dialog; + + configStartPage = ConfigDialog::GeneralPage; +} + +void soundKonverter::showConfigPluginsPage() +{ + configStartPage = ConfigDialog::PluginsPage; + showConfigDialog(); +} + +void soundKonverter::showConfigEnvironmentPage() +{ + configStartPage = ConfigDialog::EnvironmentPage; + showConfigDialog(); +} + +// void soundKonverter::showAboutPlugins() +// { +// AboutPlugins *dialog = new AboutPlugins( config, this, "AboutPlugins" ); +// +// Q_CHECK_PTR( dialog ); +// +// dialog->exec(); +// +// delete dialog; +// } + +void soundKonverter::showToolbar() +{ + if( showToolBarAction->isChecked() ) { + toolBar()->show(); + config->data.general.showToolBar = true; + } + else { + toolBar()->hide(); + config->data.general.showToolBar = false; + } +} + +void soundKonverter::editToolbar() +{ + saveMainWindowSettings( kapp->config(), "MainWindow" ); + KEditToolbar dlg( actionCollection() ); + connect( &dlg, SIGNAL(newToolbarConfig()), + this, SLOT(newToolbarConfig()) + ); + dlg.exec(); +} + +void soundKonverter::newToolbarConfig() +{ + createGUI(); + applyMainWindowSettings( kapp->config(), "MainWindow" ); +} + +void soundKonverter::fileCountChanged( int count ) +{ + if( count > 0 ) { + startAction->setEnabled( true ); + pStart->setEnabled( true ); + } + else { + startAction->setEnabled( false ); + pStart->setEnabled( false ); + } +} + +void soundKonverter::setTitle( const QString& title ) +{ + setCaption( title ); +} + + +#include "soundkonverter.moc" diff --git a/src/soundkonverter.desktop b/src/soundkonverter.desktop new file mode 100755 index 0000000..967b83a --- /dev/null +++ b/src/soundkonverter.desktop @@ -0,0 +1,15 @@ +[Desktop Entry] +Categories=Qt;KDE;AudioVideo;AudioVideoEditing +Encoding=UTF-8 +Name=soundKonverter +Exec=soundkonverter +Icon=soundkonverter +Type=Application +X-DCOP-ServiceType=Unique +Comment=An audio converter and CD ripper +Comment[de]=Ein Audiokonverter und CD Ripper +Comment[fr]=Convertisseur de fichiers audio +GenericName=Audio files converter and CD ripper +GenericName[de]=Audiodateien Konvertierer und CD Ripper +GenericName[fr]=Convertisseur Audio +Terminal=false diff --git a/src/soundkonverter.h b/src/soundkonverter.h new file mode 100755 index 0000000..ce441cf --- /dev/null +++ b/src/soundkonverter.h @@ -0,0 +1,206 @@ + + +#ifndef SOUNDKONVERTER_H +#define SOUNDKONVERTER_H + +#include "dcopinterface.h" + +#include + +class Config; +class Options; +class FileList; +class ProgressIndicator; +class ComboButton; +class CDManager; +class TagEngine; +class Convert; +class ReplayGainScanner; +class CuesheetEditor; +class Logger; +class LogViewer; + +class QProgressBar; +class KPushButton; +class KAction; +class KToggleAction; +class KActionMenu; +class KSystemTray; + +/** + * @short The main window and connections to all other classes + * @author Daniel Faust + * @version 0.3 + */ +class soundKonverter : public KMainWindow, virtual public DCOPInterface +{ + Q_OBJECT +public: + /** + * Constructor + */ + soundKonverter(); + + /** + * Destructor + */ + virtual ~soundKonverter(); + + /** + * When a new instance of soundKonverter should be created, + * this function is called and all @p files are passed, that should be opened (for conversion). + */ + void openArgFiles( const QStringList &files ); + + /** + * When a new instance of soundKonverter should be created, + * this function is called and all @p files are passed, that should be opened for editing the replaygain tag. + */ + void openArgReplayGainFiles( const QStringList &files ); + + /* + * When a new instance of soundKonverter should be created, + * this function is called and all @p files are passed, that should be opened for repair. + */ +// void openArgRepairFiles( const QStringList &files ); + + /** + * When a new instance of soundKonverter should be created, + * this function is called and instances is increased. + */ + void increaseInstances(); + + /** + * Returns the number of 'started' instances + */ + int getInstances() { return instances; } + + QString device; + QString format; + QString profile; + QString directory; + bool visible; + bool autoclose; + void setNotify( const QString& cmd ); + + /** A system tray icon that is shown, when the main window is hidden */ + KSystemTray* systemTray; + + //virtual void moveEvent( QMoveEvent* ); + +protected: + virtual bool queryClose(); + +private: + /** Saves the amount of calls to create a new instance (only one instance is running at the same time) */ + int instances; + + /** All configuration information */ + Config* config; + + /** Log everything */ + Logger* logger; + + /** Show the logs */ + LogViewer* logViewer; + + /** The widget, where we can set our output options */ + Options* options; + + /** The list view with all files (for conversion) */ + FileList* fileList; + + /** Displays the current progress */ + ProgressIndicator* progressIndicator; + + /** The CD manager */ + CDManager* cdManager; + + /** The tag engine */ + TagEngine* tagEngine; + + /** The conversion engine */ + Convert* convert; + + /** The Replay Gain tool */ + ReplayGainScanner* replayGainScanner; + + /** The cuesheet editor */ + CuesheetEditor* cuesheetEditor; + + /** The combobutton for adding files */ + ComboButton* cAdd; + + /** The button to start the conversion */ + KPushButton* pStart; + + /** The button to stop the conversion */ + KPushButton* pStop; + + KAction* startAction; + KAction* stopAction; + KAction* continueAction; + KAction* killAction; + KActionMenu* stopActionMenu; + KToggleAction* showToolBarAction; +// KToggleAction* veryHighPriorityAction; +// KToggleAction* highPriorityAction; +// KToggleAction* normalPriorityAction; +// KToggleAction* lowPriorityAction; +// KToggleAction* veryLowPriorityAction; +// KActionMenu* priorityActionMenu; + + int configStartPage; + +private slots: + /** + * The conversion has started + */ + void startedConversion(); + + /** + * The user clicked on stop/continue conversion + */ + void stopClicked(); + void continueClicked(); + + /** + * The conversion has stopped + */ + void stoppedConversion(); +// void priorityChanged(); + + /** + * The combobutton for adding files was clicked and the item @p index was selected + */ + void addClicked( int index ); + + void showReplayGainScanner(); + void showRepairTool(); + void showCuesheetEditor(); + void showLogViewer(); + void showConfigDialog(); + void showConfigPluginsPage(); + void showConfigEnvironmentPage(); +// void showAboutPlugins(); + void showToolbar(); + void editToolbar(); + void newToolbarConfig(); + void fileCountChanged( int ); + void setTitle( const QString& ); + + //void openCuesheetEditor( const QString& content ); + +public slots: + void showFileDialog(); + void showDirDialog(); + void showCdDialog( bool intern = true ); + void showUrlDialog(); + +signals: + //void windowMoved( int x, int y ); +// void setPriority( int ); +// void addFilesToReplayGainScanner( QStringList ); +}; + +#endif // SOUNDKONVERTER_H diff --git a/src/soundkonverterapp.cpp b/src/soundkonverterapp.cpp new file mode 100755 index 0000000..91ea877 --- /dev/null +++ b/src/soundkonverterapp.cpp @@ -0,0 +1,133 @@ + +#include "soundkonverterapp.h" +#include "soundkonverter.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +soundKonverterApp::soundKonverterApp() + : KUniqueApplication() +{} + +soundKonverterApp::~soundKonverterApp() +{} + +int soundKonverterApp::newInstance() +{ + // register ourselves as a dcop client + if( !dcopClient()->isRegistered() ) + dcopClient()->registerAs( name(), false ); + + // see if we are starting with session management + if( restoringSession() ) + { + RESTORE( soundKonverter ); + } + else + { + // no session.. just start up normally + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + + if( !mainWidget() ) + { + soundKonverter *widget = new soundKonverter(); + setMainWidget(widget); + //widget->show(); + } + else + KStartupInfo::setNewStartupId( mainWidget(), kapp->startupId()); + + soundKonverter *widget = ::qt_cast( mainWidget() ); + + widget->increaseInstances(); + + QCString notify = args->getOption( "command" ); + if( notify ) { + widget->setNotify( notify ); + } + + QCString profile = args->getOption( "profile" ); + if( profile ) { + widget->profile = profile; + } + + QCString format = args->getOption( "format" ); + if( format ) { + widget->format = format; + } + + QCString directory = args->getOption( "output" ); + if( directory ) { + widget->directory = directory; + } + + QCString device = args->getOption( "rip" ); + if( device ) { + if( !args->isSet( "invisible" ) ) { + widget->visible = true; + widget->show(); + widget->systemTray->hide(); + widget->systemTray->setPixmap( 0 ); + } + widget->device = device; + widget->showCdDialog( false ); + } + + widget->autoclose = args->isSet( "autoclose" ); + + if( args->isSet( "invisible" ) ) { + widget->visible = false; + widget->autoclose = true; + widget->hide(); + widget->systemTray->show(); + KStandardDirs* stdDirs = new KStandardDirs(); + widget->systemTray->setMovie( QMovie(stdDirs->findResource("data","soundkonverter/pics/systray.mng")) ); + delete stdDirs; + } + else { + widget->visible = true; + widget->show(); + widget->systemTray->hide(); + widget->systemTray->setPixmap( 0 ); + } + + // add the files to the file lists depending on the used switch + if( args->isSet( "replaygain" ) ) { + QStringList replayGainFiles; + for( int i = 0; i < args->count(); i++ ) { + replayGainFiles.append(KURL::encode_string(args->arg(i))); + } + if(!replayGainFiles.isEmpty()) + widget->openArgReplayGainFiles(replayGainFiles); + } +// else if( args->isSet( "repair" ) ) { +// QStringList repairFiles; +// for( int i = 0; i < args->count(); i++ ) { +// repairFiles.append(QFile::decodeName(args->arg(i))); +// } +// if(!repairFiles.isEmpty()) +// widget->openArgRepairFiles(repairFiles); +// } + else { + QStringList files; + for( int i = 0; i < args->count(); i++ ) + { + files.append(KURL::encode_string(args->arg(i))); + } + if(!files.isEmpty()) + widget->openArgFiles(files); + } + + args->clear(); + } + return 0; +} + diff --git a/src/soundkonverterapp.h b/src/soundkonverterapp.h new file mode 100755 index 0000000..77e5b9f --- /dev/null +++ b/src/soundkonverterapp.h @@ -0,0 +1,37 @@ + + +#ifndef SOUNDKONVERTERAPP_H +#define SOUNDKONVERTERAPP_H + +#include "dcopinterface.h" + +#include + +class soundKonverter; + +/** + * @short The soundKonverter application. It controlles ensures that there can only run one instance of soundKonverter. + * @author Daniel Faust + * @version 0.3 + */ +class soundKonverterApp : public KUniqueApplication +{ + Q_OBJECT +public: + /** + * Constructor. + */ + soundKonverterApp(); + + /** + * Destructor + */ + virtual ~soundKonverterApp(); + + /** + * This function is called, when a new instance of soundKonverter should be created. + */ + virtual int newInstance(); +}; + +#endif // SOUNDKONVERTERAPP_H diff --git a/src/soundkonverterui.rc b/src/soundkonverterui.rc new file mode 100755 index 0000000..cfda25d --- /dev/null +++ b/src/soundkonverterui.rc @@ -0,0 +1,40 @@ + + + + + + + + + + + + + &Conversion + + + + + + + + + + + + + diff --git a/src/userscript.sh b/src/userscript.sh new file mode 100755 index 0000000..3f7714b --- /dev/null +++ b/src/userscript.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +COVERNAMES="cover.jpg cover.png front.jpg front.png" + +for COVERNAME in $COVERNAMES; do + + S_FILENAME=`echo "$1" | sed "s/^.*\///"` + S_DIRECTORY=`echo "$1" | sed "s/$S_FILENAME//"` + SOURCE=`ls "$S_DIRECTORY" | grep -F $COVERNAME` + + D_FILENAME=`echo "$2" | sed "s/^.*\///"` + D_DIRECTORY=`echo "$2" | sed "s/$D_FILENAME//"` + DESTINATION="$COVERNAME" + + if [ $SOURCE ]; then +# echo "cp $S_DIRECTORY$SOURCE $D_DIRECTORY$DESTINATION" + cp --update "$S_DIRECTORY$SOURCE" "$D_DIRECTORY$DESTINATION" + fi + +done + +exit 0 diff --git a/stamp-h.in b/stamp-h.in new file mode 100644 index 0000000..e69de29