diff options
author | Ross Burton <rburton@src.gnome.org> | 2003-03-30 20:28:32 +0000 |
---|---|---|
committer | Ross Burton <rburton@src.gnome.org> | 2003-03-30 20:28:32 +0000 |
commit | 36ff0dc5f60f5d69ba2b4f6179f5f129945e6f53 (patch) | |
tree | da2734767d67cf35c2b608c93f96fc3c9258309e |
Initial revision
38 files changed, 5269 insertions, 0 deletions
@@ -0,0 +1 @@ +Ross Burton <ross@burtonini.com> @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. + + <signature of Ty Coon>, 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..e69de29 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,229 @@ +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software +Foundation, Inc. + + This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +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, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + 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 you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' 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 awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +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 support 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. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + 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' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + 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 machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the `--target=TYPE' option to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +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. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +will cause the specified gcc to be used as the C compiler (unless it is +overridden in the site shell script). + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..5da004c --- /dev/null +++ b/Makefile.am @@ -0,0 +1,13 @@ +SUBDIRS = tests + +INTLTOOL_BUILT = \ + intltool-extract \ + intltool-merge \ + intltool-update + +EXTRA_DIST = \ + autogen.sh \ + $(INTLTOOL_BUILT:=.in) \ + NOTES + +CLEANFILES = $(INTLTOOL_BUILT) @@ -0,0 +1,13 @@ +Either pass in an AlbumDetails* to sj_gstreamer_extract_track(), or +put an AlbumDetails* into each TrackDetails. This means we can set the +album name. + +Use GConf. Keys so far: +/apps/sound-juicer/base_path (string, default "") +/apps/sound-juicer/device (string, default "") + +GErrorify everywhere! + +Instead of using an int counter, lookup the track number too? + +Find out why track duration doesn't work on MB. diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..75b9849 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,358 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + +#name of package +PKG_NAME=${PKG_NAME:Sound Juicer} +srcdir=${srcdir:-.} + +# default version requirements ... +REQUIRED_AUTOCONF_VERSION=${REQUIRED_AUTOCONF_VERSION:-2.53} +REQUIRED_AUTOMAKE_VERSION=${REQUIRED_AUTOMAKE_VERSION:-1.7} +REQUIRED_LIBTOOL_VERSION=${REQUIRED_LIBTOOL_VERSION:-1.4.3} +REQUIRED_GETTEXT_VERSION=${REQUIRED_GETTEXT_VERSION:-0.10.40} +REQUIRED_GLIB_GETTEXT_VERSION=${REQUIRED_GLIB_GETTEXT_VERSION:-2.2.0} +REQUIRED_INTLTOOL_VERSION=${REQUIRED_INTLTOOL_VERSION:-0.25} +REQUIRED_PKG_CONFIG_VERSION=${REQUIRED_PKG_CONFIG_VERSION:-0.14.0} +REQUIRED_GTK_DOC_VERSION=${REQUIRED_GTK_DOC_VERSION:-1.0} + +# a list of required m4 macros. Package can set an initial value +REQUIRED_M4MACROS=${REQUIRED_M4MACROS:-} +FORBIDDEN_M4MACROS=${FORBIDDEN_M4MACROS:-} + +# if GNOME2_DIR set, modify ACLOCAL_FLAGS ... +if [ -n "$GNOME2_DIR" ]; then + ACLOCAL_FLAGS="-I $GNOME2_DIR/share/aclocal $ACLOCAL_FLAGS" + LD_LIBRARY_PATH="$GNOME2_DIR/lib:$LD_LIBRARY_PATH" + PATH="$GNOME2_DIR/bin:$PATH" + export PATH + export LD_LIBRARY_PATH +fi + + +# some terminal codes ... +boldface="`tput bold 2>/dev/null`" +normal="`tput sgr0 2>/dev/null`" +printbold() { + echo -n "$boldface" + echo "$@" + echo -n "$normal" +} +printerr() { + echo "$@" >&2 +} + +# Usage: +# compare_versions MIN_VERSION ACTUAL_VERSION +# returns true if ACTUAL_VERSION >= MIN_VERSION +compare_versions() { + local min_version actual_version status save_IFS cur min + min_version=$1 + actual_version=$2 + status=0 + IFS="${IFS= }"; save_IFS="$IFS"; IFS="." + set $actual_version + for min in $min_version; do + cur=`echo $1 | sed 's/[^0-9].*$//'`; shift # remove letter suffixes + if [ -z "$min" ]; then break; fi + if [ -z "$cur" ]; then status=1; break; fi + if [ $cur -gt $min ]; then break; fi + if [ $cur -lt $min ]; then status=1; break; fi + done + IFS="$save_IFS" + return $status +} + +# Usage: +# version_check PACKAGE VARIABLE CHECKPROGS MIN_VERSION SOURCE +# checks to see if the package is available +version_check() { + local package variable checkprogs min_version source status checkprog actual_version + package=$1 + variable=$2 + checkprogs=$3 + min_version=$4 + source=$5 + status=1 + + checkprog=`eval echo "\\$$variable"` + if [ -n "$checkprog" ]; then + printbold "using $checkprog for $package" + return 0 + fi + + printbold "checking for $package >= $min_version..." + for checkprog in $checkprogs; do + echo -n " testing $checkprog... " + if $checkprog --version < /dev/null > /dev/null 2>&1; then + actual_version=`$checkprog --version | head -1 | \ + sed 's/^.*[ ]\([0-9.]*[a-z]*\).*$/\1/'` + if compare_versions $min_version $actual_version; then + echo "found." + # set variable + eval "$variable=$checkprog" + status=0 + break + else + echo "too old (found version $actual_version)" + fi + else + echo "not found." + fi + done + if [ "$status" != 0 ]; then + printerr "***Error***: You must have $package >= $min_version installed" + printerr " to build $PKG_NAME. Download the appropriate package for" + printerr " from your distribution or get the source tarball at" + printerr " $source" + printerr + fi + return $status +} + +# Usage: +# require_m4macro filename.m4 +# adds filename.m4 to the list of required macros +require_m4macro() { + case "$REQUIRED_M4MACROS" in + $1\ * | *\ $1\ * | *\ $1) ;; + *) REQUIRED_M4MACROS="$REQUIRED_M4MACROS $1" ;; + esac +} + +forbid_m4macro() { + case "$FORBIDDEN_M4MACROS" in + $1\ * | *\ $1\ * | *\ $1) ;; + *) FORBIDDEN_M4MACROS="$FORBIDDEN_M4MACROS $1" ;; + esac +} + +# Usage: +# check_m4macros +# Checks that all the requested macro files are in the aclocal macro path +# Uses REQUIRED_M4MACROS and ACLOCAL variables. +check_m4macros() { + local macrodirs status macro dir macrofound + + # construct list of macro directories + macrodirs="`$ACLOCAL --print-ac-dir`" + set - $ACLOCAL_FLAGS + while [ $# -gt 0 ]; do + if [ "$1" = "-I" ]; then + macrodirs="$macrodirs $2" + shift + fi + shift + done + + status=0 + if [ -n "$REQUIRED_M4MACROS" ]; then + printbold "Checking for required M4 macros..." + # check that each macro file is in one of the macro dirs + for macro in $REQUIRED_M4MACROS; do + macrofound=false + for dir in $macrodirs; do + if [ -f "$dir/$macro" ]; then + macrofound=true + break + fi + done + if $macrofound; then + : + else + printerr " $macro not found" + status=1 + fi + done + fi + if [ -n "$FORBIDDEN_M4MACROS" ]; then + printbold "Checking for forbidden M4 macros..." + # check that each macro file is in one of the macro dirs + for macro in $FORBIDDEN_M4MACROS; do + macrofound=false + for dir in $macrodirs; do + if [ -f "$dir/$macro" ]; then + macrofound=true + break + fi + done + if $macrofound; then + printerr " $macro found (should be cleared from macros dir)" + status=1 + fi + done + fi + if [ "$status" != 0 ]; then + printerr "***Error***: some autoconf macros required to build $PKG_NAME" + printerr " were not found in your aclocal path, or some forbidden" + printerr " macros were found. Perhaps you need to adjust your" + printerr " ACLOCAL_PATH?" + printerr + fi + return $status +} + +# try to catch the case where the macros2/ directory hasn't been cleared out. +forbid_m4macro gnome-cxx-check.m4 + +want_libtool=false +want_gettext=false +want_glib_gettext=false +want_intltool=false +want_pkg_config=false +want_gtk_doc=false + +configure_files="`find $srcdir -name configure.ac -print -or -name configure.in -print`" +for configure_ac in $configure_files; do + if grep "^A[CM]_PROG_LIBTOOL" $configure_ac >/dev/null; then + want_libtool=true + fi + if grep "^AM_GNU_GETTEXT" $configure_ac >/dev/null; then + want_gettext=true + fi + if grep "^AM_GLIB_GNU_GETTEXT" $configure_ac >/dev/null; then + want_glib_gettext=true + fi + if grep "^AC_PROG_INTLTOOL" $configure_ac >/dev/null; then + want_intltool=true + fi + if grep "^PKG_CHECK_MODULES" $configure_ac >/dev/null; then + want_pkg_config=true + fi + if grep "^GTK_DOC_CHECK" $configure_ac >/dev/null; then + want_gtk_doc=true + fi +done + +DIE=0 + +#tell Mandrake autoconf wrapper we want autoconf 2.5x, not 2.13 +WANT_AUTOCONF_2_5=1 +export WANT_AUTOCONF_2_5 +version_check autoconf AUTOCONF 'autoconf2.50 autoconf autoconf-2.53' $REQUIRED_AUTOCONF_VERSION \ + "http://ftp.gnu.org/pub/gnu/autoconf/autoconf-$REQUIRED_AUTOCONF_VERSION.tar.gz" || DIE=1 +AUTOHEADER=`echo $AUTOCONF | sed s/autoconf/autoheader/` + +case $REQUIRED_AUTOMAKE_VERSION in + 1.4*) automake_progs="automake-1.4" ;; + 1.5*) automake_progs="automake-1.7 automake-1.6 automake-1.5" ;; + 1.6*) automake_progs="automake-1.7 automake-1.6" ;; + 1.7*) automake_progs="automake-1.7" ;; +esac +version_check automake AUTOMAKE "$automake_progs" $REQUIRED_AUTOMAKE_VERSION \ + "http://ftp.gnu.org/pub/gnu/automake/automake-$REQUIRED_AUTOMAKE_VERSION.tar.gz" || DIE=1 +ACLOCAL=`echo $AUTOMAKE | sed s/automake/aclocal/` + +if $want_libtool; then + version_check libtool LIBTOOLIZE libtoolize $REQUIRED_LIBTOOL_VERSION \ + "http://ftp.gnu.org/pub/gnu/libtool/libtool-$REQUIRED_LIBTOOL_VERSION.tar.gz" || DIE=1 + require_m4macro libtool.m4 +fi + +if $want_gettext; then + version_check gettext GETTEXTIZE gettextize $REQUIRED_GETTEXT_VERSION \ + "http://ftp.gnu.org/pub/gnu/gettext/gettext-$REQUIRED_GETTEXT_VERSION.tar.gz" || DIE=1 + require_m4macro gettext.m4 +fi + +if $want_glib_gettextize; then + version_check glib-gettext GLIB_GETTEXTIZE glib-gettextize $REQUIRED_GLIB_GETTEXT_VERSION \ + "ftp://ftp.gtk.org/pub/gtk/v2.2/glib-$REQUIRED_GLIB_GETTEXT_VERSION.tar.gz" || DIE=1 + require_m4macro glib-gettext.m4 +fi + +if $want_intltool; then + version_check intltool INTLTOOLIZE intltoolize $REQUIRED_INTLTOOL_VERSION \ + "http://ftp.gnome.org/pub/GNOME/sources/intltool/" || DIE=1 + require_m4macro intltool.m4 +fi + +if $want_pkg_config; then + version_check pkg-config PKG_CONFIG pkg-config $REQUIRED_PKG_CONFIG_VERSION \ + "'http://www.freedesktop.org/software/pkgconfig/releases/pkgconfig-$REQUIRED_PKG_CONFIG_VERSION.tar.gz" || DIE=1 + require_m4macro pkg.m4 +fi + +if $want_gtk_doc; then + version_check gtk-doc GTKDOCIZE gtkdocize $REQUIRED_GTK_DOC_VERSION \ + "http://ftp.gnome.org/pub/GNOME/sources/gtk-doc/" || DIE=1 + require_m4macro gtk-doc.m4 +fi + +check_m4macros || DIE=1 + +if [ "$DIE" -eq 1 ]; then + exit 1 +fi + +if test -z "$*"; then + printerr "**Warning**: I am going to run \`configure' with no arguments." + printerr "If you wish to pass any to it, please specify them on the" + printerr \`$0\'" command line." + printerr +fi + +topdir=`pwd` +for configure_ac in $configure_files; do + dirname=`dirname $configure_ac` + basename=`basename $configure_ac` + if test -f $dirname/NO-AUTO-GEN; then + echo skipping $dirname -- flagged as no auto-gen + else + printbold "Processing $configure_ac" + + aclocalinclude="$ACLOCAL_FLAGS" + printbold "Running $ACLOCAL..." + $ACLOCAL $aclocalinclude || exit 1 + + if grep "GNOME_AUTOGEN_OBSOLETE" aclocal.m4 >/dev/null; then + printerr "*** obsolete gnome macros were used in $configure_ac" + fi + + if grep "^A[CM]_PROG_LIBTOOL" $basename >/dev/null; then + printbold "Running $LIBTOOLIZE..." + $LIBTOOLIZE --force || exit 1 + fi + if grep "^AM_GLIB_GNU_GETTEXT" $basename >/dev/null; then + printbold "Running $GLIB_GETTEXTIZE... Ignore non-fatal messages." + echo "no" | $GLIB_GETTEXTIZE --force --copy || exit 1 + elif grep "^AM_GNU_GETTEXT" $basename >/dev/null; then + if grep "^AM_GNU_GETTEXT_VERSION" $basename > /dev/null; then + printbold "Running autopoint..." + autopoint --force || exit 1 + else + printbold "Running $GETTEXTIZE... Ignore non-fatal messages." + echo "no" | $GETTEXTIZE --force --copy || exit 1 + fi + fi + if grep "^AC_PROG_INTLTOOL" $basename >/dev/null; then + printbold "Running $INTLTOOLIZE..." + $INTLTOOLIZE --force --automake || exit 1 + fi + if grep "^GTK_DOC_CHECK" $basename >/dev/null; then + printbold "Running $GTKDOCIZE..." + $GTKDOCIZE || exit 1 + fi + if grep "^A[CM]_CONFIG_HEADER" $basename >/dev/null; then + printbold "Running $AUTOHEADER..." + $AUTOHEADER || exit 1 + fi + + printbold "Running $AUTOMAKE..." + $AUTOMAKE --gnu --add-missing || exit 1 + + printbold "Running $AUTOCONF..." + $AUTOCONF || exit 1 + + cd $topdir + fi +done + +conf_flags="--enable-maintainer-mode --enable-compile-warnings" + +if test x$NOCONFIGURE = x; then + printbold Running $srcdir/configure $conf_flags "$@" ... + $srcdir/configure $conf_flags "$@" \ + && echo Now type \`make\' to compile $PKG_NAME || exit 1 +else + echo Skipping configure process. +fi diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..4adf55f --- /dev/null +++ b/configure.in @@ -0,0 +1,62 @@ +dnl Initial blurb +AC_PREREQ(2.52) +AC_INIT(sound-juicer, 0.1, http://www.burtonini.com/) +AC_CONFIG_SRCDIR(src/sj-gstreamer.c) +AM_INIT_AUTOMAKE(AC_PACKAGE_NAME, AC_PACKAGE_VERSION) +AM_CONFIG_HEADER(config.h) + +# Honor aclocal flags +ACLOCAL="$ACLOCAL $ACLOCAL_FLAGS" + +dnl Do the gettext/i18n stuff +GETTEXT_PACKAGE=sound-juicer +AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [The name of the gettext package.]) +AC_SUBST(GETTEXT_PACKAGE) + +AM_MAINTAINER_MODE + +AC_ISC_POSIX +AC_PROG_CC +AM_PROG_CC_STDC +AC_HEADER_STDC +AC_PROG_INTLTOOL([0.20]) + +PKG_CHECK_MODULES(GLIB, glib-2.0) +AC_SUBST(GLIB_CFLAGS) +AC_SUBST(GLIB_LIBS) + +PKG_CHECK_MODULES(LIBGLADE, libglade-2.0) +AC_SUBST(LIBGLADE_CFLAGS) +AC_SUBST(LIBGLADE_LIBS) + +PKG_CHECK_MODULES(GCONF, gconf-2.0) +AC_SUBST(GCONF_CFLAGS) +AC_SUBST(GCONF_LIBS) + +PKG_CHECK_MODULES(GNOME, libgnomeui-2.0) +AC_SUBST(GNOME_CFLAGS) +AC_SUBST(GNOME_LIBS) + +PKG_CHECK_MODULES(GSTREAMER, gstreamer-0.6) +AC_SUBST(GSTREAMER_CFLAGS) +AC_SUBST(GSTREAMER_LIBS) + +PKG_CHECK_MODULES(MUSICBRAINZ, libmusicbrainz >= 2.0.0) +AC_SUBST(MUSICBRAINZ_CFLAGS) +AC_SUBST(MUSICBRAINZ_LIBS) + +dnl Find how and where to put the GConf schemas +AC_PATH_PROG(GCONFTOOL, gconftool-2, no) +if test x"$GCONFTOOL" = xno; then + AC_MSG_ERROR([gconftool-2 executable not found in your path - should be installed with GConf]) +fi +AM_GCONF_SOURCE_2 + +ALL_LINGUAS="" +AM_GLIB_GNU_GETTEXT + +AC_OUTPUT([ +Makefile +po/Makefile.in +tests/Makefile +]) diff --git a/data/grip-48.png b/data/grip-48.png Binary files differnew file mode 100644 index 0000000..a184924 --- /dev/null +++ b/data/grip-48.png diff --git a/data/logo.xcf b/data/logo.xcf Binary files differnew file mode 100644 index 0000000..bb43ab4 --- /dev/null +++ b/data/logo.xcf diff --git a/data/sound-juicer.glade b/data/sound-juicer.glade new file mode 100644 index 0000000..ce5f59f --- /dev/null +++ b/data/sound-juicer.glade @@ -0,0 +1,1176 @@ +<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> +<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd"> + +<glade-interface> + +<widget class="GtkWindow" id="main_window"> + <property name="width_request">350</property> + <property name="height_request">420</property> + <property name="title" translatable="yes">Sound Juicer</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <signal name="destroy" handler="on_quit_activate" last_modification_time="Fri, 28 Mar 2003 09:09:29 GMT"/> + <signal name="destroy_event" handler="on_destory_event" last_modification_time="Fri, 28 Mar 2003 09:10:18 GMT"/> + + <child> + <widget class="GtkVBox" id="vbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="GtkMenuBar" id="menubar1"> + <property name="visible">True</property> + + <child> + <widget class="GtkMenuItem" id="menuitem1"> + <property name="visible">True</property> + <property name="label" translatable="yes">_File</property> + <property name="use_underline">True</property> + + <child> + <widget class="GtkMenu" id="menuitem1_menu"> + + <child> + <widget class="GtkImageMenuItem" id="extract"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Extract</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_extract_activate" last_modification_time="Tue, 25 Mar 2003 07:45:51 GMT"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image21"> + <property name="visible">True</property> + <property name="stock">gtk-cdrom</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="re-read"> + <property name="visible">True</property> + <property name="label" translatable="yes">Re-read</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_reread_activate" last_modification_time="Tue, 25 Mar 2003 07:45:51 GMT"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image22"> + <property name="visible">True</property> + <property name="stock">gtk-refresh</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="separatormenuitem1"> + <property name="visible">True</property> + </widget> + </child> + + <child> + <widget class="GtkImageMenuItem" id="quit"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Quit</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_quit_activate" last_modification_time="Tue, 25 Mar 2003 18:52:39 GMT"/> + <accelerator key="Q" modifiers="GDK_CONTROL_MASK" signal="activate"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image23"> + <property name="visible">True</property> + <property name="stock">gtk-quit</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="menuitem2"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Edit</property> + <property name="use_underline">True</property> + + <child> + <widget class="GtkMenu" id="menuitem2_menu"> + + <child> + <widget class="GtkImageMenuItem" id="edit_preferences"> + <property name="visible">True</property> + <property name="label" translatable="yes">Prefere_nces</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_edit_preferences_cb" last_modification_time="Tue, 25 Mar 2003 08:37:30 GMT"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image24"> + <property name="visible">True</property> + <property name="stock">gtk-preferences</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + </child> + + <child> + <widget class="GtkMenuItem" id="menuitem4"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Help</property> + <property name="use_underline">True</property> + + <child> + <widget class="GtkMenu" id="menuitem4_menu"> + + <child> + <widget class="GtkImageMenuItem" id="about"> + <property name="visible">True</property> + <property name="label" translatable="yes">_About</property> + <property name="use_underline">True</property> + <signal name="activate" handler="on_about_activate" last_modification_time="Thu, 20 Mar 2003 18:36:52 GMT"/> + + <child internal-child="image"> + <widget class="GtkImage" id="image25"> + <property name="visible">True</property> + <property name="stock">gnome-stock-about</property> + <property name="icon_size">1</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox2"> + <property name="border_width">8</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">8</property> + + <child> + <widget class="GtkFrame" id="frame3"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="label_yalign">0.5</property> + <property name="shadow_type">GTK_SHADOW_NONE</property> + + <child> + <widget class="GtkTable" id="table1"> + <property name="border_width">8</property> + <property name="visible">True</property> + <property name="n_rows">3</property> + <property name="n_columns">2</property> + <property name="homogeneous">False</property> + <property name="row_spacing">4</property> + <property name="column_spacing">8</property> + + <child> + <widget class="GtkLabel" id="label1"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Title:</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label2"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Artist:</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label3"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Duration:</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="left_attach">0</property> + <property name="right_attach">1</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="duration_label"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">label</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">True</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">2</property> + <property name="bottom_attach">3</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="artist_label"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">label</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">True</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">1</property> + <property name="bottom_attach">2</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="title_label"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">label</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">True</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="left_attach">1</property> + <property name="right_attach">2</property> + <property name="top_attach">0</property> + <property name="bottom_attach">1</property> + <property name="x_options">fill</property> + <property name="y_options"></property> + </packing> + </child> + </widget> + </child> + + <child> + <widget class="GtkLabel" id="label9"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>CD Info</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow1"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTreeView" id="track_listview"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="headers_visible">True</property> + <property name="rules_hint">True</property> + <property name="reorderable">False</property> + <property name="enable_search">True</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkHButtonBox" id="hbuttonbox1"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + <property name="spacing">8</property> + + <child> + <widget class="GtkButton" id="reread_button"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-refresh</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <signal name="clicked" handler="on_reread_activate" last_modification_time="Thu, 27 Mar 2003 09:28:44 GMT"/> + </widget> + </child> + + <child> + <widget class="GtkButton" id="extract_button"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <signal name="clicked" handler="on_extract_activate" last_modification_time="Tue, 25 Mar 2003 19:54:03 GMT"/> + + <child> + <widget class="GtkAlignment" id="alignment1"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">0</property> + <property name="yscale">0</property> + + <child> + <widget class="GtkHBox" id="hbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">2</property> + + <child> + <widget class="GtkImage" id="image4"> + <property name="visible">True</property> + <property name="stock">gtk-cdrom</property> + <property name="icon_size">4</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label6"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Extract</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkStatusbar" id="statusbar1"> + <property name="visible">True</property> + <property name="has_resize_grip">True</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkDialog" id="prefs_dialog"> + <property name="title" translatable="yes">Preferences</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="has_separator">True</property> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox1"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area1"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="prefs_help"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-help</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="response_id">-11</property> + </widget> + </child> + + <child> + <widget class="GtkButton" id="prefs_close"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="has_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-close</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="response_id">-7</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox3"> + <property name="border_width">4</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">8</property> + + <child> + <widget class="GtkFrame" id="frame1"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="label_yalign">0.5</property> + <property name="shadow_type">GTK_SHADOW_NONE</property> + + <child> + <widget class="GtkVBox" id="vbox5"> + <property name="border_width">8</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child> + <widget class="Custom" id="cd_option"> + <property name="visible">True</property> + <property name="creation_function">bacon_cd_selection_new</property> + <property name="int1">0</property> + <property name="int2">0</property> + <property name="last_modification_time">Sat, 22 Mar 2003 16:23:05 GMT</property> + <signal name="device_changed" handler="prefs_cdrom_changed_cb" last_modification_time="Tue, 25 Mar 2003 19:53:07 GMT"/> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> + + <child> + <widget class="GtkLabel" id="label4"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>CD Drive</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkFrame" id="frame6"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="label_yalign">0.5</property> + <property name="shadow_type">GTK_SHADOW_NONE</property> + + <child> + <widget class="GtkHBox" id="hbox3"> + <property name="border_width">8</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">8</property> + + <child> + <widget class="GtkLabel" id="path_label"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="label" translatable="yes">label</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">True</property> + <property name="selectable">True</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkButton" id="prefs_browse"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <signal name="clicked" handler="prefs_browse_clicked" last_modification_time="Thu, 27 Mar 2003 08:48:05 GMT"/> + + <child> + <widget class="GtkAlignment" id="alignment3"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">0</property> + <property name="yscale">0</property> + + <child> + <widget class="GtkHBox" id="hbox4"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">2</property> + + <child> + <widget class="GtkImage" id="image26"> + <property name="visible">True</property> + <property name="stock">gtk-open</property> + <property name="icon_size">4</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label17"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Browse...</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + </widget> + </child> + + <child> + <widget class="GtkLabel" id="label15"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Output Path</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkFrame" id="frame7"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="label_yalign">0.5</property> + <property name="shadow_type">GTK_SHADOW_NONE</property> + + <child> + <placeholder/> + </child> + + <child> + <widget class="GtkLabel" id="label20"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Output Name</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkDialog" id="multiple_dialog"> + <property name="title" translatable="yes">Multiple Albums Found</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="has_separator">False</property> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox2"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area2"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="ok_button"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="has_default">True</property> + <property name="can_focus">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="response_id">-5</property> + + <child> + <widget class="GtkAlignment" id="alignment2"> + <property name="visible">True</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xscale">0</property> + <property name="yscale">0</property> + + <child> + <widget class="GtkHBox" id="hbox2"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">2</property> + + <child> + <widget class="GtkImage" id="image16"> + <property name="visible">True</property> + <property name="stock">gtk-go-forward</property> + <property name="icon_size">4</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkLabel" id="label11"> + <property name="visible">True</property> + <property name="label" translatable="yes">_Continue</property> + <property name="use_underline">True</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + </widget> + </child> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox4"> + <property name="border_width">8</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">8</property> + + <child> + <widget class="GtkLabel" id="label10"> + <property name="visible">True</property> + <property name="label" translatable="yes">This CD could be more than one album. Please select which album it is below and press <i>Continue</i>.</property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">True</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkScrolledWindow" id="scrolledwindow2"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property> + <property name="shadow_type">GTK_SHADOW_IN</property> + <property name="window_placement">GTK_CORNER_TOP_LEFT</property> + + <child> + <widget class="GtkTreeView" id="albums_listview"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="headers_visible">True</property> + <property name="rules_hint">False</property> + <property name="reorderable">False</property> + <property name="enable_search">True</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">True</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +<widget class="GtkDialog" id="progress_dialog"> + <property name="title" translatable="yes">Progress</property> + <property name="type">GTK_WINDOW_TOPLEVEL</property> + <property name="window_position">GTK_WIN_POS_NONE</property> + <property name="modal">False</property> + <property name="resizable">True</property> + <property name="destroy_with_parent">False</property> + <property name="has_separator">True</property> + + <child internal-child="vbox"> + <widget class="GtkVBox" id="dialog-vbox3"> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">0</property> + + <child internal-child="action_area"> + <widget class="GtkHButtonBox" id="dialog-action_area3"> + <property name="visible">True</property> + <property name="layout_style">GTK_BUTTONBOX_END</property> + + <child> + <widget class="GtkButton" id="okbutton2"> + <property name="visible">True</property> + <property name="can_default">True</property> + <property name="can_focus">True</property> + <property name="label">gtk-cancel</property> + <property name="use_stock">True</property> + <property name="relief">GTK_RELIEF_NORMAL</property> + <property name="response_id">-6</property> + </widget> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="pack_type">GTK_PACK_END</property> + </packing> + </child> + + <child> + <widget class="GtkVBox" id="vbox7"> + <property name="border_width">8</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">8</property> + + <child> + <widget class="GtkLabel" id="progress_label"> + <property name="visible">True</property> + <property name="label" translatable="yes">Currently ripping track %d (%d remaining)</property> + <property name="use_underline">False</property> + <property name="use_markup">False</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + + <child> + <widget class="GtkFrame" id="frame4"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="label_yalign">0.5</property> + <property name="shadow_type">GTK_SHADOW_NONE</property> + + <child> + <widget class="GtkVBox" id="vbox8"> + <property name="border_width">8</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">8</property> + + <child> + <widget class="GtkProgressBar" id="track_progress"> + <property name="visible">True</property> + <property name="orientation">GTK_PROGRESS_LEFT_TO_RIGHT</property> + <property name="fraction">0</property> + <property name="pulse_step">0.1</property> + <property name="text" translatable="yes"></property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + + <child> + <widget class="GtkLabel" id="label13"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Track Progress</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + + <child> + <widget class="GtkFrame" id="frame5"> + <property name="visible">True</property> + <property name="label_xalign">0</property> + <property name="label_yalign">0.5</property> + <property name="shadow_type">GTK_SHADOW_NONE</property> + + <child> + <widget class="GtkVBox" id="vbox9"> + <property name="border_width">8</property> + <property name="visible">True</property> + <property name="homogeneous">False</property> + <property name="spacing">8</property> + + <child> + <widget class="GtkProgressBar" id="disc_progress"> + <property name="visible">True</property> + <property name="orientation">GTK_PROGRESS_LEFT_TO_RIGHT</property> + <property name="fraction">0</property> + <property name="pulse_step">0.1</property> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">False</property> + </packing> + </child> + </widget> + </child> + + <child> + <widget class="GtkLabel" id="label14"> + <property name="visible">True</property> + <property name="label" translatable="yes"><b>Disc Progress</b></property> + <property name="use_underline">False</property> + <property name="use_markup">True</property> + <property name="justify">GTK_JUSTIFY_LEFT</property> + <property name="wrap">False</property> + <property name="selectable">False</property> + <property name="xalign">0.5</property> + <property name="yalign">0.5</property> + <property name="xpad">0</property> + <property name="ypad">0</property> + </widget> + <packing> + <property name="type">label_item</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + <packing> + <property name="padding">0</property> + <property name="expand">False</property> + <property name="fill">True</property> + </packing> + </child> + </widget> + </child> +</widget> + +</glade-interface> diff --git a/data/sound-juicer.gladep b/data/sound-juicer.gladep new file mode 100644 index 0000000..7012234 --- /dev/null +++ b/data/sound-juicer.gladep @@ -0,0 +1,7 @@ +<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*--> +<!DOCTYPE glade-project SYSTEM "http://glade.gnome.org/glade-project-2.0.dtd"> + +<glade-project> + <name></name> + <program_name></program_name> +</glade-project> diff --git a/po/Makefile b/po/Makefile new file mode 100644 index 0000000..a5eaf1d --- /dev/null +++ b/po/Makefile @@ -0,0 +1,256 @@ +# Makefile for program source directory in GNU NLS utilities package. +# Copyright (C) 1995, 1996, 1997 by Ulrich Drepper <drepper@gnu.ai.mit.edu> +# +# This file file be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. +# +# - Modified by Owen Taylor <otaylor@redhat.com> to use GETTEXT_PACKAGE +# instead of PACKAGE and to look for po2tbl in ./ not in intl/ +# +# - Modified by jacob berkman <jacob@ximian.com> to install +# Makefile.in.in and po2tbl.sed.in for use with glib-gettextize + +GETTEXT_PACKAGE = sound-juicer +PACKAGE = sound-juicer +VERSION = 0.1 + +SHELL = /bin/sh + + +srcdir = . +top_srcdir = .. +top_builddir = .. + + +prefix = /usr/local +exec_prefix = ${prefix} +datadir = ${prefix}/share +libdir = ${exec_prefix}/lib +localedir = $(libdir)/locale +gnulocaledir = $(datadir)/locale +gettextsrcdir = $(datadir)/glib-2.0/gettext/po +subdir = po + +INSTALL = /usr/bin/install -c +INSTALL_DATA = ${INSTALL} -m 644 +MKINSTALLDIRS = $(top_srcdir)/./mkinstalldirs + +CC = gcc +GENCAT = @GENCAT@ +GMSGFMT = /usr/bin/msgfmt +MSGFMT = /usr/bin/msgfmt +XGETTEXT = /usr/bin/xgettext +INTLTOOL_UPDATE = $(top_builddir)/intltool-update +INTLTOOL_EXTRACT = $(top_builddir)/intltool-extract +MSGMERGE = INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --dist +GENPOT = INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --pot + +DEFS = -DHAVE_CONFIG_H +CFLAGS = -g -O2 +CPPFLAGS = + +INCLUDES = -I.. -I$(top_srcdir)/intl + +COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) + +SOURCES = +POFILES = +GMOFILES = +DISTFILES = ChangeLog Makefile.in.in POTFILES.in $(GETTEXT_PACKAGE).pot \ +$(POFILES) $(GMOFILES) $(SOURCES) + +POTFILES = \ + ../data/sound-juicer.glade + +CATALOGS = +CATOBJEXT = .gmo +INSTOBJEXT = .mo + +.SUFFIXES: +.SUFFIXES: .c .o .po .pox .gmo .mo .msg .cat + +.c.o: + $(COMPILE) $< + +.po.pox: + $(MAKE) $(GETTEXT_PACKAGE).pot + $(MSGMERGE) $< $(srcdir)/$(GETTEXT_PACKAGE).pot -o $*.pox + +.po.mo: + $(MSGFMT) -o $@ $< + +.po.gmo: + file=$(srcdir)/`echo $* | sed 's,.*/,,'`.gmo \ + && rm -f $$file && $(GMSGFMT) -o $$file $< + +.po.cat: + sed -f ../intl/po2msg.sed < $< > $*.msg \ + && rm -f $@ && $(GENCAT) $@ $*.msg + + +all: all-yes + +all-yes: $(CATALOGS) +all-no: + +$(srcdir)/$(GETTEXT_PACKAGE).pot: $(POTFILES) + $(GENPOT) + +install: install-exec install-data +install-exec: +install-data: install-data-yes +install-data-no: all +install-data-yes: all + if test -r "$(MKINSTALLDIRS)"; then \ + $(MKINSTALLDIRS) $(DESTDIR)$(datadir); \ + else \ + $(SHELL) $(top_srcdir)/mkinstalldirs $(DESTDIR)$(datadir); \ + fi + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + case "$$cat" in \ + *.gmo) destdir=$(gnulocaledir);; \ + *) destdir=$(localedir);; \ + esac; \ + lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \ + dir=$(DESTDIR)$$destdir/$$lang/LC_MESSAGES; \ + if test -r "$(MKINSTALLDIRS)"; then \ + $(MKINSTALLDIRS) $$dir; \ + else \ + $(SHELL) $(top_srcdir)/mkinstalldirs $$dir; \ + fi; \ + if test -r $$cat; then \ + $(INSTALL_DATA) $$cat $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \ + echo "installing $$cat as $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT)"; \ + else \ + $(INSTALL_DATA) $(srcdir)/$$cat $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \ + echo "installing $(srcdir)/$$cat as" \ + "$$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT)"; \ + fi; \ + if test -r $$cat.m; then \ + $(INSTALL_DATA) $$cat.m $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \ + echo "installing $$cat.m as $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m"; \ + else \ + if test -r $(srcdir)/$$cat.m ; then \ + $(INSTALL_DATA) $(srcdir)/$$cat.m \ + $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \ + echo "installing $(srcdir)/$$cat as" \ + "$$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m"; \ + else \ + true; \ + fi; \ + fi; \ + done + if test "$(PACKAGE)" = "glib"; then \ + if test -r "$(MKINSTALLDIRS)"; then \ + $(MKINSTALLDIRS) $(DESTDIR)$(gettextsrcdir); \ + else \ + $(SHELL) $(top_srcdir)/mkinstalldirs $(DESTDIR)$(gettextsrcdir); \ + fi; \ + $(INSTALL_DATA) $(srcdir)/Makefile.in.in \ + $(DESTDIR)$(gettextsrcdir)/Makefile.in.in; \ + else \ + : ; \ + fi + +# Define this as empty until I found a useful application. +installcheck: + +uninstall: + catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \ + rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \ + rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \ + rm -f $(DESTDIR)$(gnulocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \ + rm -f $(DESTDIR)$(gnulocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \ + done + rm -f $(DESTDIR)$(gettextsrcdir)/po-Makefile.in.in + +check: all + +dvi info tags TAGS ID: + +mostlyclean: + rm -f core core.* *.pox $(GETTEXT_PACKAGE).po *.old.po cat-id-tbl.tmp + rm -fr *.o + +clean: mostlyclean + +distclean: clean + rm -f Makefile Makefile.in POTFILES *.mo *.msg *.cat *.cat.m + +maintainer-clean: distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + rm -f $(GMOFILES) + +distdir = ../$(GETTEXT_PACKAGE)-$(VERSION)/$(subdir) +dist distdir: update-po $(DISTFILES) + dists="$(DISTFILES)"; \ + for file in $$dists; do \ + ln $(srcdir)/$$file $(distdir) 2> /dev/null \ + || cp -p $(srcdir)/$$file $(distdir); \ + done + +update-po: Makefile + $(MAKE) $(GETTEXT_PACKAGE).pot + cd $(srcdir); \ + catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \ + cp $$lang.po $$lang.old.po; \ + echo "$$lang:"; \ + if $(MSGMERGE) $$lang; then \ + rm -f $$lang.old.po; \ + else \ + echo "msgmerge for $$cat failed!"; \ + rm -f $$lang.po; \ + mv $$lang.old.po $$lang.po; \ + fi; \ + done + +.po: Makefile + $(MAKE) $(PACKAGE).pot; + PATH=`pwd`/../src:$$PATH; \ + echo; printf "$*: "; \ + if $(MSGMERGE) $*; then \ + rm -f $*.old.po; \ + else \ + echo "msgmerge for * failed!"; \ + mv $*.old.po $*.po; \ + fi; \ + msgfmt --statistics $*.po; echo; + + +# POTFILES is created from POTFILES.in by stripping comments, empty lines +# and Intltool tags (enclosed in square brackets), and appending a full +# relative path to them +POTFILES: POTFILES.in + ( if test 'x$(srcdir)' != 'x.'; then \ + posrcprefix='$(top_srcdir)/'; \ + else \ + posrcprefix="../"; \ + fi; \ + rm -f $@-t $@ \ + && (sed -e '/^#/d' \ + -e "s/^\[.*\] +//" \ + -e '/^[ ]*$$/d' \ + -e "s@.*@ $$posrcprefix& \\\\@" < $(srcdir)/$@.in \ + | sed -e '$$s/\\$$//') > $@-t \ + && chmod a-w $@-t \ + && mv $@-t $@ ) + +Makefile: Makefile.in.in ../config.status POTFILES + cd .. \ + && CONFIG_FILES=$(subdir)/$@.in CONFIG_HEADERS= \ + $(SHELL) ./config.status + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/po/Makefile.in b/po/Makefile.in new file mode 100644 index 0000000..ba10c99 --- /dev/null +++ b/po/Makefile.in @@ -0,0 +1,255 @@ +# Makefile for program source directory in GNU NLS utilities package. +# Copyright (C) 1995, 1996, 1997 by Ulrich Drepper <drepper@gnu.ai.mit.edu> +# +# This file file be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. +# +# - Modified by Owen Taylor <otaylor@redhat.com> to use GETTEXT_PACKAGE +# instead of PACKAGE and to look for po2tbl in ./ not in intl/ +# +# - Modified by jacob berkman <jacob@ximian.com> to install +# Makefile.in.in and po2tbl.sed.in for use with glib-gettextize + +GETTEXT_PACKAGE = sound-juicer +PACKAGE = sound-juicer +VERSION = 0.1 + +SHELL = /bin/sh + + +srcdir = . +top_srcdir = .. +top_builddir = .. + + +prefix = /usr/local +exec_prefix = ${prefix} +datadir = ${prefix}/share +libdir = ${exec_prefix}/lib +localedir = $(libdir)/locale +gnulocaledir = $(datadir)/locale +gettextsrcdir = $(datadir)/glib-2.0/gettext/po +subdir = po + +INSTALL = /usr/bin/install -c +INSTALL_DATA = ${INSTALL} -m 644 +MKINSTALLDIRS = $(top_srcdir)/./mkinstalldirs + +CC = gcc +GENCAT = @GENCAT@ +GMSGFMT = /usr/bin/msgfmt +MSGFMT = /usr/bin/msgfmt +XGETTEXT = /usr/bin/xgettext +INTLTOOL_UPDATE = $(top_builddir)/intltool-update +INTLTOOL_EXTRACT = $(top_builddir)/intltool-extract +MSGMERGE = INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --dist +GENPOT = INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --pot + +DEFS = -DHAVE_CONFIG_H +CFLAGS = -g -O2 +CPPFLAGS = + +INCLUDES = -I.. -I$(top_srcdir)/intl + +COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) + +SOURCES = +POFILES = +GMOFILES = +DISTFILES = ChangeLog Makefile.in.in POTFILES.in $(GETTEXT_PACKAGE).pot \ +$(POFILES) $(GMOFILES) $(SOURCES) + +POTFILES = \ + +CATALOGS = +CATOBJEXT = .gmo +INSTOBJEXT = .mo + +.SUFFIXES: +.SUFFIXES: .c .o .po .pox .gmo .mo .msg .cat + +.c.o: + $(COMPILE) $< + +.po.pox: + $(MAKE) $(GETTEXT_PACKAGE).pot + $(MSGMERGE) $< $(srcdir)/$(GETTEXT_PACKAGE).pot -o $*.pox + +.po.mo: + $(MSGFMT) -o $@ $< + +.po.gmo: + file=$(srcdir)/`echo $* | sed 's,.*/,,'`.gmo \ + && rm -f $$file && $(GMSGFMT) -o $$file $< + +.po.cat: + sed -f ../intl/po2msg.sed < $< > $*.msg \ + && rm -f $@ && $(GENCAT) $@ $*.msg + + +all: all-yes + +all-yes: $(CATALOGS) +all-no: + +$(srcdir)/$(GETTEXT_PACKAGE).pot: $(POTFILES) + $(GENPOT) + +install: install-exec install-data +install-exec: +install-data: install-data-yes +install-data-no: all +install-data-yes: all + if test -r "$(MKINSTALLDIRS)"; then \ + $(MKINSTALLDIRS) $(DESTDIR)$(datadir); \ + else \ + $(SHELL) $(top_srcdir)/mkinstalldirs $(DESTDIR)$(datadir); \ + fi + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + case "$$cat" in \ + *.gmo) destdir=$(gnulocaledir);; \ + *) destdir=$(localedir);; \ + esac; \ + lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \ + dir=$(DESTDIR)$$destdir/$$lang/LC_MESSAGES; \ + if test -r "$(MKINSTALLDIRS)"; then \ + $(MKINSTALLDIRS) $$dir; \ + else \ + $(SHELL) $(top_srcdir)/mkinstalldirs $$dir; \ + fi; \ + if test -r $$cat; then \ + $(INSTALL_DATA) $$cat $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \ + echo "installing $$cat as $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT)"; \ + else \ + $(INSTALL_DATA) $(srcdir)/$$cat $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \ + echo "installing $(srcdir)/$$cat as" \ + "$$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT)"; \ + fi; \ + if test -r $$cat.m; then \ + $(INSTALL_DATA) $$cat.m $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \ + echo "installing $$cat.m as $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m"; \ + else \ + if test -r $(srcdir)/$$cat.m ; then \ + $(INSTALL_DATA) $(srcdir)/$$cat.m \ + $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \ + echo "installing $(srcdir)/$$cat as" \ + "$$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m"; \ + else \ + true; \ + fi; \ + fi; \ + done + if test "$(PACKAGE)" = "glib"; then \ + if test -r "$(MKINSTALLDIRS)"; then \ + $(MKINSTALLDIRS) $(DESTDIR)$(gettextsrcdir); \ + else \ + $(SHELL) $(top_srcdir)/mkinstalldirs $(DESTDIR)$(gettextsrcdir); \ + fi; \ + $(INSTALL_DATA) $(srcdir)/Makefile.in.in \ + $(DESTDIR)$(gettextsrcdir)/Makefile.in.in; \ + else \ + : ; \ + fi + +# Define this as empty until I found a useful application. +installcheck: + +uninstall: + catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \ + rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \ + rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \ + rm -f $(DESTDIR)$(gnulocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \ + rm -f $(DESTDIR)$(gnulocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \ + done + rm -f $(DESTDIR)$(gettextsrcdir)/po-Makefile.in.in + +check: all + +dvi info tags TAGS ID: + +mostlyclean: + rm -f core core.* *.pox $(GETTEXT_PACKAGE).po *.old.po cat-id-tbl.tmp + rm -fr *.o + +clean: mostlyclean + +distclean: clean + rm -f Makefile Makefile.in POTFILES *.mo *.msg *.cat *.cat.m + +maintainer-clean: distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + rm -f $(GMOFILES) + +distdir = ../$(GETTEXT_PACKAGE)-$(VERSION)/$(subdir) +dist distdir: update-po $(DISTFILES) + dists="$(DISTFILES)"; \ + for file in $$dists; do \ + ln $(srcdir)/$$file $(distdir) 2> /dev/null \ + || cp -p $(srcdir)/$$file $(distdir); \ + done + +update-po: Makefile + $(MAKE) $(GETTEXT_PACKAGE).pot + cd $(srcdir); \ + catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \ + cp $$lang.po $$lang.old.po; \ + echo "$$lang:"; \ + if $(MSGMERGE) $$lang; then \ + rm -f $$lang.old.po; \ + else \ + echo "msgmerge for $$cat failed!"; \ + rm -f $$lang.po; \ + mv $$lang.old.po $$lang.po; \ + fi; \ + done + +.po: Makefile + $(MAKE) $(PACKAGE).pot; + PATH=`pwd`/../src:$$PATH; \ + echo; printf "$*: "; \ + if $(MSGMERGE) $*; then \ + rm -f $*.old.po; \ + else \ + echo "msgmerge for * failed!"; \ + mv $*.old.po $*.po; \ + fi; \ + msgfmt --statistics $*.po; echo; + + +# POTFILES is created from POTFILES.in by stripping comments, empty lines +# and Intltool tags (enclosed in square brackets), and appending a full +# relative path to them +POTFILES: POTFILES.in + ( if test 'x$(srcdir)' != 'x.'; then \ + posrcprefix='$(top_srcdir)/'; \ + else \ + posrcprefix="../"; \ + fi; \ + rm -f $@-t $@ \ + && (sed -e '/^#/d' \ + -e "s/^\[.*\] +//" \ + -e '/^[ ]*$$/d' \ + -e "s@.*@ $$posrcprefix& \\\\@" < $(srcdir)/$@.in \ + | sed -e '$$s/\\$$//') > $@-t \ + && chmod a-w $@-t \ + && mv $@-t $@ ) + +Makefile: Makefile.in.in ../config.status POTFILES + cd .. \ + && CONFIG_FILES=$(subdir)/$@.in CONFIG_HEADERS= \ + $(SHELL) ./config.status + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/po/Makefile.in.in b/po/Makefile.in.in new file mode 100644 index 0000000..98a4ca9 --- /dev/null +++ b/po/Makefile.in.in @@ -0,0 +1,255 @@ +# Makefile for program source directory in GNU NLS utilities package. +# Copyright (C) 1995, 1996, 1997 by Ulrich Drepper <drepper@gnu.ai.mit.edu> +# +# This file file be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# Please note that the actual code is *not* freely available. +# +# - Modified by Owen Taylor <otaylor@redhat.com> to use GETTEXT_PACKAGE +# instead of PACKAGE and to look for po2tbl in ./ not in intl/ +# +# - Modified by jacob berkman <jacob@ximian.com> to install +# Makefile.in.in and po2tbl.sed.in for use with glib-gettextize + +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ + +SHELL = /bin/sh +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +top_builddir = .. +VPATH = @srcdir@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +datadir = @datadir@ +libdir = @libdir@ +localedir = $(libdir)/locale +gnulocaledir = $(datadir)/locale +gettextsrcdir = $(datadir)/glib-2.0/gettext/po +subdir = po + +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +MKINSTALLDIRS = $(top_srcdir)/@MKINSTALLDIRS@ + +CC = @CC@ +GENCAT = @GENCAT@ +GMSGFMT = @GMSGFMT@ +MSGFMT = @MSGFMT@ +XGETTEXT = @XGETTEXT@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +MSGMERGE = INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --dist +GENPOT = INTLTOOL_EXTRACT=$(INTLTOOL_EXTRACT) $(INTLTOOL_UPDATE) --gettext-package $(GETTEXT_PACKAGE) --pot + +DEFS = @DEFS@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ + +INCLUDES = -I.. -I$(top_srcdir)/intl + +COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) + +SOURCES = +POFILES = @POFILES@ +GMOFILES = @GMOFILES@ +DISTFILES = ChangeLog Makefile.in.in POTFILES.in $(GETTEXT_PACKAGE).pot \ +$(POFILES) $(GMOFILES) $(SOURCES) + +POTFILES = \ + +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +INSTOBJEXT = @INSTOBJEXT@ + +.SUFFIXES: +.SUFFIXES: .c .o .po .pox .gmo .mo .msg .cat + +.c.o: + $(COMPILE) $< + +.po.pox: + $(MAKE) $(GETTEXT_PACKAGE).pot + $(MSGMERGE) $< $(srcdir)/$(GETTEXT_PACKAGE).pot -o $*.pox + +.po.mo: + $(MSGFMT) -o $@ $< + +.po.gmo: + file=$(srcdir)/`echo $* | sed 's,.*/,,'`.gmo \ + && rm -f $$file && $(GMSGFMT) -o $$file $< + +.po.cat: + sed -f ../intl/po2msg.sed < $< > $*.msg \ + && rm -f $@ && $(GENCAT) $@ $*.msg + + +all: all-@USE_NLS@ + +all-yes: $(CATALOGS) +all-no: + +$(srcdir)/$(GETTEXT_PACKAGE).pot: $(POTFILES) + $(GENPOT) + +install: install-exec install-data +install-exec: +install-data: install-data-@USE_NLS@ +install-data-no: all +install-data-yes: all + if test -r "$(MKINSTALLDIRS)"; then \ + $(MKINSTALLDIRS) $(DESTDIR)$(datadir); \ + else \ + $(SHELL) $(top_srcdir)/mkinstalldirs $(DESTDIR)$(datadir); \ + fi + @catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + case "$$cat" in \ + *.gmo) destdir=$(gnulocaledir);; \ + *) destdir=$(localedir);; \ + esac; \ + lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \ + dir=$(DESTDIR)$$destdir/$$lang/LC_MESSAGES; \ + if test -r "$(MKINSTALLDIRS)"; then \ + $(MKINSTALLDIRS) $$dir; \ + else \ + $(SHELL) $(top_srcdir)/mkinstalldirs $$dir; \ + fi; \ + if test -r $$cat; then \ + $(INSTALL_DATA) $$cat $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \ + echo "installing $$cat as $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT)"; \ + else \ + $(INSTALL_DATA) $(srcdir)/$$cat $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \ + echo "installing $(srcdir)/$$cat as" \ + "$$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT)"; \ + fi; \ + if test -r $$cat.m; then \ + $(INSTALL_DATA) $$cat.m $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \ + echo "installing $$cat.m as $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m"; \ + else \ + if test -r $(srcdir)/$$cat.m ; then \ + $(INSTALL_DATA) $(srcdir)/$$cat.m \ + $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \ + echo "installing $(srcdir)/$$cat as" \ + "$$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m"; \ + else \ + true; \ + fi; \ + fi; \ + done + if test "$(PACKAGE)" = "glib"; then \ + if test -r "$(MKINSTALLDIRS)"; then \ + $(MKINSTALLDIRS) $(DESTDIR)$(gettextsrcdir); \ + else \ + $(SHELL) $(top_srcdir)/mkinstalldirs $(DESTDIR)$(gettextsrcdir); \ + fi; \ + $(INSTALL_DATA) $(srcdir)/Makefile.in.in \ + $(DESTDIR)$(gettextsrcdir)/Makefile.in.in; \ + else \ + : ; \ + fi + +# Define this as empty until I found a useful application. +installcheck: + +uninstall: + catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \ + rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \ + rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \ + rm -f $(DESTDIR)$(gnulocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \ + rm -f $(DESTDIR)$(gnulocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \ + done + rm -f $(DESTDIR)$(gettextsrcdir)/po-Makefile.in.in + +check: all + +dvi info tags TAGS ID: + +mostlyclean: + rm -f core core.* *.pox $(GETTEXT_PACKAGE).po *.old.po cat-id-tbl.tmp + rm -fr *.o + +clean: mostlyclean + +distclean: clean + rm -f Makefile Makefile.in POTFILES *.mo *.msg *.cat *.cat.m + +maintainer-clean: distclean + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + rm -f $(GMOFILES) + +distdir = ../$(GETTEXT_PACKAGE)-$(VERSION)/$(subdir) +dist distdir: update-po $(DISTFILES) + dists="$(DISTFILES)"; \ + for file in $$dists; do \ + ln $(srcdir)/$$file $(distdir) 2> /dev/null \ + || cp -p $(srcdir)/$$file $(distdir); \ + done + +update-po: Makefile + $(MAKE) $(GETTEXT_PACKAGE).pot + cd $(srcdir); \ + catalogs='$(CATALOGS)'; \ + for cat in $$catalogs; do \ + cat=`basename $$cat`; \ + lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \ + cp $$lang.po $$lang.old.po; \ + echo "$$lang:"; \ + if $(MSGMERGE) $$lang; then \ + rm -f $$lang.old.po; \ + else \ + echo "msgmerge for $$cat failed!"; \ + rm -f $$lang.po; \ + mv $$lang.old.po $$lang.po; \ + fi; \ + done + +.po: Makefile + $(MAKE) $(PACKAGE).pot; + PATH=`pwd`/../src:$$PATH; \ + echo; printf "$*: "; \ + if $(MSGMERGE) $*; then \ + rm -f $*.old.po; \ + else \ + echo "msgmerge for * failed!"; \ + mv $*.old.po $*.po; \ + fi; \ + msgfmt --statistics $*.po; echo; + + +# POTFILES is created from POTFILES.in by stripping comments, empty lines +# and Intltool tags (enclosed in square brackets), and appending a full +# relative path to them +POTFILES: POTFILES.in + ( if test 'x$(srcdir)' != 'x.'; then \ + posrcprefix='$(top_srcdir)/'; \ + else \ + posrcprefix="../"; \ + fi; \ + rm -f $@-t $@ \ + && (sed -e '/^#/d' \ + -e "s/^\[.*\] +//" \ + -e '/^[ ]*$$/d' \ + -e "s@.*@ $$posrcprefix& \\\\@" < $(srcdir)/$@.in \ + | sed -e '$$s/\\$$//') > $@-t \ + && chmod a-w $@-t \ + && mv $@-t $@ ) + +Makefile: Makefile.in.in ../config.status POTFILES + cd .. \ + && CONFIG_FILES=$(subdir)/$@.in CONFIG_HEADERS= \ + $(SHELL) ./config.status + +# Tell versions [3.59,3.63) of GNU make not to export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/po/POTFILES b/po/POTFILES new file mode 100644 index 0000000..c8d3bf5 --- /dev/null +++ b/po/POTFILES @@ -0,0 +1 @@ + ../data/sound-juicer.glade diff --git a/po/POTFILES.in b/po/POTFILES.in new file mode 100644 index 0000000..93df9ed --- /dev/null +++ b/po/POTFILES.in @@ -0,0 +1 @@ +data/sound-juicer.glade diff --git a/po/sound-juicer.pot b/po/sound-juicer.pot new file mode 100644 index 0000000..3e7afc9 --- /dev/null +++ b/po/sound-juicer.pot @@ -0,0 +1,94 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2003-03-25 13:06+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: data/sound-juicer.glade.h:1 +msgid "<b>Artist:</b>" +msgstr "" + +#: data/sound-juicer.glade.h:2 +msgid "<b>CD Drive</b>" +msgstr "" + +#: data/sound-juicer.glade.h:3 +msgid "<b>CD Info</b>" +msgstr "" + +#: data/sound-juicer.glade.h:4 +msgid "<b>Duration:</b>" +msgstr "" + +#: data/sound-juicer.glade.h:5 +msgid "<b>Output Path</b>" +msgstr "" + +#: data/sound-juicer.glade.h:6 +msgid "<b>Title:</b>" +msgstr "" + +#: data/sound-juicer.glade.h:7 +msgid "Multiple Albums Found" +msgstr "" + +#: data/sound-juicer.glade.h:8 +msgid "Prefere_nces" +msgstr "" + +#: data/sound-juicer.glade.h:9 +msgid "Preferences" +msgstr "" + +#: data/sound-juicer.glade.h:10 +msgid "Re-read" +msgstr "" + +#: data/sound-juicer.glade.h:11 +msgid "Sound Juicer" +msgstr "" + +#: data/sound-juicer.glade.h:12 +msgid "" +"This CD could be more than one album. Please select which album it is below " +"and press OK." +msgstr "" + +#: data/sound-juicer.glade.h:13 +msgid "_About" +msgstr "" + +#: data/sound-juicer.glade.h:14 +msgid "_Edit" +msgstr "" + +#: data/sound-juicer.glade.h:15 +msgid "_Extract" +msgstr "" + +#: data/sound-juicer.glade.h:16 +msgid "_File" +msgstr "" + +#: data/sound-juicer.glade.h:17 +msgid "_Help" +msgstr "" + +#: data/sound-juicer.glade.h:18 +msgid "_Quit" +msgstr "" + +#: data/sound-juicer.glade.h:19 +msgid "label" +msgstr "" diff --git a/src/bacon-cd-selection.c b/src/bacon-cd-selection.c new file mode 100644 index 0000000..57e1b8d --- /dev/null +++ b/src/bacon-cd-selection.c @@ -0,0 +1,439 @@ +/* + * Copyright (C) 2002 Bastien Nocera <hadess@hadess.net> + * + * bacon-cd-selection.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Authors: Bastien Nocera <hadess@hadess.net> + */ + +#include <config.h> + +#include <string.h> +#include <gnome.h> + +#include "bacon-cd-selection.h" +#include "cd-drive.h" + +/* Signals */ +enum { + DEVICE_CHANGED, + LAST_SIGNAL +}; + +/* Arguments */ +enum { + PROP_0, + PROP_DEVICE, +}; + +struct BaconCdSelectionPrivate { + gboolean is_entry; + GtkWidget *widget; + GList *cdroms; +}; + + +static void bacon_cd_selection_class_init (BaconCdSelectionClass *klass); +static void bacon_cd_selection_instance_init (BaconCdSelection *bcs); + +static void bacon_cd_selection_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec); +static void bacon_cd_selection_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec); + +static void bacon_cd_selection_realize (GtkWidget *widget); +static void bacon_cd_selection_unrealize (GtkWidget *widget); +static void bacon_cd_selection_finalize (GObject *object); + +static GtkWidgetClass *parent_class = NULL; + +static int bcs_table_signals[LAST_SIGNAL] = { 0 }; + +static CDDrive * +get_drive (BaconCdSelection *bcs, int nr) +{ + GList *item; + + item = g_list_nth (bcs->priv->cdroms, nr); + if (item == NULL) + return NULL; + else + return item->data; +} + + +GtkType +bacon_cd_selection_get_type (void) +{ + static GtkType bacon_cd_selection_type = 0; + + if (!bacon_cd_selection_type) { + static const GTypeInfo bacon_cd_selection_info = { + sizeof (BaconCdSelectionClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) bacon_cd_selection_class_init, + (GClassFinalizeFunc) NULL, + NULL /* class_data */, + sizeof (BaconCdSelection), + 0 /* n_preallocs */, + (GInstanceInitFunc) bacon_cd_selection_instance_init, + }; + + bacon_cd_selection_type = g_type_register_static + (GTK_TYPE_VBOX, + "BaconCdSelection", &bacon_cd_selection_info, + (GTypeFlags)0); + } + + return bacon_cd_selection_type; +} + +static void +bacon_cd_selection_class_init (BaconCdSelectionClass *klass) +{ + GObjectClass *object_class; + GtkWidgetClass *widget_class; + + object_class = (GObjectClass *) klass; + widget_class = (GtkWidgetClass *) klass; + + parent_class = gtk_type_class (gtk_vbox_get_type ()); + + /* GtkWidget */ + widget_class->realize = bacon_cd_selection_realize; + widget_class->unrealize = bacon_cd_selection_unrealize; + + /* GObject */ + object_class->set_property = bacon_cd_selection_set_property; + object_class->get_property = bacon_cd_selection_get_property; + object_class->finalize = bacon_cd_selection_finalize; + + /* Properties */ + g_object_class_install_property (object_class, PROP_DEVICE, + g_param_spec_string ("device", NULL, NULL, + FALSE, G_PARAM_READWRITE)); + + /* Signals */ + bcs_table_signals[DEVICE_CHANGED] = + g_signal_new ("device-changed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (BaconCdSelectionClass, + device_changed), + NULL, NULL, + g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); +} + +static void +bacon_cd_selection_instance_init (BaconCdSelection *bcs) +{ + bcs->priv = g_new0 (BaconCdSelectionPrivate, 1); + +#ifdef __linux__ + bcs->priv->is_entry = FALSE; +#else + bcs->priv->is_entry = TRUE; +#endif + + bcs->priv->cdroms = NULL; +} + +static void +bacon_cd_selection_realize (GtkWidget *widget) +{ + if (GTK_WIDGET_CLASS (parent_class)->realize != NULL) { + (* GTK_WIDGET_CLASS (parent_class)->realize) (widget); + } +} + +static void +bacon_cd_selection_unrealize (GtkWidget *widget) +{ + if (GTK_WIDGET_CLASS (parent_class)->unrealize != NULL) { + (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); + } +} + +static void +bacon_cd_selection_finalize (GObject *object) +{ + GList *l; + + BaconCdSelection *bcs = (BaconCdSelection *) object; + G_OBJECT_CLASS (parent_class)->finalize (object); + + gtk_widget_destroy (bcs->priv->widget); + + l = bcs->priv->cdroms; + while (l != NULL) + { + CDDrive *cdrom = l->data; + + cd_drive_free (cdrom); + l = g_list_remove (l, cdrom); + g_free (cdrom); + } + + bcs->priv = NULL; + bcs = NULL; +} + +static void +option_menu_device_changed (GtkOptionMenu *option_menu, gpointer user_data) +{ + BaconCdSelection *bcs = (BaconCdSelection *) user_data; + CDDrive *drive; + int i; + + i = gtk_option_menu_get_history (GTK_OPTION_MENU (option_menu)); + drive = get_drive (bcs, i); + + g_signal_emit (G_OBJECT (bcs), + bcs_table_signals[DEVICE_CHANGED], + 0, drive->device); +} + +static GtkWidget * +cdrom_option_menu (BaconCdSelection *bcs) +{ + GList *l; + GtkWidget *option_menu, *menu, *item; + CDDrive *cdrom; + + bcs->priv->cdroms = scan_for_cdroms (FALSE, FALSE); + + menu = gtk_menu_new(); + gtk_widget_show(menu); + + option_menu = gtk_option_menu_new (); + + for (l = bcs->priv->cdroms; l != NULL; l = l->next) + { + cdrom = l->data; + + if (cdrom->display_name == NULL) + g_warning ("cdrom->display_name != NULL failed"); + item = gtk_menu_item_new_with_label (cdrom->display_name + ? cdrom->display_name : _("Unnamed CDROM")); + gtk_widget_show (item); + gtk_menu_shell_append (GTK_MENU_SHELL (menu), item); + } + gtk_option_menu_set_history (GTK_OPTION_MENU (option_menu), 0); + + gtk_option_menu_set_menu (GTK_OPTION_MENU (option_menu), menu); + + if (bcs->priv->cdroms == NULL) + gtk_widget_set_sensitive (option_menu, FALSE); + + return option_menu; +} + +static void +on_combo_entry_changed (GnomeFileEntry *entry, gpointer user_data) +{ + BaconCdSelection *bcs = (BaconCdSelection *) user_data; + const char *str; + GtkWidget *widget; + + widget = gnome_file_entry_gtk_entry (entry); + str = gtk_entry_get_text (GTK_ENTRY (widget)); + + g_signal_emit (G_OBJECT (bcs), + bcs_table_signals[DEVICE_CHANGED], + 0, str); +} + +GtkWidget * +bacon_cd_selection_new (void) +{ + GtkWidget *widget; + BaconCdSelection *bcs; + + widget = GTK_WIDGET + (g_object_new (bacon_cd_selection_get_type (), NULL)); + bcs = BACON_CD_SELECTION (widget); + + if (bcs->priv->is_entry) + { + bcs->priv->widget = gnome_file_entry_new (NULL, + _("Select the drive")); + g_signal_connect (G_OBJECT (bcs->priv->widget), "changed", + G_CALLBACK (on_combo_entry_changed), bcs); + + gtk_box_pack_start (GTK_BOX (widget), + bcs->priv->widget, + TRUE, /* expand */ + TRUE, /* fill */ + 0); /* padding */ + } else { + bcs->priv->widget = cdrom_option_menu (bcs); + + g_signal_connect (bcs->priv->widget, "changed", + (GCallback)option_menu_device_changed, bcs); + + gtk_box_pack_start (GTK_BOX (widget), + bcs->priv->widget, + TRUE, /* expand */ + TRUE, /* fill */ + 0); /* padding */ + } + + gtk_widget_show_all (bcs->priv->widget); + + return widget; +} + +/* Properties */ +static void +bacon_cd_selection_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + BaconCdSelection *bcs; + + g_return_if_fail (BACON_IS_CD_SELECTION (object)); + + bcs = BACON_CD_SELECTION (object); + + switch (property_id) + { + case PROP_DEVICE: + bacon_cd_selection_set_device (bcs, g_value_get_string (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +bacon_cd_selection_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + BaconCdSelection *bcs; + + g_return_if_fail (BACON_IS_CD_SELECTION (object)); + + bcs = BACON_CD_SELECTION (object); + + switch (property_id) + { + case PROP_DEVICE: + g_value_set_string (value, bacon_cd_selection_get_device (bcs)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +const char * +bacon_cd_selection_get_default_device (BaconCdSelection *bcs) +{ + GList *l; + CDDrive *drive; + + l = bcs->priv->cdroms; + if (bcs->priv->cdroms == NULL) + /* TODO: not sure about this. if this is NULL, there are no devices present, so return NULL? */ + return "/dev/cdrom"; + + drive = l->data; + + return drive->device; +} + +void +bacon_cd_selection_set_device (BaconCdSelection *bcs, const char *device) +{ + GtkWidget *entry; + GList *l; + CDDrive *drive; + gboolean found; + int i; + + g_return_if_fail (bcs != NULL); + g_return_if_fail (BACON_IS_CD_SELECTION (bcs)); + + if (bcs->priv->is_entry == TRUE) + { + entry = gnome_file_entry_gtk_entry + (GNOME_FILE_ENTRY (bcs->priv->widget)); + gtk_entry_set_text (GTK_ENTRY (entry), device); + } else { + i = -1; + found = FALSE; + + for (l = bcs->priv->cdroms; l != NULL && found == FALSE; + l = l->next) + { + i++; + + drive = l->data; + + if (strcmp (drive->device, device) == 0) + found = TRUE; + } + + if (found) + { + gtk_option_menu_set_history (GTK_OPTION_MENU + (bcs->priv->widget), i); + } else { + /* If the device doesn't exist, set it back to + * the default */ + gtk_option_menu_set_history (GTK_OPTION_MENU + (bcs->priv->widget), 0); + + drive = get_drive (bcs, 0); + + if (drive == NULL) + return; + + g_signal_emit (G_OBJECT (bcs), + bcs_table_signals [DEVICE_CHANGED], + 0, drive->device); + } + + } +} + +const char * +bacon_cd_selection_get_device (BaconCdSelection *bcs) +{ + GtkWidget *entry; + CDDrive *drive; + int i; + + g_return_val_if_fail (bcs != NULL, NULL); + g_return_val_if_fail (BACON_IS_CD_SELECTION (bcs), NULL); + + if (bcs->priv->is_entry == TRUE) + { + entry = gnome_file_entry_gtk_entry + (GNOME_FILE_ENTRY (bcs->priv->widget)); + return gtk_entry_get_text (GTK_ENTRY (entry)); + } else { + i = gtk_option_menu_get_history (GTK_OPTION_MENU + (bcs->priv->widget)); + drive = get_drive (bcs, i); + + return drive ? drive->device : NULL; + } + + return NULL; +} + diff --git a/src/bacon-cd-selection.h b/src/bacon-cd-selection.h new file mode 100644 index 0000000..ea07294 --- /dev/null +++ b/src/bacon-cd-selection.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2002 Bastien Nocera <hadess@hadess.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 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Authors: Bastien Nocera <hadess@hadess.net> + */ + +#ifndef HAVE_BACON_CD_SELECTION_H +#define HAVE_BACON_CD_SELECTION_H + +#include <gtk/gtkwidget.h> + +G_BEGIN_DECLS + +#define BACON_CD_SELECTION(obj) (GTK_CHECK_CAST ((obj), bacon_cd_selection_get_type (), BaconCdSelection)) +#define BACON_CD_SELECTION_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), bacon_cd_selection_get_type (), BaconCdSelectionClass)) +#define BACON_IS_CD_SELECTION(obj) (GTK_CHECK_TYPE (obj, bacon_cd_selection_get_type ())) +#define BACON_IS_CD_SELECTION_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), bacon_cd_selection_get_type ())) + +typedef struct BaconCdSelectionPrivate BaconCdSelectionPrivate; + +typedef struct { + GtkVBox widget; + BaconCdSelectionPrivate *priv; +} BaconCdSelection; + +typedef struct { + GtkVBoxClass parent_class; + void (*device_changed) (GtkWidget *gtx, const char *title); +} BaconCdSelectionClass; + +GtkType bacon_cd_selection_get_type (void); +GtkWidget *bacon_cd_selection_new (void); + +void bacon_cd_selection_set_device (BaconCdSelection *tcs, + const char *device); +const char *bacon_cd_selection_get_device (BaconCdSelection *tcs); +const char *bacon_cd_selection_get_default_device (BaconCdSelection *tcs); + +G_END_DECLS + +#endif /* HAVE_BACON_CD_SELECTION_H */ diff --git a/src/cd-drive.c b/src/cd-drive.c new file mode 100644 index 0000000..e5c45f1 --- /dev/null +++ b/src/cd-drive.c @@ -0,0 +1,593 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- + + cd-drive.c: easy to use cd burner software + + Copyright (C) 2002 Red Hat, Inc. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Authors: Alexander Larsson <alexl@redhat.com> + Bastien Nocera <hadess@hadess.net> +*/ + +#include "config.h" + +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <math.h> + +#ifdef __linux__ +#include <scsi/scsi.h> +#include <scsi/sg.h> +#endif /* __linux__ */ + +#include <glib.h> +#include <libgnome/gnome-i18n.h> + +#include "cd-drive.h" + +#ifdef __linux__ + +#ifdef USE_STABLE_LIBGLIB +static gboolean +g_str_has_prefix (gchar *haystack, gchar *needle) +{ + if (haystack == NULL && needle == NULL) { + return TRUE; + } + + if (haystack == NULL || needle == NULL) { + return FALSE; + } + + if (strncmp (haystack, needle, strlen (needle)) == 0) { + return TRUE; + } + + return FALSE; +} +#endif /* USE_STABLE_LIBGLIB */ + +static char ** +read_lines (char *filename) +{ + char *contents; + gsize len; + char *p, *n; + GPtrArray *array; + + if (g_file_get_contents (filename, + &contents, + &len, NULL)) { + + array = g_ptr_array_new (); + + p = contents; + while ((n = memchr (p, '\n', len - (p - contents))) != NULL) { + *n = 0; + g_ptr_array_add (array, g_strdup (p)); + p = n + 1; + } + if ((gsize)(p - contents) < len) { + g_ptr_array_add (array, g_strndup (p, len - (p - contents))); + } + + g_ptr_array_add (array, NULL); + + g_free (contents); + return (char **)g_ptr_array_free (array, FALSE); + } + return NULL; +} + +struct scsi_unit { + gboolean exist; + char *vendor; + char *model; + char *rev; + int bus; + int id; + int lun; + int type; +}; + +struct cdrom_unit { + char *device; + int speed; + gboolean can_write_cdr; + gboolean can_write_cdrw; + gboolean can_write_dvdr; + gboolean can_write_dvdram; + gboolean can_read_dvd; +}; + +static void +parse_sg_line (char *device_str, char *devices, struct scsi_unit *scsi_unit) +{ + char vendor[9], model[17], rev[5]; + int host_no, access_count, queue_depth, device_busy, online, channel; + + scsi_unit->exist = FALSE; + + if (strcmp (device_str, "<no active device>") == 0) { + scsi_unit->exist = FALSE; + return; + } + if (sscanf (device_str, "%8c\t%16c\t%4c", vendor, model, rev) != 3) { + g_warning ("Couldn't match line in /proc/scsi/sg/device_strs\n"); + return; + } + vendor[8] = 0; model[16] = 0; rev[4] = 0; + + scsi_unit->vendor = g_strdup (g_strstrip (vendor)); + scsi_unit->model = g_strdup (g_strstrip (model)); + scsi_unit->rev = g_strdup (g_strstrip (rev)); + + if (sscanf (devices, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d", + &host_no, + &channel, &scsi_unit->id, &scsi_unit->lun, &scsi_unit->type, + &access_count, &queue_depth, &device_busy, + &online) != 9) { + + g_warning ("Couldn't match line in /proc/scsi/sg/devices\n"); + return; + } + scsi_unit->bus = host_no; + scsi_unit->exist = TRUE; +} + +static int +count_strings (char *p) +{ + int n_strings; + + n_strings = 0; + while (*p != 0) { + n_strings++; + while (*p != '\t' && *p != 0) { + p++; + } + if (*p == '\t') { + p++; + } + } + return n_strings; +} + +static int +get_cd_scsi_id (const char *dev, int *bus, int *id, int *lun) +{ + int fd; + char *devfile; + struct { + long mux4; + long hostUniqueId; + } m_idlun; + + devfile = g_strdup_printf ("/dev/%s", dev); + fd = open(devfile, O_RDONLY | O_NONBLOCK); + g_free (devfile); + + if (fd < 0) { + g_warning ("Failed to open cd device %s\n", dev); + return 0; + } + + if (ioctl (fd, SCSI_IOCTL_GET_BUS_NUMBER, bus) < 0) { + g_warning ("Failed to get scsi bus nr\n"); + close (fd); + return 0; + } + if (ioctl (fd, SCSI_IOCTL_GET_IDLUN, &m_idlun) < 0) { + g_warning ("Failed to get scsi id and lun\n"); + close(fd); + return 0; + } + *id = m_idlun.mux4 & 0xFF; + *lun = (m_idlun.mux4 >> 8) & 0xFF; + + close(fd); + return 1; +} + +static struct scsi_unit * +lookup_scsi_unit (int bus, int id, int lun, + struct scsi_unit *scsi_units, int n_scsi_units) +{ + int i; + + for (i = 0; i < n_scsi_units; i++) { + if (scsi_units[i].bus == bus && + scsi_units[i].id == id && + scsi_units[i].lun == lun) { + return &scsi_units[i]; + } + } + return NULL; +} + +static int +get_device_max_speed (char *id) +{ + int max_speed, i; + const char *argv[20]; /* Shouldn't need more than 20 arguments */ + char *dev_str, *stdout_data, *speed; + + max_speed = 1; + + i = 0; + argv[i++] = "cdrecord"; + argv[i++] = "-prcap"; + dev_str = g_strdup_printf ("dev=%s", id); + argv[i++] = dev_str; + argv[i++] = NULL; + + if (g_spawn_sync (NULL, + (char **)argv, + NULL, + G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL, + NULL, NULL, + &stdout_data, + NULL, + NULL, + NULL)) { + speed = strstr (stdout_data, "Maximum write speed in kB/s:"); + if (speed != NULL) { + speed += strlen ("Maximum write speed in kB/s:"); + max_speed = (int)floor (atol (speed) / 176.0 + 0.5); + } + } + + g_free (dev_str); + return max_speed; + +} + + +static char * +get_scsi_cd_name (int bus, int id, int lun, const char *dev, + struct scsi_unit *scsi_units, int n_scsi_units) +{ + struct scsi_unit *scsi_unit; + + scsi_unit = lookup_scsi_unit (bus, id, lun, scsi_units, n_scsi_units); + if (scsi_unit == NULL) { + return g_strdup_printf (_("Unnamed SCSI CDROM (%s)"), dev); + } + + return g_strdup_printf ("%s - %s", + scsi_unit->vendor, + scsi_unit->model); +} + +static GList * +add_linux_cd_recorder (GList *cdroms, + struct cdrom_unit *cdrom_s, + struct scsi_unit *scsi_units, + int n_scsi_units) +{ + int bus, id, lun; + CDDrive *cdrom; + + if (!get_cd_scsi_id (cdrom_s->device, &bus, &id, &lun)) { + return cdroms; + } + + cdrom = g_new0 (CDDrive, 1); + cdrom->device = g_strdup_printf ("/dev/%s", cdrom_s->device); + cdrom->cdrecord_id = g_strdup_printf ("%d,%d,%d", + bus, id, lun); + cdrom->display_name = get_scsi_cd_name (bus, id, lun, cdrom_s->device, scsi_units, n_scsi_units); + cdrom->max_speed_write = get_device_max_speed (cdrom->cdrecord_id); + cdrom->max_speed_read = cdrom_s->speed; + if (cdrom_s->can_write_dvdr + || cdrom_s->can_write_dvdram) { + cdrom->type = CDDRIVE_TYPE_DVD_RECORDER; + } else { + cdrom->type = CDDRIVE_TYPE_CD_RECORDER; + } + + return g_list_append (cdroms, cdrom); +} + +static char * +cdrom_get_name (struct cdrom_unit *cdrom, struct scsi_unit *scsi_units, int n_scsi_units) +{ + char *filename, *line, *retval; + int bus, id, lun, i; + + g_return_val_if_fail (cdrom != NULL, FALSE); + + if ((cdrom->device[0] == 's' && + cdrom->device[1] == 'r') || + (cdrom->device[0] == 's' && + cdrom->device[1] == 'c' && + cdrom->device[2] == 'd')) { + get_cd_scsi_id (cdrom->device, &bus, &id, &lun); + + retval = get_scsi_cd_name (bus, id, lun, cdrom->device, scsi_units, n_scsi_units); + } else { + filename = g_strdup_printf ("/proc/ide/%s/model", + cdrom->device); + if (!g_file_get_contents (filename, &line, NULL, NULL) || + line == NULL) { + g_free (filename); + return NULL; + } + g_free (filename); + + i = strlen (line); + if (line[i-1] != '\n') { + retval = g_strdup (line); + } else { + retval = g_strndup (line, i - 1); + } + + g_free (line); + } + + return retval; +} + +static GList * +add_linux_cd_drive (GList *cdroms, struct cdrom_unit *cdrom_s, + struct scsi_unit *scsi_units, int n_scsi_units) +{ + CDDrive *cdrom; + + cdrom = g_new0 (CDDrive, 1); + cdrom->cdrecord_id = NULL; + cdrom->device = g_strdup_printf ("/dev/%s", cdrom_s->device); + cdrom->display_name = cdrom_get_name (cdrom_s, scsi_units, n_scsi_units); + cdrom->max_speed_write = 0; /* Can't write */ + cdrom->max_speed_read = cdrom_s->speed; + if (cdrom_s->can_read_dvd) { + cdrom->type = CDDRIVE_TYPE_DVD_DRIVE; + } else { + cdrom->type = CDDRIVE_TYPE_CD_DRIVE; + } + + return g_list_append (cdroms, cdrom); +} + +static char * +get_cd_device_file (const char *str) +{ + char *devname; + + if (str[0] == 's' && str[1] == 'r') { + devname = g_strdup_printf ("/dev/scd%c", str[2]); + if (g_file_test (devname, G_FILE_TEST_EXISTS)) { + g_free (devname); + return g_strdup_printf ("scd%c", str[2]); + } + g_free (devname); + } + return g_strdup (str); +} + +static GList * +linux_scan (gboolean recorder_only) +{ + char **device_str, **devices; + char **cdrom_info; + struct scsi_unit *scsi_units; + struct cdrom_unit *cdroms; + char *p, *t; + int n_scsi_units, n_cdroms, i, j; + int fd; + GList *cdroms_list; + + /* Open /dev/sg0 to force loading of the sg module if not loaded yet */ + fd = open ("/dev/sg0", O_RDONLY); + if (fd != -1) { + close (fd); + } + + devices = read_lines ("/proc/scsi/sg/devices"); + if (devices != NULL) { + device_str = read_lines ("/proc/scsi/sg/device_strs"); + if (device_str == NULL) { + g_warning ("Can't read /proc/scsi/sg/device_strs"); + g_strfreev (devices); + return NULL; + } + + /* Count the number of scsi units, DO NOT REMOVE */ + for (n_scsi_units = 0; + device_str[n_scsi_units] != NULL && devices[n_scsi_units] != NULL; + n_scsi_units++) { + /* Nothing */ + } + + scsi_units = g_new0 (struct scsi_unit, n_scsi_units); + for (i = 0; i < n_scsi_units; i++) { + parse_sg_line (device_str[i], devices[i], &scsi_units[i]); + } + + g_strfreev (device_str); + g_strfreev (devices); + } else { + scsi_units = NULL; + n_scsi_units = 0; + } + + cdrom_info = read_lines ("/proc/sys/dev/cdrom/info"); + if (cdrom_info == NULL || cdrom_info[0] == NULL || cdrom_info[1] == NULL) { + g_warning ("Couldn't read /proc/sys/dev/cdrom/info"); + g_free (scsi_units); + return NULL; + } + + if (!g_str_has_prefix (cdrom_info[2], "drive name:\t")) { + g_free (scsi_units); + return NULL; + } + p = cdrom_info[2] + strlen ("drive name:\t"); + while (*p == '\t') { + p++; + } + n_cdroms = count_strings (p); + cdroms = g_new0 (struct cdrom_unit, n_cdroms); + + for (j = 0; j < n_cdroms; j++) { + t = strchr (p, '\t'); + if (t != NULL) { + *t = 0; + } + cdroms[j].device = get_cd_device_file (p); + if (t != NULL) { + p = t + 1; + } + } + + for (i = 3; cdrom_info[i] != NULL; i++) { + if (g_str_has_prefix (cdrom_info[i], "Can write CD-R:")) { + p = cdrom_info[i] + strlen ("Can write CD-R:"); + while (*p == '\t') { + p++; + } + for (j = 0; j < n_cdroms; j++) { + cdroms[j].can_write_cdr = *p++ == '1'; + + /* Skip tab */ + p++; + } + } + if (g_str_has_prefix (cdrom_info[i], "Can write CD-RW:")) { + p = cdrom_info[i] + strlen ("Can write CD-RW:"); + while (*p == '\t') { + p++; + } + for (j = 0; j < n_cdroms; j++) { + cdroms[j].can_write_cdrw = *p++ == '1'; + + /* Skip tab */ + p++; + } + } + if (g_str_has_prefix (cdrom_info[i], "Can write DVD-R:")) { + p = cdrom_info[i] + strlen ("Can write DVD-R:"); + while (*p == '\t') { + p++; + } + for (j = 0; j < n_cdroms; j++) { + cdroms[j].can_write_dvdr = *p++ == '1'; + + /* Skip tab */ + p++; + } + } + if (g_str_has_prefix (cdrom_info[i], "Can write DVD-RAM:")) { + p = cdrom_info[i] + strlen ("Can write DVD-RAM:"); + while (*p == '\t') { + p++; + } + for (j = 0; j < n_cdroms; j++) { + cdroms[j].can_write_dvdram = *p++ == '1'; + + /* Skip tab */ + p++; + } + } + if (g_str_has_prefix (cdrom_info[i], "Can read DVD:")) { + p = cdrom_info[i] + strlen ("Can read DVD:"); + while (*p == '\t') { + p++; + } + for (j = 0; j < n_cdroms; j++) { + cdroms[j].can_read_dvd = *p++ == '1'; + + /* Skip tab */ + p++; + } + } + if (g_str_has_prefix (cdrom_info[i], "drive speed:")) { + p = cdrom_info[i] + strlen ("drive speed:"); + while (*p == '\t') { + p++; + } + for (j = 0; j < n_cdroms; j++) { + cdroms[j].speed = atoi (p); + + /* Skip tab */ + p++; + } + } + } + g_strfreev (cdrom_info); + + cdroms_list = NULL; + for (i = 0; i < n_cdroms; i++) { + if (cdroms[i].can_write_cdr || + cdroms[i].can_write_cdrw || + cdroms[i].can_write_dvdr || + cdroms[i].can_write_dvdram) { + cdroms_list = add_linux_cd_recorder (cdroms_list, + &cdroms[i], scsi_units, n_scsi_units); + } else if (!recorder_only) { + cdroms_list = add_linux_cd_drive (cdroms_list, + &cdroms[i], scsi_units, n_scsi_units); + } + } + + g_free (scsi_units); + g_free (cdroms); + + return cdroms_list; +} +#endif /* __linux__ */ + +GList * +scan_for_cdroms (gboolean recorder_only, gboolean add_image) +{ + CDDrive *cdrom; + GList *cdroms = NULL; + +#ifdef __linux__ + cdroms = linux_scan (recorder_only); +#endif + + if (add_image) { + /* File */ + cdrom = g_new0 (CDDrive, 1); + cdrom->display_name = g_strdup (_("File image")); + cdrom->max_speed_read = 0; + cdrom->max_speed_write = 0; + cdrom->type = CDDRIVE_TYPE_FILE; + + cdroms = g_list_append (cdroms, cdrom); + } + + return cdroms; +} + +void +cd_drive_free (CDDrive *drive) +{ + g_return_if_fail (drive != NULL); + + g_free (drive->display_name); + g_free (drive->cdrecord_id); + g_free (drive->device); +} + diff --git a/src/cd-drive.h b/src/cd-drive.h new file mode 100644 index 0000000..ef0e238 --- /dev/null +++ b/src/cd-drive.h @@ -0,0 +1,52 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- + + cd-drive.h: easy to use cd burner software + + Copyright (C) 2002 Red Hat, Inc. + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + Authors: Alexander Larsson <alexl@redhat.com> + Bastien Nocera <hadess@hadess.net> +*/ + +#ifndef CD_DRIVE_H +#define CD_DRIVE_H + +#include <glib.h> + +typedef enum { + CDDRIVE_TYPE_FILE, + CDDRIVE_TYPE_CD_RECORDER, + CDDRIVE_TYPE_DVD_RECORDER, + CDDRIVE_TYPE_CD_DRIVE, + CDDRIVE_TYPE_DVD_DRIVE, +} CDDriveType; + +typedef struct { + CDDriveType type; + char *display_name; + int max_speed_write; + int max_speed_read; + char *cdrecord_id; + char *device; +} CDDrive; + +/* Returns a list of CDDrive structs */ +GList *scan_for_cdroms (gboolean recorder_only, gboolean add_image); +void cd_drive_free (CDDrive *drive); + +#endif diff --git a/src/sj-error.c b/src/sj-error.c new file mode 100644 index 0000000..409ef77 --- /dev/null +++ b/src/sj-error.c @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2003 Ross Burton + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <config.h> + +#include "sj-error.h" + +GQuark +sj_error_quark (void) +{ + static GQuark q = 0; + if (q == 0) { + q = g_quark_from_static_string ("sj-error-quark"); + } + return q; +} diff --git a/src/sj-error.h b/src/sj-error.h new file mode 100644 index 0000000..eeb5815 --- /dev/null +++ b/src/sj-error.h @@ -0,0 +1,14 @@ +#ifndef SJ_ERROR_H +#define SJ_ERROR_H + +#include <glib.h> + +#define SJ_ERROR sj_error_quark () + +typedef enum { + SJ_ERROR_INTERNAL_ERROR +} SjError; + +GQuark sj_error_quark (void) G_GNUC_CONST; + +#endif diff --git a/src/sj-gstreamer-fake.c b/src/sj-gstreamer-fake.c new file mode 100644 index 0000000..5f6f394 --- /dev/null +++ b/src/sj-gstreamer-fake.c @@ -0,0 +1,41 @@ +#include <glib/gerror.h> +#include <glib/gmessages.h> +#include <glib/gtimer.h> +#include <glib/gmain.h> +#include "sj-gstreamer.h" + +void sj_gstreamer_init (int argc, char **argv, GError **error) +{ + g_print ("gstreamer-fake: init()\n"); +} + +void sj_gstreamer_shutdown (void) +{ + g_print ("gstreamer-fake: shutdown()\n"); +} + +void sj_gstreamer_set_cdrom (const char* device) +{ + g_print ("gstreamer-fake: set_cdrom(\"%s\")\n", device == NULL ? "NULL" : device); +} + +static int counter; + +static gboolean idle_callback(gpointer data) +{ + g_print("."); + g_usleep(100); + counter++; + if (counter > 100) { + /* fire finish */ + } else if (counter % 10 == 0) { + /* fire progress event */ + } + return TRUE; +} + +void sj_gstreamer_extract_track (const TrackDetails *track, const char* path, GError **error) +{ + g_print ("gstreamer-fake: extract_track()\n"); + g_idle_add (idle_callback, NULL); +} diff --git a/src/sj-gstreamer.c b/src/sj-gstreamer.c new file mode 100644 index 0000000..a8c3a2e --- /dev/null +++ b/src/sj-gstreamer.c @@ -0,0 +1,181 @@ +#include <glib/gerror.h> +#include <glib/gtypes.h> +#include <gst/gst.h> +#include "sj-structures.h" +#include "sj-gstreamer.h" +#include "sj-error.h" + +static GstElement *pipeline; +static GstElement *cdparanoia, *vorbisenc, *filesink; +static GstFormat track_format; +GstPad *source_pad; + +#define THREADED 0 +#define MAINLOOP 1 + +typedef void (*progress_cb_t) (int seconds); +typedef void (*completion_cb_t) (void); + +progress_cb_t progress_cb; +completion_cb_t completion_cb; + +static void eos_cb (GstElement *gstelement, gpointer user_data) +{ + completion_cb(); +} + +void sj_gstreamer_init (int argc, char **argv, GError **error) +{ + gst_init (&argc, &argv); + +#if THREADED + pipeline = gst_thread_new ("pipeline"); +#else + pipeline = gst_pipeline_new ("pipeline"); +#endif + + /* Read from CD */ + cdparanoia = gst_element_factory_make ("cdparanoia", "cdparanoia"); + if (cdparanoia == NULL) { + g_set_error (error, + SJ_ERROR, SJ_ERROR_INTERNAL_ERROR, + "Could not create cdparanoia element"); + return; + } + g_object_set (G_OBJECT (cdparanoia), "paranoia_mode", 0, NULL); + /* Get the track format for seeking later */ + track_format = gst_format_get_by_nick ("track"); + g_assert (track_format != 0); /* TODO: GError */ + /* Get the source pad for seeking */ + source_pad = gst_element_get_pad (cdparanoia, "src"); + g_assert (source_pad); /* TODO: GError */ + + /* Encode to Ogg Vorbis */ + vorbisenc = gst_element_factory_make ("vorbisenc", "vorbisenc"); + if (vorbisenc == NULL) { + g_set_error (error, + SJ_ERROR, SJ_ERROR_INTERNAL_ERROR, + "Could not create Vorbis encoding element"); + return; + } + + /* Write to disk */ + filesink = gst_element_factory_make ("filesink", "filesink"); + if (filesink == NULL) { + g_set_error (error, + SJ_ERROR, SJ_ERROR_INTERNAL_ERROR, + "Could not create file sink element"); + return; + } + + /* Add the elements to the pipeline */ + gst_bin_add (GST_BIN (pipeline), cdparanoia); + gst_bin_add (GST_BIN (pipeline), vorbisenc); + gst_bin_add (GST_BIN (pipeline), filesink); + + /* Link it all together */ +#if 0 + gst_element_link_pads (cdparanoia, "src", vorbisenc, "sink"); + gst_element_link_pads (vorbisenc, "src", filesink, "sink"); +#else + gst_element_link_many (cdparanoia, vorbisenc, filesink, NULL); +#endif + + g_signal_connect (cdparanoia, "eos", eos_cb, NULL); +} + +void sj_gstreamer_shutdown (void) +{ + g_return_if_fail (pipeline != NULL); + gst_element_set_state (pipeline, GST_STATE_NULL); +} + +void sj_gstreamer_set_cdrom (const char* device) +{ + g_assert (cdparanoia != NULL); + g_return_if_fail (device != NULL); + + g_object_set (G_OBJECT (cdparanoia), "location", device, NULL); +} + +static gint seconds; + +static gboolean tick_timeout_cb(gpointer user_data) +{ + gint64 nanos; + gint secs; + static GstFormat format = GST_FORMAT_TIME; + + if (gst_element_get_state (pipeline) != GST_STATE_PLAYING) { + return FALSE; + } + + if (!gst_pad_query (source_pad, GST_QUERY_POSITION, &format, &nanos)) { + g_print ("pad_query failed!\n"); + return TRUE; + } + + secs = nanos / GST_SECOND; + if (secs != seconds) { + seconds = secs; + progress_cb(seconds); + } + return TRUE; +} + +void sj_gstreamer_set_callbacks (progress_cb_t progress, completion_cb_t completion) +{ + progress_cb = progress; + completion_cb = completion; +} +void sj_gstreamer_extract_track (const TrackDetails *track, const char* path, GError **error) +{ + GstEvent *event; + GstCaps *caps; + char *tracknumber; + + g_return_if_fail (pipeline != NULL); + g_return_if_fail (path != NULL); + g_return_if_fail (track != NULL); + + /* Set the output filename */ + g_object_set (G_OBJECT (filesink), "location", path, NULL); + + /* Set the Ogg metadata */ + /* Requires gst 0.6.1 to work correctly */ + tracknumber = g_strdup_printf("%d", track->number); + caps = GST_CAPS_NEW ("vorbisenc_metadata", + "application/x-gst-metadata", + "title", GST_PROPS_STRING (track->title), + "artist", GST_PROPS_STRING (track->artist), + "tracknumber", GST_PROPS_STRING (tracknumber), + "album", GST_PROPS_STRING (track->album->title), + "comment", GST_PROPS_STRING("Ripped with Sound Juicer") + ); + g_object_set (G_OBJECT (vorbisenc), "metadata", caps, NULL); + g_free (tracknumber); + + /* Let's get ready to rumble! */ + gst_element_set_state (pipeline, GST_STATE_PAUSED); + + /* Seek to the right track */ + event = gst_event_new_segment_seek (track_format | GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH, + track->number-1, track->number); + if (!gst_pad_send_event (source_pad, event)) { + g_set_error (error, + SJ_ERROR, SJ_ERROR_INTERNAL_ERROR, + "Could not seek to track"); + return; + } + + gst_element_set_state (pipeline, GST_STATE_PLAYING); +#if MAINLOOP + g_idle_add ((GSourceFunc)gst_bin_iterate, pipeline); + g_timeout_add (200, (GSourceFunc)tick_timeout_cb, NULL); +#else + while (gst_bin_iterate (GST_BIN (pipeline))) { + g_print("."); + } + gst_element_set_state (pipeline, GST_STATE_NULL); +#endif +} diff --git a/src/sj-gstreamer.h b/src/sj-gstreamer.h new file mode 100644 index 0000000..16014f3 --- /dev/null +++ b/src/sj-gstreamer.h @@ -0,0 +1,14 @@ +#ifndef SJ_GSTREAMER_H +#define SJ_GSTREAMER_H + +#include <glib/gerror.h> +#include "sj-structures.h" + +void sj_gstreamer_init (int argc, char **argv, GError **error); +void sj_gstreamer_shutdown (void); + +void sj_gstreamer_set_cdrom (const char* device); + +void sj_gstreamer_extract_track (const TrackDetails *track, const char* path, GError **error); + +#endif diff --git a/src/sj-musicbrainz-fake.c b/src/sj-musicbrainz-fake.c new file mode 100644 index 0000000..fb5caa3 --- /dev/null +++ b/src/sj-musicbrainz-fake.c @@ -0,0 +1,45 @@ +#include <glib/glist.h> +#include <glib/gerror.h> +#include <glib/gstrfuncs.h> +#include "sj-musicbrainz.h" +#include "sj-structures.h" + +void sj_musicbrainz_init (void) {} + +void sj_musicbrainz_set_cdrom (const char* device) {} + +GList* sj_musicbrainz_list_albums (GError **error) { + GList *albums = NULL; + AlbumDetails *album; + TrackDetails *track; + int i; + + album = g_new0 (AlbumDetails, 1); + album->title = "Some Title"; + album->artist = "Some Artist"; + + for (i = 1; i < 10; i++) { + track = g_new0 (TrackDetails, 1); + track->number = i; + track->title = g_strdup_printf ("Track %d", i); + track->artist = album->artist; + track->duration = 60; + album->tracks = g_list_append (album->tracks, track); + } + albums = g_list_append (albums, album); + + album = g_new0 (AlbumDetails, 1); + album->title = "Another Album"; + album->artist = "Someone Else"; + + for (i = 1; i < 10; i++) { + track = g_new0 (TrackDetails, 1); + track->number = i; + track->title = g_strdup_printf ("Song %d", i); + track->artist = album->artist; + track->duration = 120; + album->tracks = g_list_append (album->tracks, track); + } + albums = g_list_append (albums, album); + return albums; +} diff --git a/src/sj-musicbrainz.c b/src/sj-musicbrainz.c new file mode 100644 index 0000000..07dee05 --- /dev/null +++ b/src/sj-musicbrainz.c @@ -0,0 +1,122 @@ +#include <glib/gerror.h> +#include <glib/glist.h> +#include <glib/gstrfuncs.h> +#include <glib/gmessages.h> +#include <musicbrainz/queries.h> +#include <musicbrainz/mb_c.h> +#include <stdlib.h> +#include "sj-musicbrainz.h" +#include "sj-structures.h" + +static char* cdrom; + +void sj_musicbrainz_init (void) { + cdrom = g_strdup ("/dev/cdrom"); +} + +void sj_musicbrainz_set_cdrom(const char* device) { + g_return_if_fail (device != NULL); + g_free (cdrom); + cdrom = g_strdup (device); +} + +static GList* get_offline_track_listing(musicbrainz_t mb, GError **error) +{ + GList* list = NULL; + AlbumDetails *album; + TrackDetails *track; + int num_tracks, i; + + if (!mb_Query (mb, MBQ_GetCDTOC)) { + char error[255]; + mb_GetQueryError (mb, error, 255); + g_print("Cannot read CD: %s\n", error); + return NULL; /* TODO: GError */ + } + num_tracks = mb_GetResultInt (mb, MBE_TOCGetLastTrack); + + album = g_new0 (AlbumDetails, 1); + album->artist = "Unknown Artist"; + album->title = "Unknown Title"; + for (i = 1; i <= num_tracks; i++) { + track = g_new0 (TrackDetails, 1); + track->album = album; + track->number = i; + track->title = g_strdup_printf ("Track %d", i); + track->artist = album->artist; + /* TODO: track duration */ + album->tracks = g_list_append (album->tracks, track); + } + return g_list_append (list, album); +} + +/* TODO: GErrorify */ +GList* sj_musicbrainz_list_albums(GError **error) { + GList *albums = NULL; + musicbrainz_t mb; + char data[256]; + int num_albums, i, j; + + mb = mb_New (); + if (!mb) { + g_print ("Cannot get MusicBrainz connection\n"); + return NULL; /* TODO: GError */ + } + mb_SetDevice (mb, cdrom); + + if (!mb_Query (mb, MBQ_GetCDInfo)) { + char error[255]; + mb_GetQueryError (mb, error, 255); + g_print("Cannot lookup CD: %s\n", error); + return get_offline_track_listing (mb, NULL); + } + + num_albums = mb_GetResultInt(mb, MBE_GetNumAlbums); + if (num_albums < 1) { + g_print("This CD was not found.\n"); + return NULL; + } + + for (i = 1; i <= num_albums; i++) { + int num_tracks; + AlbumDetails *album; + + mb_Select1(mb, MBS_SelectAlbum, i); + album = g_new0 (AlbumDetails, 1); + + mb_GetResultData(mb, MBE_AlbumGetAlbumName, data, 256); + album->title = g_strdup (data); + + mb_GetResultData1(mb, MBE_AlbumGetArtistName, data, 256, 1); + album->artist = g_strdup (data); + + num_tracks = mb_GetResultInt(mb, MBE_AlbumGetNumTracks); + + for (j = 1; j <= num_tracks; j++) { + TrackDetails *track; + track = g_new0 (TrackDetails, 1); + + track->album = album; + + track->number = j; /* TODO: replace with number lookup */ + + if (mb_GetResultData1(mb, MBE_AlbumGetTrackName, data, 256, j)) { + track->title = g_strdup (data); + } + + if (mb_GetResultData1(mb, MBE_AlbumGetArtistName, data, 256, i)) { + track->artist = g_strdup (data); + } + + if (mb_GetResultData1(mb, MBE_AlbumGetTrackDuration, data, 256, j)) { + track->duration = atoi (data) / 1000; + } + + album->tracks = g_list_append (album->tracks, track); + } + + albums = g_list_append (albums, album); + } + mb_Delete (mb); + return albums; +} diff --git a/src/sj-musicbrainz.h b/src/sj-musicbrainz.h new file mode 100644 index 0000000..0164fe7 --- /dev/null +++ b/src/sj-musicbrainz.h @@ -0,0 +1,11 @@ +#ifndef SJ_MUSICBRAINZ_H +#define SJ_MUSICBRAINZ_H + +#include <glib/glist.h> +#include <glib/gerror.h> + +void sj_musicbrainz_init (void); +void sj_musicbrainz_set_cdrom (const char* device); +GList* sj_musicbrainz_list_albums (GError **error); + +#endif diff --git a/src/sj-structures.h b/src/sj-structures.h new file mode 100644 index 0000000..94ca558 --- /dev/null +++ b/src/sj-structures.h @@ -0,0 +1,24 @@ +#ifndef SJ_STRUCTURES_H +#define SJ_STRUCTURES_H + +#include <glib/glist.h> + +typedef struct _AlbumDetails AlbumDetails; +typedef struct _TrackDetails TrackDetails; + + +struct _TrackDetails { + AlbumDetails *album; + int number; /* track number */ + const char *title; + const char *artist; + int duration; /* seconds */ +}; + +struct _AlbumDetails { + const char* title; + const char* artist; + GList* tracks; +}; + +#endif diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..d875c4a --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,17 @@ +INCLUDES = -I../src/ @LIBGLADE_CFLAGS@ @GSTREAMER_CFLAGS@ @MUSICBRAINZ_CFLAGS@ @GNOME_CFLAGS@ +AM_CFLAGS = -g -Wall +DEFS = -DGNOME_DISABLE_DEPRECATED=1 + +noinst_PROGRAMS = data-test glade-test gst-test mb-test + +data_test_SOURCES = data-test.c +data_test_LDADD = @GLIB_LIBS@ + +gst_test_SOURCES = gst-test.c ../src/sj-gstreamer.c ../src/sj-error.c +gst_test_LDADD = @GLIB_LIBS@ @GSTREAMER_LIBS@ + +mb_test_SOURCES = mb-test.c ../src/sj-musicbrainz.c +mb_test_LDADD = @GLIB_LIBS@ @MUSICBRAINZ_LIBS@ + +glade_test_SOURCES = glade-test.c ../src/sj-error.c ../src/sj-gstreamer.c ../src/sj-musicbrainz.c ../src/bacon-cd-selection.c ../src/cd-drive.c +glade_test_LDADD = @MUSICBRAINZ_LIBS@ @GSTREAMER_LIBS@ @LIBGLADE_LIBS@ @GNOME_LIBS@ diff --git a/tests/data-test.c b/tests/data-test.c new file mode 100644 index 0000000..08677c9 --- /dev/null +++ b/tests/data-test.c @@ -0,0 +1,31 @@ +#include "sj-structures.h" +#include <glib.h> + +int main(int argc, char **argv) +{ + AlbumDetails* album; + TrackDetails* track; + int i; + + album = g_new0 (AlbumDetails, 1); + album->title = "Some Title"; + album->artist = "Some Artist"; + + for (i = 1; i < 10; i++) { + track = g_new0 (TrackDetails, 1); + track->number = i; + track->title = g_strdup_printf ("Track %d", i); + track->artist = album->artist; + track->duration = 0; + album->tracks = g_list_append (album->tracks, track); + } + + g_print("Album Title: %s; Artist: %s\n", album->title, album->artist); + /* This destroys the GList but I don't care */ + while (album->tracks) { + TrackDetails *track = (TrackDetails*)album->tracks->data; + g_print("Track %d; Title: %s; Artist: %s\n", track->number, track->title, track->artist); + album->tracks = g_list_next (album->tracks); + } + return 0; +} diff --git a/tests/glade-test.c b/tests/glade-test.c new file mode 100644 index 0000000..7d226f7 --- /dev/null +++ b/tests/glade-test.c @@ -0,0 +1,490 @@ +#include "config.h" +#include <string.h> +#include <sys/stat.h> +#include <gtk/gtk.h> +#include <glade/glade-xml.h> +#include <gconf/gconf-client.h> +#include <libgnomeui/gnome-about.h> +#include <libgnomeui/gnome-file-entry.h> +#include "bacon-cd-selection.h" +#include "sj-musicbrainz.h" +#include "sj-gstreamer.h" +#include "sj-structures.h" + +GladeXML *glade; + +GConfClient *gconf_client; + +GtkWidget *main_window, *progress_dialog = NULL; +GtkWidget *title_label, *artist_label, *basepath_label; +GtkWidget *track_listview, *cd_option, *reread_button, *extract_button; +GtkWidget *progress_label, *track_progress; +GtkListStore *track_store; + +const char *base_path; +const char *device; +int duration; /* duration of current track for progress dialog */ +gboolean ripping = FALSE; + +#define GCONF_ROOT "/apps/sound-juicer" +#define GCONF_DEVICE GCONF_ROOT "/device" +#define GCONF_BASEPATH GCONF_ROOT "/base_path" + +enum { + COLUMN_EXTRACT, + COLUMN_NUMBER, + COLUMN_TITLE, + COLUMN_ARTIST, + COLUMN_DURATION, + COLUMN_DETAILS, + COLUMN_TOTAL +}; + +/** + * Clicked About in the menus + */ +void on_about_activate (GtkMenuItem *item, gpointer user_data) +{ + GtkWidget *dialog = NULL; + const char* authors[] = {"Ross Burton <ross@burtonini.com>", NULL}; + dialog = gnome_about_new ("Sound Juicer", + VERSION, + "Copyright (C) 2003 Ross Burton", + "A CD ripper", + authors, + NULL, NULL, NULL); + gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (main_window)); + gtk_dialog_run (GTK_DIALOG (dialog)); +} + +/** + * Clicked Quit + */ +void on_quit_activate (GtkMenuItem *item, gpointer user_data) +{ + sj_gstreamer_shutdown (); + gtk_main_quit (); +} + +gboolean on_destory_event (GtkWidget *widget, GdkEvent *event, gpointer user_data) +{ + if (ripping) { + GtkWidget *dialog; + int response; + + dialog = gtk_message_dialog_new (GTK_WINDOW (main_window), GTK_DIALOG_MODAL, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_NONE, + "You are currently ripping a CD. Do you want to quit now or contine ripping?"); + gtk_dialog_add_button (GTK_DIALOG (dialog), "gtk-quit", GTK_RESPONSE_ACCEPT); + gtk_dialog_add_button (GTK_DIALOG (dialog), "Continue", GTK_RESPONSE_REJECT); + gtk_widget_show_all (dialog); + response = gtk_dialog_run (GTK_DIALOG (dialog)); + return response != GTK_RESPONSE_ACCEPT; + } + return FALSE; +} + +/** + * GtkTreeView cell renderer callback to render durations + */ +static void duration_cell_data_cb (GtkTreeViewColumn *tree_column, + GtkCellRenderer *cell, + GtkTreeModel *tree_model, + GtkTreeIter *iter, + gpointer data) +{ + GValue v = {0}; + int duration; + + gtk_tree_model_get_value (tree_model, iter, COLUMN_DURATION, &v); + duration = g_value_get_int (&v); + + g_value_unset (&v); + g_value_init(&v, G_TYPE_STRING); + g_value_set_string (&v, g_strdup_printf("%d:%02d", duration / 60, duration % 60)); + g_object_set_property (G_OBJECT (cell), "text", &v); +} + +/** + * Utility function to update the UI for a given Album + */ +static void update_ui_for_album (AlbumDetails *album) +{ + GList *l; + if (album == NULL) { + gtk_label_set_text (GTK_LABEL (title_label), ""); + gtk_label_set_text (GTK_LABEL (artist_label), ""); + gtk_list_store_clear (track_store); + gtk_widget_set_sensitive (extract_button, FALSE); + } else { + gtk_label_set_text (GTK_LABEL (title_label), album->title); + gtk_label_set_text (GTK_LABEL (artist_label), album->artist); + gtk_widget_set_sensitive (extract_button, TRUE); + + gtk_list_store_clear (track_store); + for (l = album->tracks; l; l=g_list_next (l)) { + GtkTreeIter iter; + TrackDetails *track = (TrackDetails*)l->data; + gtk_list_store_append (track_store, &iter); + gtk_list_store_set (track_store, &iter, + COLUMN_NUMBER, track->number, + COLUMN_TITLE, track->title, + COLUMN_ARTIST, track->artist, + COLUMN_DURATION, track->duration, + COLUMN_DETAILS, track, + -1); + } + } +} + +/** + * Called by the Multiple Album dialog when the user hits return in + * the list view + */ +static void album_row_activated (GtkTreeView *treeview, + GtkTreePath *arg1, + GtkTreeViewColumn *arg2, + gpointer user_data) +{ + GtkDialog *dialog = GTK_DIALOG (user_data); + gtk_dialog_response (dialog, GTK_RESPONSE_OK); +} + +/** + * Utility function for when there are more than one albums available + */ +AlbumDetails* multiple_album_dialog(GList *albums) +{ + static GtkWidget *dialog = NULL, *albums_listview; + static GtkListStore *albums_store; + static GtkTreeSelection *selection; + AlbumDetails *album; + GtkTreeIter iter; + int response; + + if (dialog == NULL) { + GtkTreeViewColumn *column; + GtkCellRenderer *text_renderer = text_renderer = gtk_cell_renderer_text_new (); + + dialog = glade_xml_get_widget (glade, "multiple_dialog"); + g_assert (dialog != NULL); + gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (main_window)); + albums_listview = glade_xml_get_widget (glade, "albums_listview"); + /* TODO: A little hacky */ + g_signal_connect (albums_listview, "row-activated", G_CALLBACK (album_row_activated), dialog); + + albums_store = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER); + column = gtk_tree_view_column_new_with_attributes ("Title", + text_renderer, + "text", 0, + NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (albums_listview), column); + + column = gtk_tree_view_column_new_with_attributes ("Artist", + text_renderer, + "text", 1, + NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (albums_listview), column); + gtk_tree_view_set_model (GTK_TREE_VIEW (albums_listview), GTK_TREE_MODEL (albums_store)); + selection = gtk_tree_view_get_selection(GTK_TREE_VIEW (albums_listview)); + gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE); + } + + gtk_list_store_clear (albums_store); + for (; albums ; albums = g_list_next (albums)) { + GtkTreeIter iter; + AlbumDetails *album = (AlbumDetails*)(albums->data); + gtk_list_store_append (albums_store, &iter); + gtk_list_store_set (albums_store, &iter, + 0, album->title, + 1, album->artist, + 2, album, + -1); + } + /* TODO: focus is a little broken here */ + gtk_widget_grab_focus (albums_listview); + gtk_widget_show_all (dialog); + response = gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_hide (dialog); + + if (response == GTK_RESPONSE_DELETE_EVENT) { + return NULL; + } + gtk_tree_selection_get_selected (selection, NULL, &iter); + gtk_tree_model_get (GTK_TREE_MODEL (albums_store), &iter, 2, &album, -1); + return album; +} + +/** + * The GConf key for the base path changed + */ +void basepath_changed_cb (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data) +{ + g_assert (strcmp (entry->key, GCONF_BASEPATH) == 0); + if (entry->value == NULL) { + base_path = g_strdup (g_get_home_dir ()); + } else { + base_path = gconf_value_get_string (entry->value); + } + /* TODO: sanity check the path somewhat */ + gtk_label_set_text (GTK_LABEL (basepath_label), base_path); +} + +/** + * Utility function to reread a CD + */ +void reread_cd (void) +{ + GList *albums; + GError *error = NULL; + + albums = sj_musicbrainz_list_albums(&error); + if (error) { + g_print ("Cannot list albums: %s\n", error->message); + g_error_free (error); + return; + } + + /* If there is more than one album... */ + if (g_list_next (albums)) { + update_ui_for_album(multiple_album_dialog (albums)); + } else { + update_ui_for_album (albums ? albums->data : NULL); + } +} + +/** + * The GConf key for the device changed + */ +void device_changed_cb (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer user_data) +{ + g_assert (strcmp (entry->key, GCONF_DEVICE) == 0); + + if (entry->value == NULL) { + device = bacon_cd_selection_get_device (BACON_CD_SELECTION (cd_option)); + if (device == NULL) { +#if 0 + GtkWidget *dialog; + dialog = gtk_message_dialog_new (NULL, 0, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "<b>No CD-ROMs found</b>\n\n" + "Sound Juicer could not find any CD-ROM drives to read."); + gtk_label_set_use_markup (GTK_LABEL (GTK_MESSAGE_DIALOG (dialog)->label), TRUE); + gtk_dialog_run (GTK_DIALOG (dialog)); + exit(1); /* TODO: fix */ +#endif + } + } else { + device = gconf_value_get_string (entry->value); + /* TODO: sanity check device */ + } + sj_musicbrainz_set_cdrom (device); + sj_gstreamer_set_cdrom (device); + + reread_cd(); +} + +/** + * Called for every selected track when ripping + */ +static gboolean rip_track_foreach_cb (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + gpointer data) +{ + /* Remember, FALSE to continue! */ + TrackDetails *track; + gboolean extract; + char *file_path, *directory; + int number; + + gtk_tree_model_get (model, iter, COLUMN_EXTRACT, &extract, -1); + if (!extract) return FALSE; + + gtk_tree_model_get (model, iter, + COLUMN_NUMBER, &number, + COLUMN_DETAILS, &track, + COLUMN_DURATION, &duration, + -1); + + gtk_label_set_text (GTK_LABEL (progress_label), g_strdup_printf ("Currently extracting '%s'", track->title)); + file_path = g_strdup_printf("%s/%s/%s/%s.ogg", base_path, track->artist, track->album->title, track->title); /* TODO: CRAP */ + /* TODO: create the folder */ + directory = g_path_get_dirname (file_path); + if (!g_file_test (directory, G_FILE_TEST_IS_DIR)) { + int res; + res = mkdir (directory, 0750); + if (res == -1) { + /* TODO: handle errno, dialog etc */ + g_warning ("mkdir() failed"); + return TRUE; + } + } + g_free (directory); + ripping = TRUE; + sj_gstreamer_extract_track (track, file_path, NULL); + g_free (file_path); + /* Need to wait for completion */ + return FALSE; +} + +/** + * Clicked on Extract in the UI + */ +void on_extract_activate (GtkWidget *button, gpointer user_data) +{ + if (progress_dialog == NULL) { + progress_dialog = glade_xml_get_widget (glade, "progress_dialog"); + track_progress = glade_xml_get_widget (glade, "track_progress"); + progress_label = glade_xml_get_widget (glade, "progress_label"); + g_assert (progress_dialog != NULL); + } + gtk_widget_show_all (progress_dialog); + gtk_tree_model_foreach (GTK_TREE_MODEL (track_store), rip_track_foreach_cb, NULL); +} + +/** + * Clicked on Reread in the UI (button/menu) + */ +void on_reread_activate (GtkWidget *button, gpointer user_data) +{ + reread_cd (); +} + +/** + * Changed the CD-ROM device in the prefs dialog + */ +void prefs_cdrom_changed_cb (GtkWidget *widget, const char* device) +{ + gconf_client_set_string (gconf_client, "/apps/sound-juicer/device", device, NULL); +} + +/** + * Clicked on Browse in the Prefs dialog + */ +void prefs_browse_clicked (GtkButton *button, gpointer user_data) +{ + g_print ("%s: TODO\n", __FUNCTION__); +} + +/** + * Clicked on Preferences in the UI + */ +void on_edit_preferences_cb (GtkMenuItem *item, gpointer user_data) +{ + static GtkWidget *dialog; + if (dialog == NULL) { + dialog = glade_xml_get_widget (glade, "prefs_dialog"); + g_assert (dialog != NULL); + gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (main_window)); + /* Maybe connect a GConf notify to the base_path key here to update the label... */ + } + gtk_widget_show_all (dialog); + gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_hide (dialog); +} + +static void on_extract_toggled (GtkCellRendererToggle *cellrenderertoggle, + gchar *path, + gpointer user_data) +{ + gboolean extract; + GtkTreeIter iter; + gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (track_store), &iter, path); + gtk_tree_model_get (GTK_TREE_MODEL (track_store), &iter, COLUMN_EXTRACT, &extract, -1); + gtk_list_store_set (track_store, &iter, COLUMN_EXTRACT, !extract, -1); +} + +static void on_progress_cb (int seconds) +{ + g_print ("Callback: %d\n", seconds); + gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (track_progress), (float)seconds/(float)duration); + return; +} + +static void on_completion_cb (void) +{ + gtk_widget_hide (progress_dialog); + g_print ("Callback complete\n"); + ripping = FALSE; + return; +} + +int main (int argc, char **argv) +{ + gtk_init (&argc, &argv); + sj_musicbrainz_init (); + sj_gstreamer_init (argc, argv, NULL); + sj_gstreamer_set_callbacks (on_progress_cb, on_completion_cb); + + gconf_client = gconf_client_get_default(); + g_assert (gconf_client != NULL); + /* TODO: move paths and key names to defines */ + gconf_client_add_dir (gconf_client, GCONF_ROOT, GCONF_CLIENT_PRELOAD_RECURSIVE, NULL); + gconf_client_notify_add (gconf_client, GCONF_DEVICE, device_changed_cb, NULL, NULL, NULL); + gconf_client_notify_add (gconf_client, GCONF_BASEPATH, basepath_changed_cb, NULL, NULL, NULL); + + glade = glade_xml_new ("../data/sound-juicer.glade", NULL, NULL); + g_assert (glade != NULL); + glade_xml_signal_autoconnect (glade); + + main_window = glade_xml_get_widget (glade, "main_window"); + title_label = glade_xml_get_widget (glade, "title_label"); + artist_label = glade_xml_get_widget (glade, "artist_label"); + basepath_label = glade_xml_get_widget (glade, "path_label"); /* from prefs, urgh */ + track_listview = glade_xml_get_widget (glade, "track_listview"); + cd_option = glade_xml_get_widget (glade, "cd_option"); /* hmm */ + extract_button = glade_xml_get_widget (glade, "extract_button"); + reread_button = glade_xml_get_widget (glade, "reread_button"); + + track_store = gtk_list_store_new (COLUMN_TOTAL, G_TYPE_BOOLEAN, G_TYPE_INT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_POINTER); + gtk_tree_view_set_model (GTK_TREE_VIEW (track_listview), GTK_TREE_MODEL (track_store)); + { + GtkTreeViewColumn *column; + GtkCellRenderer *text_renderer, *toggle_renderer; + + toggle_renderer = gtk_cell_renderer_toggle_new (); + g_signal_connect (toggle_renderer, "toggled", G_CALLBACK (on_extract_toggled), NULL); + column = gtk_tree_view_column_new_with_attributes ("Extract?", + toggle_renderer, + "active", COLUMN_EXTRACT, + NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (track_listview), column); + + text_renderer = gtk_cell_renderer_text_new (); /* TODO: is this cheating? */ + column = gtk_tree_view_column_new_with_attributes ("Track", + text_renderer, + "text", COLUMN_NUMBER, + NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (track_listview), column); + + column = gtk_tree_view_column_new_with_attributes ("Title", + text_renderer, + "text", COLUMN_TITLE, + NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (track_listview), column); + + column = gtk_tree_view_column_new_with_attributes ("Artist", + text_renderer, + "text", COLUMN_ARTIST, + NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (track_listview), column); + + column = gtk_tree_view_column_new_with_attributes ("Duration", + text_renderer, + NULL); + gtk_tree_view_column_set_cell_data_func (column, text_renderer, duration_cell_data_cb, NULL, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (track_listview), column); + + } + + /* YUCK. As bad as Baldrick's trousers */ + basepath_changed_cb (gconf_client, -1, gconf_client_get_entry (gconf_client, GCONF_BASEPATH, NULL, TRUE, NULL), NULL); + device_changed_cb (gconf_client, -1, gconf_client_get_entry (gconf_client, GCONF_DEVICE, NULL, TRUE, NULL), NULL); + + gtk_widget_show_all(main_window); + gtk_main(); + return 0; +} diff --git a/tests/gst-test.c b/tests/gst-test.c new file mode 100644 index 0000000..a0447a8 --- /dev/null +++ b/tests/gst-test.c @@ -0,0 +1,22 @@ +#include <glib.h> +#include "sj-gstreamer.h" +#include "sj-structures.h" + +int main(int argc, char** argv) +{ + GError *error = NULL; + + TrackDetails track; + track.artist = "Some Artist"; + track.title = "Some Title"; + track.number = 7; + + sj_gstreamer_init (argc, argv, &error); + if (error) { + g_print ("Cannot init SJ_GST: %s\n", error->message); + return 1; + } + sj_gstreamer_set_cdrom ("/dev/cdroms/cdrom1"); + sj_gstreamer_extract_track (&track, "test.ogg", NULL); + return 0; +} diff --git a/tests/mb-test.c b/tests/mb-test.c new file mode 100644 index 0000000..29e7819 --- /dev/null +++ b/tests/mb-test.c @@ -0,0 +1,25 @@ +#include <glib.h> +#include "sj-structures.h" +#include "sj-musicbrainz.h" + +int main (int argc, char** argv) +{ + GList *albums; + + sj_musicbrainz_init (); + sj_musicbrainz_set_cdrom ("/dev/cdroms/cdrom1"); + albums = sj_musicbrainz_list_albums(NULL); + + while (albums) { + AlbumDetails *album; + album = (AlbumDetails*)albums->data; + g_print ("'%s', by %s\n", album->title, album->artist); + while (album->tracks) { + TrackDetails *track = (TrackDetails*)album->tracks->data; + g_print (" Track %d; Title: %s; Artist: %s\n", track->number, track->title, track->artist); + album->tracks = g_list_next (album->tracks); + } + albums = g_list_next (albums); + } + return 0; +} |