[Pkg-gtkpod-devel] r280 - in gtkpod/tags: . 0.99.10-5 0.99.10-5/debian 0.99.10-5/debian/patches 0.99.10-5/scripts 0.99.10-5/src
nion at alioth.debian.org
nion at alioth.debian.org
Tue Nov 20 13:46:36 UTC 2007
Author: nion
Date: 2007-11-20 13:46:35 +0000 (Tue, 20 Nov 2007)
New Revision: 280
Added:
gtkpod/tags/0.99.10-5/
gtkpod/tags/0.99.10-5/README
gtkpod/tags/0.99.10-5/debian/changelog
gtkpod/tags/0.99.10-5/debian/control
gtkpod/tags/0.99.10-5/debian/patches/
gtkpod/tags/0.99.10-5/debian/patches/01_mountpoint.dpatch
gtkpod/tags/0.99.10-5/debian/rules
gtkpod/tags/0.99.10-5/scripts/sync-abook.sh
gtkpod/tags/0.99.10-5/scripts/sync-evocalendar.sh
gtkpod/tags/0.99.10-5/scripts/sync-evolution.sh
gtkpod/tags/0.99.10-5/scripts/sync-kaddressbook.sh
gtkpod/tags/0.99.10-5/scripts/sync-korganizer.sh
gtkpod/tags/0.99.10-5/scripts/sync-ldif.sh
gtkpod/tags/0.99.10-5/scripts/sync-thunderbird-nano.sh
gtkpod/tags/0.99.10-5/scripts/sync-thunderbird.sh
gtkpod/tags/0.99.10-5/scripts/sync-webcalendar.sh
gtkpod/tags/0.99.10-5/src/mp3file.c
gtkpod/tags/0.99.10-5/src/prefs.c
Removed:
gtkpod/tags/0.99.10-5/README
gtkpod/tags/0.99.10-5/debian/NEWS
gtkpod/tags/0.99.10-5/debian/changelog
gtkpod/tags/0.99.10-5/debian/control
gtkpod/tags/0.99.10-5/debian/patches/01_mountpoint.dpatch
gtkpod/tags/0.99.10-5/debian/rules
gtkpod/tags/0.99.10-5/scripts/sync-abook.sh
gtkpod/tags/0.99.10-5/scripts/sync-evocalendar.sh
gtkpod/tags/0.99.10-5/scripts/sync-evolution.sh
gtkpod/tags/0.99.10-5/scripts/sync-kaddressbook.sh
gtkpod/tags/0.99.10-5/scripts/sync-korganizer.sh
gtkpod/tags/0.99.10-5/scripts/sync-ldif.sh
gtkpod/tags/0.99.10-5/scripts/sync-thunderbird-nano.sh
gtkpod/tags/0.99.10-5/scripts/sync-thunderbird.sh
gtkpod/tags/0.99.10-5/scripts/sync-webcalendar.sh
gtkpod/tags/0.99.10-5/src/mp3file.c
gtkpod/tags/0.99.10-5/src/prefs.c
Log:
tagging 0.99.10-5
Copied: gtkpod/tags/0.99.10-5 (from rev 259, gtkpod/trunk)
Deleted: gtkpod/tags/0.99.10-5/README
===================================================================
--- gtkpod/trunk/README 2007-11-13 14:54:03 UTC (rev 259)
+++ gtkpod/tags/0.99.10-5/README 2007-11-20 13:46:35 UTC (rev 280)
@@ -1,1116 +0,0 @@
-iPod, iTunes, Mac, Macintosh, iBook are trademarks of Apple Computer,
-Inc., registered in the U.S. and other countries.
-
-
-
-Donations are welcome: please go to
-https://sourceforge.net/project/project_donations.php?group_id=67873
-for details.
-
-
-*----------------------------------*
-| |
-| Contents |
-| |
-*----------------------------------*
-
-
- - Using gtkpod
- - Features
- - Tracks
- - Filter Tabs
- - Playlists
- - Drag and Drop
- - Duplicate Detection
- - Preferences File
- - Startup and Shutdown scripts
- - Load iPod and eject iPod scripts
- - Extended Information File
- - Refresh (Update) Track Info From File
- - Synchronize Directories
- - Volume Normalization
- - Podcasts
- - Export of Tracks (Copy from iPod)
- - Encoding of ID3 tags (charsets)
- - Extracting tag information from the filename
- - Checking iPod's files
- - Restoring your iPod after file system error
- - Playcounts & Rating
- - About filenames
- - Icons for window managers
- - Connecting iPod to a Linux box:
- - Sick of loading the sbp2 modules by hand? (an example of how to
- use startup/shutdown scripts)
-
-*----------------------------------*
-| |
-| Using gtkpod |
-| |
-*----------------------------------*
-
-
-1) If your iPod is not mounted automatically when connecting it to
- your computer follow steps 1-7 in the "Connecting your iPod to a
- Linux box" (basically you need to get the iPod partition mounted to
- /media/ipod). In most cases this should not be necessary any more
- these days.
-
-2) If you are using GNOME, starting with V1.0 of gtkpod your iPod will
- be automatically loaded and displayed within gtkpod once you
- connect it to your box. Otherwise:
-
- - Use "Load iPods" to import the contents of your old iTunesDB (you
- may have to specify the correct mountpoint: right-button click on
- the "iPod" repository, select "Edit iPod's Properties" and change
- the mountpoint).
-
-3) Use "Add Files", "Add Directories" or DND to add files or
- directories.
-
-4) Use "Eject iPod" in the context menu or click on the icon to the
- left of the iPod name to write the added files to the iPod and
- create a new iTunesDB and unload the iPod from gtkpod.
-
-5) Unmount your iPod. The easiest way is to use the windowmanager. If
- this is not an option for you continue with step 8-11 of the
- "Connecting your iPod to a Linux box" section (basically describing
- how to unmount and disconnect your iPod).
-
- You can automate the unmounting by adding creating a
- ~/.gtkpod/gtkpod.eject file with the following line in it (without
- the quotation marks): "eject $1"
-
-
-*----------------------------------*
-| |
-| Features |
-| |
-*----------------------------------*
-
-Tracks
------
-
-- You can add individual tracks, entire directories recursively, or
- existing playlists using "Add Files". A file selection dialogue will
- appear. By default existing tracks (same full filename) will be skipped.
-- You can add directories recursively using "Add Dirs". A directory
- selection dialogue will appear.
-- You can add existing playlists using "Add Playlists"
-- You can delete tracks by marking them and pressing the "Ctrl-d" . If
- you delete tracks from the master playlist (the topmost playlist,
- called "gtkpod" by default). You can also delete tracks by selecting them,
- and using "Delete Track" in the Edit menu or from the context menu.
-- You can update ID3 tags of selected tracks in gtkpod from the mp3
- file by pressing "Ctrl-u" or choose "Update track info from file" in
- the Edit menu or from the context menu.
-- You can rename ID3 tags by editing the fields in gtkpod. You can
- change an entire group of ID3 tags by editing an entry in the sort
- tab (or mark several tracks and edit the first).
-- You can specify which tags to display in the preferences window
-- You can specify (in the prefs window) if the ID3 tags of the
- corresponding mp3 file(s) should also be updated
-
-
-Filter Tabs
------------
-
-- The two notebooks above the track display are called "Filter Tabs"
-- They allow you to filter which tracks to display
-- If you edit an entry in the filter tab, the corresponding entry in all
- associated tracks will be updated as well. When writing the tags to
- disk as well, updating of a large number of tracks may take a while
-
-
-Playlists
----------
-
-- You can create playlists with "New Playlist" or pressing "Ctrl-n" in
- the playlist listview.
-- You can also create playlists by adding an existing playlist file
- with "Add file" or "Add playlist".
-- You can add tracks to playlists by marking the tracks you want to add,
- and then dragging them onto the playlist.
-- You can rename playlists.
-- You can delete playlists by selecting the desired playlist and pressing
- "Ctrl-D", or by selecting "Delete Playlist" from the Edit menu.
-
-
-Drag and Drop
--------------
-
-Drag and Drop can be used in several ways:
-
-1) gtkpod internal
-
-- Playlists, entries of a filter tab, and tracks can be dragged.
-
-- A drop _onto_ an existing playlist will add the tracks to that
- playlist
-
-- A drop _between_ two existing playlists or behind the last playlist
- will create a new playlist to which the tracks are added.
-
-- The default action for the drop is either move or copy as appears
- appropriate (e.g. playlists are moved within a database ('local' or
- 'iPod/Shuffle'), but copied when dragged across different
- databases). The applicable action is displayed within the drag
- icon and can be changed by pressing the control key during the drop.
-
-2) between external file browser and gtkpod
-
-- Tracks, directories or playlist files can be dropped onto the
- playlist view or track view. Drops between two existing playlists
- create a new playlist.
-
-
-Preferences File
-----------------
-
-On startup gtkpod will read the preferences from ~/.gtkpod/prefs (or
-/etc/gtkpod/prefs if the former doesn't exist).
-
-
-Startup and Shutdown Scripts
-----------------------------
-
-After reading the preferences file gtkpod will try to execute
-~/.gtkpod/gtkpod.in (or /etc/gtkpod/gtkpod.in if the former doesn't
-exist) during startup.
-
-Just before exiting the program, gtkpod will try to execute
-~/.gtkpod/gtkpod.out (or /etc/gtkpod/gtkpod.out if the former doesn't
-exist).
-
-Please see the section "Sick of loading the sbp2 modules by hand?" for
-an example of how to use this functionality.
-
-
-
-Load iPod and eject iPod scripts
---------------------------------
-
-Before loading the contents of an iPod, gtkpod will call
-~/.gtkpod/gtkpod.load with the iPod's mountpoint as the only
-command line argument. Put any commands here needed to access the
-iPod, for example if you need to mount the iPod manually.
-
-When ejecting an iPod, gtkpod will call ~/.gtkpod/gtkpod.eject
-with the the iPod's mountpoint as the only command line argument. Put
-any commands here you want to execute after gtkpod has written the
-changes to the iPod. One major candidate will probably be
-
-sudo eject $1
-
-gtkpod will not attempt to do any magic of it's own to
-mount/unmount/eject the iPod.
-
-
-
-Duplicate Detection
--------------------
-
-You can instruct gtkpod (in the prefs window) to use
-file-size-dependent SHA1 checksums to prevent the same file from
-being copied to your iPod twice.
-
-If a duplicate is detected, gtkpod will print out the the filenames
-of the duplicate files. If the filename of the already existing file
-is not available (it is not stored in the iTunes database, see
-"Extended Information File" below), other available information of
-the track is printed.
-
-
-Extended Information File
--------------------------
-
-Some (I believe) essential information is not stored in Apple's iTunes
-database. You can therefore instruct gtkpod to write an additional
-file (iTunesDB.ext) with extended information. For each track it stores
-
- - SHA1 hash
- - filename in the locale's encoding
- - filename in UTF8 encoding
- - hostname where the file was added (not used for anything yet)
- - filename of an associated converted file (for example an .mp3 for
- a .flac file)
- - if the file is present in the local database a reference to there
- in order for playcounts to work on the local database as well
- - last modification time
- - the charset used for the file when adding it
-
-Since the extended information file is only valid with the
-corresponding standard iTunes database, a checksum of the iTunes
-database is also stored in the extended information file.
-
-Using an extended information file will considerably speed up the
-import of an existing iTunes database when using duplicate detection,
-since the SHA1 checksums do not have to be re-calculated.
-
-Using an extended information file will also allow modification of ID3
-tags in the track files after the initial import, because the full
-filenames are still available.
-
-
-Refresh (Update) Track Info From File
-------------------------------------
-
-If you have changed the ID3 tags of your original file, you can update
-the ID3 tags stored in gtkpod without removing and re-adding the
-track. Simply select the track to be updated and press "Ctrl-u" or
-choose "Update Track Info From File" from the Edit menu. Since gtkpod
-needs to know the filename of the track, the "Extended Information
-File" (see above) is needed.
-
-"Update" will also re-read the replay-gain tags from disk, if
-available, and set the soundcheck field. If no replay-gain tag is
-available, the soundcheck field will be erased.
-
-You can also select entries in the filter tab or entire playlists for
-refresh.
-
-
-Synchronize with Directories
-----------------------------
-
-If you have added files to directories or changed files in directories
-you have previously added tracks from, you can use the "Synchronize
-Dirs" utility to update your iTunesDB.
-
-"Synchronize with Dir(s)" will use the selected tracks to make a list
-of directories to update, so you should activate the "Write Extended
-Information" option in the export section of the preferences dialogue.
-
-It will then add all non-existing tracks in those directories and
-update (see "Refresh") all existing tracks. The tracks are also added to
-the currently selected playlist, if they aren't already a member.
-
-Tracks that have been removed from the directory will only be removed
-from the iTunesDB if this option is checked in the option dialogue.
-
-For best results you should also activate duplicate detection. This
-avoids unnecessary copying of unchanged tracks.
-
-
-
-Volume Normalization
---------------------
-
-There are two fields in the iTunesDB that allow to adjust the volume
-of an individual track: the volume field (a signed integer) and the
-soundcheck field (in dB). The volume is always active, whereas the
-soundcheck field is only active when you select 'soundcheck' on the
-iPod. Further, the soundcheck field only affects the earphone output
-but not the line output of the iPod.
-
-gtkpod will set the soundcheck according to the replay-gain tag set in
-your mp3 file. Newer versions of 'lame' automatically include the
-replay-gain tag when encoding. In that case the soundcheck field will
-be filled in when you first import a track.
-
-If no replay-gain tag is set, you can use the function 'Normalize
-Volume' to call mp3gain (mp3gain.sourceforge.net) to calculate the
-gain and write a replay-gain tag. Since this procedure is very time
-consuming, it is not done automatically during import. You need to
-install mp3gain in the default path or set the full path in the
-'Tools' section of the preferences dialog. If the iPod is connected,
-the tag is written to the file stored on the iPod.
-
-At this time "album gain" functionality is not supported. "Album gain"
-means that the volume of all tracks of one album is adjusted by the
-same gain, such that the relative volume level remains the same. It is
-planned to realize this in one of the next versions.
-
-Also, please be aware that tracks are not normalized on a 'per
-playlist' fashion. If a track is normalized, it's normalized in all
-playlists it is a member of.
-
-Once the replay-gain tag has been read, it is stored in the extended
-information file 'iTunesDB.ext'. When you call 'Normalize volume'
-again, the stored value will be used to re-populate the soundcheck
-field. Use 'Update Track' to re-read the tag from the file.
-
-
-Podcasts
---------
-
-You have to download podcasts using a third party tool like bashpodder
-(http://linc.homeunix.org:8080/scripts/bashpodder/) or gpodder
-(http://perli.net/projekte/gpodder/)
-
-Podcasts should be added directly into the 'Podcasts' playlist of the
-iPod repository, for example by selecting the Podcasts playlist before
-manually adding files/directories. Podcasts will then appear only in
-the Podcasts section on the iPod.
-
-If you add podcasts to the main playlist 'gtkpod/iPod' or any other
-iPod playlist first and then drag them over to the Podcasts playlist,
-the podcasts will appear in the Podcasts section on the iPod, as well
-as in the normal music section.
-
-The podcast 'repository' is a local repository (like 'Local') where
-you can keep all local podcasts. No mechanism exists to automatically
-synchronize the iPod repository with the Podcast repository at this
-time. You have to drag the podcasts over manually.
-
-
-Export of Tracks (Copy from iPod)
----------------------------------
-
-- mark the tracks you want to export and select "Export Tracks from
- Database" from the file menu (or use the context sensitive menu)
-- A file selection dialog window appears and you can choose the directory
- you'd like the selected files to be written to.
-- You can specify the output filename in the prefs dialog by
- specifying a template (e.g. "%A/%a - %t"). You can specify multiple
- templates for different file formats by separating them by a
- semicolon (e.g. "%A/%a - %t.mp3;%t.wav"). See the tooltip in the
- prefs dialog for a list of identifiers.
-
-
-Encoding of ID3 tags (charsets)
--------------------------------
-If you use correctly written unicode ID3V2 tags you don't have to
-worry about the charset setting.
-
-Otherwise you must specify the charset to be used for representing ID3
-tags in the preferences menu. The default is "System Charset", which
-is the charset associated with the locale gtkpod is running under. If
-your tags are stored in a different encoding, you should set it
-appropriately.
-
-Please note that if necessary you can change the charset each time you
-add files or directories: the iTunesDB itself is using UTF16, so once
-tags are imported correctly, changing the charset has no influence.
-
-If you chose "Japanese (automatic detection)", gtkpod will try to
-determine if the string is in ISO-2022-JP, Shift_JIS, or EUC-JP
-(Hankaku Katakana (1-byte Katakana) may not be recognized correctly --
-specify the correct encoding if you run into this problem). The actual
-encoding used for the ID tags will be stored and will be used when
-writing tags or doing updates/syncs. Check the "Use selected charset
-also when updating or syncing tracks" and "Use selected charset when
-writing tags" options if you want to specify a particular character
-set when writing or updating/syncing. The default charset is "EUC-JP"
--- it will be used when the charset cannot be autodetected, as well as
-when writing tags if a specific charset could not be determined
-before.
-
-gtkpod will recognize ID3V2 tags encoded in unicode automatically and
-ignore your charset setting when necessary.
-
-
-Extracting tag information from the filename
---------------------------------------------
-Tags can also be extracted from the filename if you activate the
-option 'Use this template to parse filename for tag information' and
-supply a template that explains how the filenames are constructed.
-
-For filenames like
- music/new/latin1/alan_jackson - drive/01 drive_for_daddy_gene.mp3
-you could use
- %a - %A/%T %*.mp3
-
-to extract artist, album, track number and title.
-
-The following character sequences are supported:
-
- %t: title
- %a: artist
- %A: album
- %c: composer
- %t: title
- %g: genre
- %T: track number
- %C: CD number
- %*: placeholder, ignore data
- %%: the character '%'
-
-You cannot supply a template like "%a%t.mp3" because gtkpod would not
-know how to separate artist and title. "%a_%t.mp3" would be correct,
-if artist and title are separated by an underscore.
-
-You can also omit the trailing ".mp3" if you want the template to
-apply to all files instead of only to mp3 files.
-
-
-Checking iPod's Files
----------------------
-For whatever reason -- it may happen that tracks are present in your
-iTunesDB that are no longer present on the iPod (dangling tracks), or
-that tracks are on the iPod but not in the iTunesDB (orphaned
-tracks).
-
-The function "Checking iPod's Files" under the "File" menu will
-identify both types and take the following actions:
-
-Orphaned tracks:
-A new playlist "[Orphaned]" will be created with all orphaned tracks
-in it. The only exception are orphaned tracks that would become
-duplicates (if duplicate detection is activated). Those are marked for
-deletion with the next sync.
-
-Dangling tracks:
-These tracks will be marked for deletion with the next sync unless the
-original PC file is still available. In that case you can have them
-restored with the next sync.
-
-
-Restoring your iPod after file system error
--------------------------------------------
-If iPod's file system gets corrupted and you need to reformat your
-iPod, there is a way to restore the contents semi-automatically if you
-have been using the "write extended information file" (iTunesDB.ext)
-options:
-
- - If the directory structure on the iPod doesn't exist yet,
- load the iPod in gtkpod and have it created for you. Then unload
- the iPod again.
-
- - copy your backup files in .gtkpod/ (usually iTunesDB and
- iTunesDB.ext) to your iPod (usually
- <mountpoint>/iPod_Control/iTunes/
- On the iPod the files must be named iTunesDB and iTunesDB.ext.
-
- - load the iPod in gtkpod
-
- - select the iPod repository and start "Check iPod's files" from the
- File menu
-
- - unload the iPod (or save changes)
-
-This should restore your iPod to what it was before, provided you
-didn't move or remove any of the original tracks on your harddrive, and
-the charset information was stored correctly.
-
-
-Playcounts & Rating
--------------------
-
-Whenever you play a track completely on the iPod (firmware version 1.3
-or higher) a counter in the "Play Counts" file will be increased by
-one. The same file also contains the rating you can set with the 3rd
-generation iPods.
-
-This file appears to be deleted whenever the iPod resets itself --
-e.g. because you disconnect it from the computer. Therefore, be
-careful... Charging the iPod seems to do no harm.
-
-When gtkpod is started, it will also read this file and incorporate
-the information into the iTunesDB that can be written back to the
-iPod.
-
-There have been several requests to also register playcounts when
-playing a track on the local machine. This is possible by calling
-gtkpod as "gtkpod -p <filename>".
-
-If gtkpod is already running, the playcount of that track there will
-be increased by one. If gtkpod is not already running, the playcount
-will be registered in ~/.gtkpod/offline_playcount. This file will be
-read the next time you import the iTunesDB from your iPod, and the
-playcounts will be updated accordingly.
-
-Please note that if you start several instances of gtkpod, only the
-first instance will register playcounts through "gtkpod -p".
-
-Now all you have to do is tell your favorite player to call gtkpod
-with the filename of the played track.
-
-For xmms this is possible as of July 18th, 2004 (CVS
-version). Versions before that (including 1.2.10) only allow you to
-have an external program called at the beginning of a track. Our patch
-allows to have an external program called also at the end of a track.
-
-In each case you will need to activate the "General Plugin" called
-"song_change" and configure it to call 'gtkpod -p "%f"'.
-
-
-About filenames (excerpt from the GTK2 release notes):
-------------------------------------------------------
-* The assumption of GLib and GTK+ by default is that filenames on the
- filesystem are encoded in UTF-8 rather than the encoding of the locale;
- The GTK+ developers consider that having filenames whose interpretation
- depends on the current locale is fundamentally a bad idea.
-
- If you have filenames encoded in the encoding of your locale, then
- you may want to set the G_BROKEN_FILENAMES environment variable:
-
- G_BROKEN_FILENAMES=1
- export G_BROKEN_FILENAMES
-
- Best integration of GTK+-2.0 with the environment is achieved by
- using a UTF-8 locale.
-
------- end of excerpt
-
-It is my feeling that many people use filenames encoded in the
-encoding of the locale. The "Add directories" dialogue already takes
-care of this and assumes the filenames to be in the same encoding as
-you have specified for the ID3 tags (see above). You can therefore
-forget about the excerpt above.
-
-However, the "Add Files" and "Add Playlists" dialogue (at the moment)
-uses the standard GTK+-2.0 file selection dialogue. Therefore I have
-no access on the conversion functions used, and a warning is printed
-when filenames are encountered that are encoded in an encoding other
-than the one of the current locale. ID3 tags are still read correctly
-(according to the charset set in the preference dialogue).
-
-
-*--------------------------------------------------*
-| |
-| Environment variables |
-| |
-*--------------------------------------------------*
-
-The following environment variables can be set if needed:
-
-IPOD_MOUNTPOINT: Defines the mountpoint of the iPod. This overwrites
-the value stored in the prefs, but is overwritten by the command line
-argument "-m" or "--mountpoint".
-
-GTKPOD_DF_COMMAND: Only used on systems without statvfs(). Defines the
-"df" command to be used for probing the free space on the iPod
-including command line arguments. Default is "df -k -P". On some
-systems it may be necessary to remove the "-P" option. The mount point
-is added to this command line automatically. You can switch off calls
-to df by setting this environment variable to an empty string.
-
-
-
-*--------------------------------------------------*
-| |
-| Icons for window managers |
-| |
-*--------------------------------------------------*
-
-Should you require an icon for your window manager you can use those
-provided in $(datadir)/pixmaps (usually
-/usr/local/share/gtkpod/pixmaps or
-/usr/share/gtkpod/pixmaps).
-
-Currently the following files are available:
-
- gtkpod-icon-32.png
- gtkpod-icon-32x32.png
- gtkpod-icon-32x32-2.png
- gtkpod-icon-48.png
- gtkpod-icon-48x48.png
- gtkpod-icon-64x64.png
-
-
-*--------------------------------------------------*
-| |
-| Connecting iPod to a Linux box |
-| (kernel 2.6.6) |
-| (should also work with earlier 2.6 kernels) |
-| |
-*--------------------------------------------------*
-
-This describes how to set up the iPod together with the automounter in
-kernel V2.6.6 (some minor changes in the kernel configuration may be
-necessary for older V2.6 versions).
-
-1) It appears to be possible to use HFS-formatted (Apple)
- iPods. However, this short guide assumes you have a Windows
- (VFAT) iPod. For conversion from HFS to VFAT please see
-
- http://www.blinkenlights.ch/gnupod/gnupod.html#SEC6
-
-2) I'm using the following kernel configuration options (I'm only
- using FireWire -- so the USB options are just educated
- guesses. Please let me know if it works).
-
- I'm not using modules, simply because what's compiled in can't fail
- loading.
-
- * General Setup -> Support for hot-pluggable devices - y
- * Device Drivers -> SCSI device support - y
- * -> SCSI device support -> SCSI disk support - y
- * -> SCSI device support -> SCSI generic support - y
-For FireWire:
- * -> IEEE1394 (FireWire) support - y
- * -> IEEE1394 (FireWire) support -> OHCI-1394 support - y
- * -> IEEE1394 (FireWire) support -> SBP-2 support - y
-For USB:
- * -> USB support -> Support for Host-side USB - y
- * -> EHCI HCD support - y
- * -> OHCI HCD support - y
- * -> UHCI HCD support - y
- * -> USB Mass Storage support - y
-For USB and FireWire:
- * Filesystems -> DOS/FAT/NT Filesystems - y
- * -> DOS/FAT/NT Filesystems -> VFAT fs support - y
- * -> Kernel automounter version 4 support - y
- * -> Native Language Support
- * -> Codepage 437 (CONFIG_NLS_CODEPAGE_437)
- * -> NLS ISO 8859-1 (CONFIG_NLS_ISO8859_1)
-
-
-
-(for iPods formatted with the HFS filesystem choose
- * Filesystems -> Miscellaneous filesystems
- -> Apple Extended HFS filesystem support)
-
-At least for the new 4Gs and iPod minis you should _disable_
-(CONFIG_EFI_PARTITION, see Troubleshooting for more information):
- * File Systems -> Partition Types -> Advanced Partition Selection
- -> EFI GUID Partition support
-
-3) You need to install the following external packages:
-
- hotplug and udev (http://linux-hotplug.sourceforge.net/)
- autofs (ftp.kernel.org:/pub/linux/daemons/autofs)
-
- Most likely packages are available for your distribution.
-
-4) Write rules for udev (/etc/udev/udev.rules, add at the beginning)
- to recognize your iPod automatically (mind the spaces within
- "iPod...", and be aware that some distributions require a double
- equal after the BUS keyword (BUS=="scsi"...)):
-
-BUS="scsi", SYSFS{model}="iPod ", KERNEL="sd?2", NAME="%k", SYMLINK="ipod"
-
- This will map /dev/sd?2 to /dev/ipod everytime you plug in your
- iPod. That even works if you own more than one USB/Firewire device
- that shows up as a harddisk, independent of the order in which you
- connect the devices.
-
- (You need to replace "sd?2" with "sd?1" (or maybe just "sd?") for
- HFS formatted iPods.)
-
- For more information on how to write udev rules please refer to
- http://www.gamingclones.com/Howtos/udevrules.html. That document
- gives an easy-to-understand introduction
-
-5) Set up autofs to automatically mount the iPod when you access it
- and unmount it after 2 seconds of inactivity. In /etc/auto.master
- add:
-
-/var/autofs/removable /etc/auto.removable --timeout=2,sync,nodev,nosuid,gid=autofs,umask=007
-
- Adjust the gid,umask (and uid) values to whatever you need -- in this
- example all users in the group "autofs" have read/write access, and
- I have added all users that may access the iPod to the autofs group.
-
- In /etc/auto.removable add
-
-ipod -fstype=vfat :/dev/ipod
-
- (Obviously you need to change the filesystem type from 'vfat' to
- 'hfsplus' when you use an HFS formatted iPod.)
-
- Then simply add a link from /media/ipod:
-
- ln -s /var/autofs/removable/ipod /media/ipod
-
-
-Now your system is configured to mount the iPod every time you access
-/media/ipod and to unmount it again after two seconds of inactivity. You
-won't have to worry about doing mounting/unmouting yourself any more.
-
-
-
-*--------------------------------------------------*
-| |
-| Connecting iPod to a Linux box (IEEE 1394) |
-| (kernel 2.4.21) |
-| (may also work with 2.4.20, but I didn't try) |
-| (instructions for 2.4.20 can be found below) |
-| |
-*--------------------------------------------------*
-
-1) You need a Windows iPod. See e.g.
-
-http://www.blinkenlights.ch/gnupod/gnupod.html#SEC6
-
-for information about how to convert your mac iPod to a windows iPod.
-
-Alternatively, I have received a report that Alan Cox's patches
-(2.4.21-rc8-ac1, but 2.4.21-ac1 should work as well) include hfsplus
-support. That should allow you to use hfs formatted iPods. But beware:
-hfsplus support is still beta.
-
-2) Get kernel source and configure
-Needed configuration:
-
- * Code maturity level options - y
- * SCSI support - y
- * SCSI disk support - y
- * IEEE1394 (FireWire)/IEEE 1394 (FireWire) support (Experimental) - y
- * OHCI-1394 support - y
- * SBP-2 support - m (important to use module -- if someone finds
- out how to use hotplug with sbp2 compiled in, let me know)
- (With 2.6.1 compiling sbp2 in seems to work fine.)
-At least for the new 4Gs and iPod minis you should _disable_
-(CONFIG_EFI_PARTITION, see Troubleshooting for more information):
- * File Systems -> Partition Types -> Advanced Partition Selection
- -> EFI GUID Partition support
- * -> Native Language Support
- * -> Codepage 437 (CONFIG_NLS_CODEPAGE_437)
- * -> NLS ISO 8859-1 (CONFIG_NLS_ISO8859_1)
-
-
-3) Create /media/ipod:
-
- mkdir /media/ipod
-
-4) Add a line to /etc/fstab. You should edit uid to match your user
- id. Also, /dev/sda2 may not be appropriate, if you have other scsi
- devices.
-
-/dev/sda2 /media/ipod vfat rw,user,noauto,noatime,errors=remount 0 0
-
- (For HFS this line should read
-
-/dev/sda /media/ipod hfsplus rw,user,noauto,exec 0 0
-
- please note that it's just '/dev/sda')
-
-
-NOTE: Some users have had problems with newer versions of mount(newer than
-mount-2.11h) The following fstab entry might work better for you.
-
-/dev/sda2 /media/ipod vfat rw,user,noauto,noatime,shortname=winnt 0 0
-
-5) Install the hotplug utilities
- (http://linux-hotplug.sourceforge.net/, debian package: 'hotplug')
-
- (If you don't want to use the hotplug utilities, you must call the
- rescan-scsi-bus.sh (see below) by hand after loading the sbp2
- module. This is different from 2.4.20.)
-
-5a) Add the ieee1394 hotplug support (described at
- http://www.linux1394.org/faq.html#hotplug):
-
- - copy ieee1394.agent to /etc/hotplug/ from
- http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/linux-hotplug/admin/etc/hotplug/
- - mkdir /etc/hotplug/ieee1394
- - create /etc/hotplug/ieee1394/sbp2:
- #!/bin/bash
- if [ "${ACTION}" = "add" ]; then
- . /etc/hotplug/ieee1394/rescan-scsi-bus.sh
- else
- . /etc/hotplug/ieee1394/rescan-scsi-bus.sh -r
- fi
- - chmod +rx /etc/hotplug/ieee1394/sbp2
- - copy rescan-scsi-bus.sh to /etc/hotplug/ieee1394 from
- http://www.garloff.de/kurt/linux/rescan-scsi-bus.sh
- - just to be sure: restart hotplug:
- /etc/init.d/hotplug restart
-
-6) Connect your iPod to your computer and wait until you see something
- like the following on your system log (you can use the 'dmesg'
- command to check).
-
-Jun 15 17:13:53 hatarakibachi kernel: ieee1394: Node 00:1023 changed to 01:1023
-Jun 15 17:13:55 hatarakibachi kernel: ieee1394: Node 01:1023 changed to 00:1023
-Jun 15 17:13:57 hatarakibachi kernel: ieee1394: sbp2: Logged into SBP-2 device
-Jun 15 17:13:57 hatarakibachi kernel: ieee1394: Device added: Node[00:1023] GUID[000a2700020680b5] [Apple Computer, Inc.]
-Jun 15 17:13:57 hatarakibachi kernel: ieee1394: Node 00:1023 changed to 01:1023
-Jun 15 17:13:57 hatarakibachi kernel: scsi singledevice 0 0 0 0
-Jun 15 17:13:57 hatarakibachi kernel: Vendor: Apple Model: iPod Rev: 1.30
-Jun 15 17:13:57 hatarakibachi kernel: Type: Direct-Access ANSI SCSI revision: 02
-Jun 15 17:13:57 hatarakibachi kernel: Attached scsi removable disk sda at scsi0, channel 0, id 0, lun 0
-Jun 15 17:13:57 hatarakibachi kernel: SCSI device sda: 39062520 512-byte hdwr sectors (20000 MB)
-Jun 15 17:13:57 hatarakibachi kernel: sda: test WP failed, assume Write Enabled
-Jun 15 17:13:58 hatarakibachi kernel: sda: sda1 sda2
-Jun 15 17:13:58 hatarakibachi kernel: scsi singledevice 0 0 1 0
-...
-
-7) Mount the iPod hard drive
-
- mount /media/ipod
-
-8) do whatever you need to do (e.g. start gtkpod, see below)
-
-9) Unmount the iPod:
-
- umount /media/ipod
-
-10) Unload the module sbp2 (as most likely as root):
-
- rmmod sbp2
-
-11) Disconnect the iPod from your computer (ignore the "Do not
- disconnect" message -- as long as you wait for the 'unmount' to
- command to finish properly, everything should be fine).
-
-
-
-*--------------------------------------------------*
-| |
-| Connecting iPod to a Linux box using IEEE 1394 |
-| (kernel 2.4.20) |
-| (connecting to 2.4.21 seems to work slightly |
-| differently -- see above) |
-| |
-*--------------------------------------------------*
-
-1) You need a Windows iPod. See e.g.
-
-http://www.blinkenlights.ch/gnupod/gnupod.html#SEC6
-
-for information about how to convert your mac iPod to a windows iPod.
-
-Alternatively, I have received a report that Alan Cox's patches
-(2.4.21-rc8-ac1, but 2.4.21-ac1 should work as well) include hfsplus
-support. That should allow you to use hfs formatted iPods. But beware:
-hfsplus support is still beta.
-
-2) Get kernel source and configure
-Needed configuration:
-
- * Code maturity level options - y
- * SCSI support - y
- * SCSI disk support - m
- * IEEE1394 (FireWire)/IEEE 1394 (FireWire) support (Experimental) - y
- * OHCI-1394 support - y
- * SBP-2 support - m
-At least for the new 4Gs and iPod minis you should _disable_
-(CONFIG_EFI_PARTITION, see Troubleshooting for more information):
- * File Systems -> Partition Types -> Advanced Partition Selection
- * -> EFI GUID Partition support
- * -> Native Language Support
- * -> Codepage 437 (CONFIG_NLS_CODEPAGE_437)
- * -> NLS ISO 8859-1 (CONFIG_NLS_ISO8859_1)
-
-3) Create /media/ipod:
-
- mkdir /media/ipod
-
-4) Add a line to /etc/fstab. You should edit uid to match your user
- id. Also, /dev/sda2 may not be appropriate, if you have other scsi
- devices.
-
-/dev/sda2 /media/ipod vfat rw,user,noauto,noatime 0 0
-
- (For HFS this line should read
-
-/dev/sda /media/ipod hfsplus rw,user,noauto,exec 0 0
-
- please note that it's just '/dev/sda')
-
-
-NOTE: Some users have had problems with newer versions of mount(newer than
-mount-2.11h) The following fstab entry might work better for you.
-
-/dev/sda2 /media/ipod vfat rw,user,noauto,noatime,shortname=winnt 0 0
-
-NOTE: You can add ",umask=0" to the options to make the iPod
-readable/writable for all users.
-
-5) Connect your iPod to your computer and wait until you see something
- like the following on your system log (you can use the 'dmesg'
- command to check).
-
-Nov 28 21:58:06 hatarakibachi kernel: ieee1394: Node 00:1023 changed to 01:1023
-Nov 28 21:58:09 hatarakibachi kernel: ieee1394: Node 01:1023 changed to 00:1023
-Nov 28 21:58:12 hatarakibachi kernel: ieee1394: NodeMgr: hotplug policy returned -2
-Nov 28 21:58:12 hatarakibachi kernel: ieee1394: Device added: Node[00:1023] GUID[000a2700020680b5] [Apple Computer, Inc.]
-Nov 28 21:58:12 hatarakibachi kernel: ieee1394: Node 00:1023 changed to 01:1023
-
-6) Load the sbp2 module (most likely as root):
-
- modprobe sbp2
-
- You should see something like the following on your system log:
-
-Nov 28 21:58:38 hatarakibachi kernel: ieee1394: sbp2: Logged into SBP-2 device
-Nov 28 21:58:38 hatarakibachi kernel: scsi0 : IEEE-1394 SBP-2 protocol driver (host: ohci1394)
-Nov 28 21:58:38 hatarakibachi kernel: $Rev$ James Goodwin <jamesg at filanet.com>
-Nov 28 21:58:38 hatarakibachi kernel: SBP-2 module load options:
-Nov 28 21:58:38 hatarakibachi kernel: - Max speed supported: S400
-Nov 28 21:58:38 hatarakibachi kernel: - Max sectors per I/O supported: 255
-Nov 28 21:58:38 hatarakibachi kernel: - Max outstanding commands supported: 8
-Nov 28 21:58:38 hatarakibachi kernel: - Max outstanding commands per lun supported: 1
-Nov 28 21:58:38 hatarakibachi kernel: - Serialized I/O (debug): no
-Nov 28 21:58:38 hatarakibachi kernel: - Exclusive login: yes
-Nov 28 21:58:38 hatarakibachi kernel: Vendor: Apple Model: iPod Rev: 1.21
-Nov 28 21:58:38 hatarakibachi kernel: Type: Direct-Access ANSI SCSI revision: 02
-Nov 28 21:58:38 hatarakibachi kernel: Attached scsi removable disk sda at scsi0, channel 0, id 0, lun 0
-Nov 28 21:58:38 hatarakibachi kernel: SCSI device sda: 39062520 512-byte hdwr sectors (20000 MB)
-Nov 28 21:58:38 hatarakibachi kernel: sda: test WP failed, assume Write Enabled
-Nov 28 21:58:39 hatarakibachi kernel: sda: sda1 sda2
-
-7) Mount the iPod hard drive
-
- mount /media/ipod
-
-8) do whatever you need to do (e.g. start gtkpod, see below)
-
-9) Unmount the iPod:
-
- umount /media/ipod
-
-10) Unload the module sbp2 (as most likely as root):
-
- rmmod sbp2
-
-11) Disconnect the iPod from your computer.
-
-
-*--------------------------------------------------*
-| |
-| Connecting iPod to a Linux box (USB) |
-| |
-*--------------------------------------------------*
-
-I don't have much information about this so far (I don't own a third
-generation iPod). Please help me to fill in the gaps.
-
-Stephen Drye sent me the following note:
-
-"I've figured out how to get a USB-connected iPod recognized...:
-
-The trick to it is that you have to
-
-- plug the iPod in
-
-- it'll fail to be recognized by the SCSI subsystem
-
-- now, even though your ipod says not to, unplug the USB cord and
- immediately plug it back in.
-
-- since the iPod's hdd was already spun up, the SCSI subsystem now
- recognizes it and mounts it as /dev/sda
-
-- You can then mount /dev/sda2 to /media/ipod as normal."
-
-On the other hand: with my 4G iPod under 2.6.9 and 2.6.10 I never had
-any problem whatsoever getting the iPod to work. With IEEE it was
-awful (would work some times, would not some other time).
-
-
-*----------------------------------*
-| |
-| Sick of loading the sbp2 |
-| modules by hand? |
-| |
-| Corey Donohoe |
-| <atmos at atmos dot org> |
-| March 22nd 2003 |
-| |
-*----------------------------------*
-
-Sick of loading the sbp2 modules by hand every time you want to use your
-ipod? Are you sick of mounting it too? Using sudo gtkpod can make manually
-interacting with the ipod filesystem a thing of the past. Note that you
-should have your ipod working with gtkpod before attempting this automated
-method, see the README that came with gtkpod in order to get things up and
-running.
-
-Here's a brief example of how I'm using gtkpod now in 8 easy steps.
-
-(Remark: the hotplug facility of new kernels can also load and unload
-the sbp2 module for you.)
-
-/**********/
- * Step 1 *
-/**********/
-Using sudo allow users to load/remove the sbp2 module
-Example /etc/sudoers
-------------------------------- Begin Here ---------------------------------
-
-# Cmnd alias specification
-Cmnd_Alias IPOD=/sbin/modprobe sbp2 sbp2_force_inquiry_hack=1, /sbin/rmmod sbp2
-# User privilege specification
-atmos ALL=(ALL) ALL
-atmos ALL= NOPASSWD : IPOD
-
-------------------------------- End Here -----------------------------------
-I use the force inquiry hack cause I have an older iPod, if you normally can
-get by with /sbin/modprobe sbp2 then ignore the inquiry hack stuff. Note
-that explicitly specifying which module to probe/remove keeps the user from
-being able to add/remove arbitrary modules. This allows us to keep gtkpod
-as a user process, and execute commands the user wouldn't usually have
-enough rights to.
-
-/**********/
- * Step 2 *
-/**********/
-Add a line similar to the below to your /etc/fstab, this will enable users
-to mount the ipod with read/write capabilities. Example line assumes your
-ipod mount point is /media/ipod and your ipod is detected as /dev/sda
-
-------------------------------- Begin Here ---------------------------------
-/dev/sda2 /media/ipod vfat rw,user,noauto 0 0
-------------------------------- End Here -----------------------------------
-
-
-/**********/
- * Step 3 *
-/**********/
-Then setup your /etc/gtkpod/gtkpod.in file to load the module when gtkpod is
-started.
-Example /etc/gtkpod/gtkpod.in
-------------------------------- Begin Here ---------------------------------
-
-sudo /sbin/modprobe sbp2 sbp2_force_inquiry_hack=1
-
-------------------------------- End Here -----------------------------------
-
-/**********/
- * Step 4 *
-/**********/
-
-Then setup your /etc/gtkpod/gtkpod.out file to unload the module when gtkpod
-is exited.
-Example /etc/gtkpod/gtkpod.out
-------------------------------- Begin Here ---------------------------------
-
-sudo /sbin/rmmod sbp2
-
-------------------------------- End Here -----------------------------------
-
-/**********/
- * Step 5 *
-/**********/
-Then enable ipod automounting in the gtkpod prefs(in the misc tab).
-
-/**********/
- * Step 6 *
-/**********/
-You're now ready to use gtkpod in a much nicer fashion. Start by
-plugging in your ipod. You should get a check mark with "OK to disconnect"
-displayed on your ipod.
-
-/**********/
- * Step 7 *
-/**********/
-Start gtkpod, your ipod should be accessible(i.e. autoimport should work)
-A "Do Not Disconnect" message is displayed on your ipod while gtkpod is
-running.
-
-/**********/
- * Step 8 *
-/**********/
-After you exit gtkpod, the "OK to disconnect" message should be displayed
-again. It's ok to unplug your ipod now.
-
-Good Luck.
-
-
-
-*----------------------------------*
-| |
-| Known bugs |
-| |
-*----------------------------------*
-
-
-- Display of large number of tracks is awfully slow (mainly because of
- the use of the standard GTK2 tree views) -> deactivate "Automatically
- select "All" in first filter tab" and/or deactivate "Automatically
- select master playlist". You could also "block the display" to speed
- up the display update. Further, decreasing the window size
- considerably speeds up the display.
-
- I also want to point out that updating the info window takes up a
- considerable amount of time. Update may become more intelligent in
- the future -- until then close the info window for more speed.
-
-- When changing selections in the filter tabs while importing the
- iTunesDB, sometimes the interface freezes. I tried to track this
- problem down but only found out that gtk+ does not return control
- back to gtkpod. Selecting the "All" filter tabs seems to unfreeze the
- interface again.
Copied: gtkpod/tags/0.99.10-5/README (from rev 269, gtkpod/trunk/README)
===================================================================
--- gtkpod/tags/0.99.10-5/README (rev 0)
+++ gtkpod/tags/0.99.10-5/README 2007-11-20 13:46:35 UTC (rev 280)
@@ -0,0 +1,1116 @@
+iPod, iTunes, Mac, Macintosh, iBook are trademarks of Apple Computer,
+Inc., registered in the U.S. and other countries.
+
+
+
+Donations are welcome: please go to
+https://sourceforge.net/project/project_donations.php?group_id=67873
+for details.
+
+
+*----------------------------------*
+| |
+| Contents |
+| |
+*----------------------------------*
+
+
+ - Using gtkpod
+ - Features
+ - Tracks
+ - Filter Tabs
+ - Playlists
+ - Drag and Drop
+ - Duplicate Detection
+ - Preferences File
+ - Startup and Shutdown scripts
+ - Load iPod and eject iPod scripts
+ - Extended Information File
+ - Refresh (Update) Track Info From File
+ - Synchronize Directories
+ - Volume Normalization
+ - Podcasts
+ - Export of Tracks (Copy from iPod)
+ - Encoding of ID3 tags (charsets)
+ - Extracting tag information from the filename
+ - Checking iPod's files
+ - Restoring your iPod after file system error
+ - Playcounts & Rating
+ - About filenames
+ - Icons for window managers
+ - Connecting iPod to a Linux box:
+ - Sick of loading the sbp2 modules by hand? (an example of how to
+ use startup/shutdown scripts)
+
+*----------------------------------*
+| |
+| Using gtkpod |
+| |
+*----------------------------------*
+
+
+1) If your iPod is not mounted automatically when connecting it to
+ your computer follow steps 1-7 in the "Connecting your iPod to a
+ Linux box" (basically you need to get the iPod partition mounted to
+ /mnt/ipod). In most cases this should not be necessary any more
+ these days.
+
+2) If you are using GNOME, starting with V1.0 of gtkpod your iPod will
+ be automatically loaded and displayed within gtkpod once you
+ connect it to your box. Otherwise:
+
+ - Use "Load iPods" to import the contents of your old iTunesDB (you
+ may have to specify the correct mountpoint: right-button click on
+ the "iPod" repository, select "Edit iPod's Properties" and change
+ the mountpoint).
+
+3) Use "Add Files", "Add Directories" or DND to add files or
+ directories.
+
+4) Use "Eject iPod" in the context menu or click on the icon to the
+ left of the iPod name to write the added files to the iPod and
+ create a new iTunesDB and unload the iPod from gtkpod.
+
+5) Unmount your iPod. The easiest way is to use the windowmanager. If
+ this is not an option for you continue with step 8-11 of the
+ "Connecting your iPod to a Linux box" section (basically describing
+ how to unmount and disconnect your iPod).
+
+ You can automate the unmounting by adding creating a
+ ~/.gtkpod/gtkpod.eject file with the following line in it (without
+ the quotation marks): "eject $1"
+
+
+*----------------------------------*
+| |
+| Features |
+| |
+*----------------------------------*
+
+Tracks
+-----
+
+- You can add individual tracks, entire directories recursively, or
+ existing playlists using "Add Files". A file selection dialogue will
+ appear. By default existing tracks (same full filename) will be skipped.
+- You can add directories recursively using "Add Dirs". A directory
+ selection dialogue will appear.
+- You can add existing playlists using "Add Playlists"
+- You can delete tracks by marking them and pressing the "Ctrl-d" . If
+ you delete tracks from the master playlist (the topmost playlist,
+ called "gtkpod" by default). You can also delete tracks by selecting them,
+ and using "Delete Track" in the Edit menu or from the context menu.
+- You can update ID3 tags of selected tracks in gtkpod from the mp3
+ file by pressing "Ctrl-u" or choose "Update track info from file" in
+ the Edit menu or from the context menu.
+- You can rename ID3 tags by editing the fields in gtkpod. You can
+ change an entire group of ID3 tags by editing an entry in the sort
+ tab (or mark several tracks and edit the first).
+- You can specify which tags to display in the preferences window
+- You can specify (in the prefs window) if the ID3 tags of the
+ corresponding mp3 file(s) should also be updated
+
+
+Filter Tabs
+-----------
+
+- The two notebooks above the track display are called "Filter Tabs"
+- They allow you to filter which tracks to display
+- If you edit an entry in the filter tab, the corresponding entry in all
+ associated tracks will be updated as well. When writing the tags to
+ disk as well, updating of a large number of tracks may take a while
+
+
+Playlists
+---------
+
+- You can create playlists with "New Playlist" or pressing "Ctrl-n" in
+ the playlist listview.
+- You can also create playlists by adding an existing playlist file
+ with "Add file" or "Add playlist".
+- You can add tracks to playlists by marking the tracks you want to add,
+ and then dragging them onto the playlist.
+- You can rename playlists.
+- You can delete playlists by selecting the desired playlist and pressing
+ "Ctrl-D", or by selecting "Delete Playlist" from the Edit menu.
+
+
+Drag and Drop
+-------------
+
+Drag and Drop can be used in several ways:
+
+1) gtkpod internal
+
+- Playlists, entries of a filter tab, and tracks can be dragged.
+
+- A drop _onto_ an existing playlist will add the tracks to that
+ playlist
+
+- A drop _between_ two existing playlists or behind the last playlist
+ will create a new playlist to which the tracks are added.
+
+- The default action for the drop is either move or copy as appears
+ appropriate (e.g. playlists are moved within a database ('local' or
+ 'iPod/Shuffle'), but copied when dragged across different
+ databases). The applicable action is displayed within the drag
+ icon and can be changed by pressing the control key during the drop.
+
+2) between external file browser and gtkpod
+
+- Tracks, directories or playlist files can be dropped onto the
+ playlist view or track view. Drops between two existing playlists
+ create a new playlist.
+
+
+Preferences File
+----------------
+
+On startup gtkpod will read the preferences from ~/.gtkpod/prefs (or
+/etc/gtkpod/prefs if the former doesn't exist).
+
+
+Startup and Shutdown Scripts
+----------------------------
+
+After reading the preferences file gtkpod will try to execute
+~/.gtkpod/gtkpod.in (or /etc/gtkpod/gtkpod.in if the former doesn't
+exist) during startup.
+
+Just before exiting the program, gtkpod will try to execute
+~/.gtkpod/gtkpod.out (or /etc/gtkpod/gtkpod.out if the former doesn't
+exist).
+
+Please see the section "Sick of loading the sbp2 modules by hand?" for
+an example of how to use this functionality.
+
+
+
+Load iPod and eject iPod scripts
+--------------------------------
+
+Before loading the contents of an iPod, gtkpod will call
+~/.gtkpod/gtkpod.load with the iPod's mountpoint as the only
+command line argument. Put any commands here needed to access the
+iPod, for example if you need to mount the iPod manually.
+
+When ejecting an iPod, gtkpod will call ~/.gtkpod/gtkpod.eject
+with the the iPod's mountpoint as the only command line argument. Put
+any commands here you want to execute after gtkpod has written the
+changes to the iPod. One major candidate will probably be
+
+sudo eject $1
+
+gtkpod will not attempt to do any magic of it's own to
+mount/unmount/eject the iPod.
+
+
+
+Duplicate Detection
+-------------------
+
+You can instruct gtkpod (in the prefs window) to use
+file-size-dependent SHA1 checksums to prevent the same file from
+being copied to your iPod twice.
+
+If a duplicate is detected, gtkpod will print out the the filenames
+of the duplicate files. If the filename of the already existing file
+is not available (it is not stored in the iTunes database, see
+"Extended Information File" below), other available information of
+the track is printed.
+
+
+Extended Information File
+-------------------------
+
+Some (I believe) essential information is not stored in Apple's iTunes
+database. You can therefore instruct gtkpod to write an additional
+file (iTunesDB.ext) with extended information. For each track it stores
+
+ - SHA1 hash
+ - filename in the locale's encoding
+ - filename in UTF8 encoding
+ - hostname where the file was added (not used for anything yet)
+ - filename of an associated converted file (for example an .mp3 for
+ a .flac file)
+ - if the file is present in the local database a reference to there
+ in order for playcounts to work on the local database as well
+ - last modification time
+ - the charset used for the file when adding it
+
+Since the extended information file is only valid with the
+corresponding standard iTunes database, a checksum of the iTunes
+database is also stored in the extended information file.
+
+Using an extended information file will considerably speed up the
+import of an existing iTunes database when using duplicate detection,
+since the SHA1 checksums do not have to be re-calculated.
+
+Using an extended information file will also allow modification of ID3
+tags in the track files after the initial import, because the full
+filenames are still available.
+
+
+Refresh (Update) Track Info From File
+------------------------------------
+
+If you have changed the ID3 tags of your original file, you can update
+the ID3 tags stored in gtkpod without removing and re-adding the
+track. Simply select the track to be updated and press "Ctrl-u" or
+choose "Update Track Info From File" from the Edit menu. Since gtkpod
+needs to know the filename of the track, the "Extended Information
+File" (see above) is needed.
+
+"Update" will also re-read the replay-gain tags from disk, if
+available, and set the soundcheck field. If no replay-gain tag is
+available, the soundcheck field will be erased.
+
+You can also select entries in the filter tab or entire playlists for
+refresh.
+
+
+Synchronize with Directories
+----------------------------
+
+If you have added files to directories or changed files in directories
+you have previously added tracks from, you can use the "Synchronize
+Dirs" utility to update your iTunesDB.
+
+"Synchronize with Dir(s)" will use the selected tracks to make a list
+of directories to update, so you should activate the "Write Extended
+Information" option in the export section of the preferences dialogue.
+
+It will then add all non-existing tracks in those directories and
+update (see "Refresh") all existing tracks. The tracks are also added to
+the currently selected playlist, if they aren't already a member.
+
+Tracks that have been removed from the directory will only be removed
+from the iTunesDB if this option is checked in the option dialogue.
+
+For best results you should also activate duplicate detection. This
+avoids unnecessary copying of unchanged tracks.
+
+
+
+Volume Normalization
+--------------------
+
+There are two fields in the iTunesDB that allow to adjust the volume
+of an individual track: the volume field (a signed integer) and the
+soundcheck field (in dB). The volume is always active, whereas the
+soundcheck field is only active when you select 'soundcheck' on the
+iPod. Further, the soundcheck field only affects the earphone output
+but not the line output of the iPod.
+
+gtkpod will set the soundcheck according to the replay-gain tag set in
+your mp3 file. Newer versions of 'lame' automatically include the
+replay-gain tag when encoding. In that case the soundcheck field will
+be filled in when you first import a track.
+
+If no replay-gain tag is set, you can use the function 'Normalize
+Volume' to call mp3gain (mp3gain.sourceforge.net) to calculate the
+gain and write a replay-gain tag. Since this procedure is very time
+consuming, it is not done automatically during import. You need to
+install mp3gain in the default path or set the full path in the
+'Tools' section of the preferences dialog. If the iPod is connected,
+the tag is written to the file stored on the iPod.
+
+At this time "album gain" functionality is not supported. "Album gain"
+means that the volume of all tracks of one album is adjusted by the
+same gain, such that the relative volume level remains the same. It is
+planned to realize this in one of the next versions.
+
+Also, please be aware that tracks are not normalized on a 'per
+playlist' fashion. If a track is normalized, it's normalized in all
+playlists it is a member of.
+
+Once the replay-gain tag has been read, it is stored in the extended
+information file 'iTunesDB.ext'. When you call 'Normalize volume'
+again, the stored value will be used to re-populate the soundcheck
+field. Use 'Update Track' to re-read the tag from the file.
+
+
+Podcasts
+--------
+
+You have to download podcasts using a third party tool like bashpodder
+(http://linc.homeunix.org:8080/scripts/bashpodder/) or gpodder
+(http://perli.net/projekte/gpodder/)
+
+Podcasts should be added directly into the 'Podcasts' playlist of the
+iPod repository, for example by selecting the Podcasts playlist before
+manually adding files/directories. Podcasts will then appear only in
+the Podcasts section on the iPod.
+
+If you add podcasts to the main playlist 'gtkpod/iPod' or any other
+iPod playlist first and then drag them over to the Podcasts playlist,
+the podcasts will appear in the Podcasts section on the iPod, as well
+as in the normal music section.
+
+The podcast 'repository' is a local repository (like 'Local') where
+you can keep all local podcasts. No mechanism exists to automatically
+synchronize the iPod repository with the Podcast repository at this
+time. You have to drag the podcasts over manually.
+
+
+Export of Tracks (Copy from iPod)
+---------------------------------
+
+- mark the tracks you want to export and select "Export Tracks from
+ Database" from the file menu (or use the context sensitive menu)
+- A file selection dialog window appears and you can choose the directory
+ you'd like the selected files to be written to.
+- You can specify the output filename in the prefs dialog by
+ specifying a template (e.g. "%A/%a - %t"). You can specify multiple
+ templates for different file formats by separating them by a
+ semicolon (e.g. "%A/%a - %t.mp3;%t.wav"). See the tooltip in the
+ prefs dialog for a list of identifiers.
+
+
+Encoding of ID3 tags (charsets)
+-------------------------------
+If you use correctly written unicode ID3V2 tags you don't have to
+worry about the charset setting.
+
+Otherwise you must specify the charset to be used for representing ID3
+tags in the preferences menu. The default is "System Charset", which
+is the charset associated with the locale gtkpod is running under. If
+your tags are stored in a different encoding, you should set it
+appropriately.
+
+Please note that if necessary you can change the charset each time you
+add files or directories: the iTunesDB itself is using UTF16, so once
+tags are imported correctly, changing the charset has no influence.
+
+If you chose "Japanese (automatic detection)", gtkpod will try to
+determine if the string is in ISO-2022-JP, Shift_JIS, or EUC-JP
+(Hankaku Katakana (1-byte Katakana) may not be recognized correctly --
+specify the correct encoding if you run into this problem). The actual
+encoding used for the ID tags will be stored and will be used when
+writing tags or doing updates/syncs. Check the "Use selected charset
+also when updating or syncing tracks" and "Use selected charset when
+writing tags" options if you want to specify a particular character
+set when writing or updating/syncing. The default charset is "EUC-JP"
+-- it will be used when the charset cannot be autodetected, as well as
+when writing tags if a specific charset could not be determined
+before.
+
+gtkpod will recognize ID3V2 tags encoded in unicode automatically and
+ignore your charset setting when necessary.
+
+
+Extracting tag information from the filename
+--------------------------------------------
+Tags can also be extracted from the filename if you activate the
+option 'Use this template to parse filename for tag information' and
+supply a template that explains how the filenames are constructed.
+
+For filenames like
+ music/new/latin1/alan_jackson - drive/01 drive_for_daddy_gene.mp3
+you could use
+ %a - %A/%T %*.mp3
+
+to extract artist, album, track number and title.
+
+The following character sequences are supported:
+
+ %t: title
+ %a: artist
+ %A: album
+ %c: composer
+ %t: title
+ %g: genre
+ %T: track number
+ %C: CD number
+ %*: placeholder, ignore data
+ %%: the character '%'
+
+You cannot supply a template like "%a%t.mp3" because gtkpod would not
+know how to separate artist and title. "%a_%t.mp3" would be correct,
+if artist and title are separated by an underscore.
+
+You can also omit the trailing ".mp3" if you want the template to
+apply to all files instead of only to mp3 files.
+
+
+Checking iPod's Files
+---------------------
+For whatever reason -- it may happen that tracks are present in your
+iTunesDB that are no longer present on the iPod (dangling tracks), or
+that tracks are on the iPod but not in the iTunesDB (orphaned
+tracks).
+
+The function "Checking iPod's Files" under the "File" menu will
+identify both types and take the following actions:
+
+Orphaned tracks:
+A new playlist "[Orphaned]" will be created with all orphaned tracks
+in it. The only exception are orphaned tracks that would become
+duplicates (if duplicate detection is activated). Those are marked for
+deletion with the next sync.
+
+Dangling tracks:
+These tracks will be marked for deletion with the next sync unless the
+original PC file is still available. In that case you can have them
+restored with the next sync.
+
+
+Restoring your iPod after file system error
+-------------------------------------------
+If iPod's file system gets corrupted and you need to reformat your
+iPod, there is a way to restore the contents semi-automatically if you
+have been using the "write extended information file" (iTunesDB.ext)
+options:
+
+ - If the directory structure on the iPod doesn't exist yet,
+ load the iPod in gtkpod and have it created for you. Then unload
+ the iPod again.
+
+ - copy your backup files in .gtkpod/ (usually iTunesDB and
+ iTunesDB.ext) to your iPod (usually
+ <mountpoint>/iPod_Control/iTunes/
+ On the iPod the files must be named iTunesDB and iTunesDB.ext.
+
+ - load the iPod in gtkpod
+
+ - select the iPod repository and start "Check iPod's files" from the
+ File menu
+
+ - unload the iPod (or save changes)
+
+This should restore your iPod to what it was before, provided you
+didn't move or remove any of the original tracks on your harddrive, and
+the charset information was stored correctly.
+
+
+Playcounts & Rating
+-------------------
+
+Whenever you play a track completely on the iPod (firmware version 1.3
+or higher) a counter in the "Play Counts" file will be increased by
+one. The same file also contains the rating you can set with the 3rd
+generation iPods.
+
+This file appears to be deleted whenever the iPod resets itself --
+e.g. because you disconnect it from the computer. Therefore, be
+careful... Charging the iPod seems to do no harm.
+
+When gtkpod is started, it will also read this file and incorporate
+the information into the iTunesDB that can be written back to the
+iPod.
+
+There have been several requests to also register playcounts when
+playing a track on the local machine. This is possible by calling
+gtkpod as "gtkpod -p <filename>".
+
+If gtkpod is already running, the playcount of that track there will
+be increased by one. If gtkpod is not already running, the playcount
+will be registered in ~/.gtkpod/offline_playcount. This file will be
+read the next time you import the iTunesDB from your iPod, and the
+playcounts will be updated accordingly.
+
+Please note that if you start several instances of gtkpod, only the
+first instance will register playcounts through "gtkpod -p".
+
+Now all you have to do is tell your favorite player to call gtkpod
+with the filename of the played track.
+
+For xmms this is possible as of July 18th, 2004 (CVS
+version). Versions before that (including 1.2.10) only allow you to
+have an external program called at the beginning of a track. Our patch
+allows to have an external program called also at the end of a track.
+
+In each case you will need to activate the "General Plugin" called
+"song_change" and configure it to call 'gtkpod -p "%f"'.
+
+
+About filenames (excerpt from the GTK2 release notes):
+------------------------------------------------------
+* The assumption of GLib and GTK+ by default is that filenames on the
+ filesystem are encoded in UTF-8 rather than the encoding of the locale;
+ The GTK+ developers consider that having filenames whose interpretation
+ depends on the current locale is fundamentally a bad idea.
+
+ If you have filenames encoded in the encoding of your locale, then
+ you may want to set the G_BROKEN_FILENAMES environment variable:
+
+ G_BROKEN_FILENAMES=1
+ export G_BROKEN_FILENAMES
+
+ Best integration of GTK+-2.0 with the environment is achieved by
+ using a UTF-8 locale.
+
+------ end of excerpt
+
+It is my feeling that many people use filenames encoded in the
+encoding of the locale. The "Add directories" dialogue already takes
+care of this and assumes the filenames to be in the same encoding as
+you have specified for the ID3 tags (see above). You can therefore
+forget about the excerpt above.
+
+However, the "Add Files" and "Add Playlists" dialogue (at the moment)
+uses the standard GTK+-2.0 file selection dialogue. Therefore I have
+no access on the conversion functions used, and a warning is printed
+when filenames are encountered that are encoded in an encoding other
+than the one of the current locale. ID3 tags are still read correctly
+(according to the charset set in the preference dialogue).
+
+
+*--------------------------------------------------*
+| |
+| Environment variables |
+| |
+*--------------------------------------------------*
+
+The following environment variables can be set if needed:
+
+IPOD_MOUNTPOINT: Defines the mountpoint of the iPod. This overwrites
+the value stored in the prefs, but is overwritten by the command line
+argument "-m" or "--mountpoint".
+
+GTKPOD_DF_COMMAND: Only used on systems without statvfs(). Defines the
+"df" command to be used for probing the free space on the iPod
+including command line arguments. Default is "df -k -P". On some
+systems it may be necessary to remove the "-P" option. The mount point
+is added to this command line automatically. You can switch off calls
+to df by setting this environment variable to an empty string.
+
+
+
+*--------------------------------------------------*
+| |
+| Icons for window managers |
+| |
+*--------------------------------------------------*
+
+Should you require an icon for your window manager you can use those
+provided in $(datadir)/pixmaps (usually
+/usr/local/share/gtkpod/pixmaps or
+/usr/share/gtkpod/pixmaps).
+
+Currently the following files are available:
+
+ gtkpod-icon-32.png
+ gtkpod-icon-32x32.png
+ gtkpod-icon-32x32-2.png
+ gtkpod-icon-48.png
+ gtkpod-icon-48x48.png
+ gtkpod-icon-64x64.png
+
+
+*--------------------------------------------------*
+| |
+| Connecting iPod to a Linux box |
+| (kernel 2.6.6) |
+| (should also work with earlier 2.6 kernels) |
+| |
+*--------------------------------------------------*
+
+This describes how to set up the iPod together with the automounter in
+kernel V2.6.6 (some minor changes in the kernel configuration may be
+necessary for older V2.6 versions).
+
+1) It appears to be possible to use HFS-formatted (Apple)
+ iPods. However, this short guide assumes you have a Windows
+ (VFAT) iPod. For conversion from HFS to VFAT please see
+
+ http://www.blinkenlights.ch/gnupod/gnupod.html#SEC6
+
+2) I'm using the following kernel configuration options (I'm only
+ using FireWire -- so the USB options are just educated
+ guesses. Please let me know if it works).
+
+ I'm not using modules, simply because what's compiled in can't fail
+ loading.
+
+ * General Setup -> Support for hot-pluggable devices - y
+ * Device Drivers -> SCSI device support - y
+ * -> SCSI device support -> SCSI disk support - y
+ * -> SCSI device support -> SCSI generic support - y
+For FireWire:
+ * -> IEEE1394 (FireWire) support - y
+ * -> IEEE1394 (FireWire) support -> OHCI-1394 support - y
+ * -> IEEE1394 (FireWire) support -> SBP-2 support - y
+For USB:
+ * -> USB support -> Support for Host-side USB - y
+ * -> EHCI HCD support - y
+ * -> OHCI HCD support - y
+ * -> UHCI HCD support - y
+ * -> USB Mass Storage support - y
+For USB and FireWire:
+ * Filesystems -> DOS/FAT/NT Filesystems - y
+ * -> DOS/FAT/NT Filesystems -> VFAT fs support - y
+ * -> Kernel automounter version 4 support - y
+ * -> Native Language Support
+ * -> Codepage 437 (CONFIG_NLS_CODEPAGE_437)
+ * -> NLS ISO 8859-1 (CONFIG_NLS_ISO8859_1)
+
+
+
+(for iPods formatted with the HFS filesystem choose
+ * Filesystems -> Miscellaneous filesystems
+ -> Apple Extended HFS filesystem support)
+
+At least for the new 4Gs and iPod minis you should _disable_
+(CONFIG_EFI_PARTITION, see Troubleshooting for more information):
+ * File Systems -> Partition Types -> Advanced Partition Selection
+ -> EFI GUID Partition support
+
+3) You need to install the following external packages:
+
+ hotplug and udev (http://linux-hotplug.sourceforge.net/)
+ autofs (ftp.kernel.org:/pub/linux/daemons/autofs)
+
+ Most likely packages are available for your distribution.
+
+4) Write rules for udev (/etc/udev/udev.rules, add at the beginning)
+ to recognize your iPod automatically (mind the spaces within
+ "iPod...", and be aware that some distributions require a double
+ equal after the BUS keyword (BUS=="scsi"...)):
+
+BUS="scsi", SYSFS{model}="iPod ", KERNEL="sd?2", NAME="%k", SYMLINK="ipod"
+
+ This will map /dev/sd?2 to /dev/ipod everytime you plug in your
+ iPod. That even works if you own more than one USB/Firewire device
+ that shows up as a harddisk, independent of the order in which you
+ connect the devices.
+
+ (You need to replace "sd?2" with "sd?1" (or maybe just "sd?") for
+ HFS formatted iPods.)
+
+ For more information on how to write udev rules please refer to
+ http://www.gamingclones.com/Howtos/udevrules.html. That document
+ gives an easy-to-understand introduction
+
+5) Set up autofs to automatically mount the iPod when you access it
+ and unmount it after 2 seconds of inactivity. In /etc/auto.master
+ add:
+
+/var/autofs/removable /etc/auto.removable --timeout=2,sync,nodev,nosuid,gid=autofs,umask=007
+
+ Adjust the gid,umask (and uid) values to whatever you need -- in this
+ example all users in the group "autofs" have read/write access, and
+ I have added all users that may access the iPod to the autofs group.
+
+ In /etc/auto.removable add
+
+ipod -fstype=vfat :/dev/ipod
+
+ (Obviously you need to change the filesystem type from 'vfat' to
+ 'hfsplus' when you use an HFS formatted iPod.)
+
+ Then simply add a link from /mnt/ipod:
+
+ ln -s /var/autofs/removable/ipod /mnt/ipod
+
+
+Now your system is configured to mount the iPod every time you access
+/mnt/ipod and to unmount it again after two seconds of inactivity. You
+won't have to worry about doing mounting/unmouting yourself any more.
+
+
+
+*--------------------------------------------------*
+| |
+| Connecting iPod to a Linux box (IEEE 1394) |
+| (kernel 2.4.21) |
+| (may also work with 2.4.20, but I didn't try) |
+| (instructions for 2.4.20 can be found below) |
+| |
+*--------------------------------------------------*
+
+1) You need a Windows iPod. See e.g.
+
+http://www.blinkenlights.ch/gnupod/gnupod.html#SEC6
+
+for information about how to convert your mac iPod to a windows iPod.
+
+Alternatively, I have received a report that Alan Cox's patches
+(2.4.21-rc8-ac1, but 2.4.21-ac1 should work as well) include hfsplus
+support. That should allow you to use hfs formatted iPods. But beware:
+hfsplus support is still beta.
+
+2) Get kernel source and configure
+Needed configuration:
+
+ * Code maturity level options - y
+ * SCSI support - y
+ * SCSI disk support - y
+ * IEEE1394 (FireWire)/IEEE 1394 (FireWire) support (Experimental) - y
+ * OHCI-1394 support - y
+ * SBP-2 support - m (important to use module -- if someone finds
+ out how to use hotplug with sbp2 compiled in, let me know)
+ (With 2.6.1 compiling sbp2 in seems to work fine.)
+At least for the new 4Gs and iPod minis you should _disable_
+(CONFIG_EFI_PARTITION, see Troubleshooting for more information):
+ * File Systems -> Partition Types -> Advanced Partition Selection
+ -> EFI GUID Partition support
+ * -> Native Language Support
+ * -> Codepage 437 (CONFIG_NLS_CODEPAGE_437)
+ * -> NLS ISO 8859-1 (CONFIG_NLS_ISO8859_1)
+
+
+3) Create /mnt/ipod:
+
+ mkdir /mnt/ipod
+
+4) Add a line to /etc/fstab. You should edit uid to match your user
+ id. Also, /dev/sda2 may not be appropriate, if you have other scsi
+ devices.
+
+/dev/sda2 /mnt/ipod vfat rw,user,noauto,noatime,errors=remount 0 0
+
+ (For HFS this line should read
+
+/dev/sda /mnt/ipod hfsplus rw,user,noauto,exec 0 0
+
+ please note that it's just '/dev/sda')
+
+
+NOTE: Some users have had problems with newer versions of mount(newer than
+mount-2.11h) The following fstab entry might work better for you.
+
+/dev/sda2 /mnt/ipod vfat rw,user,noauto,noatime,shortname=winnt 0 0
+
+5) Install the hotplug utilities
+ (http://linux-hotplug.sourceforge.net/, debian package: 'hotplug')
+
+ (If you don't want to use the hotplug utilities, you must call the
+ rescan-scsi-bus.sh (see below) by hand after loading the sbp2
+ module. This is different from 2.4.20.)
+
+5a) Add the ieee1394 hotplug support (described at
+ http://www.linux1394.org/faq.html#hotplug):
+
+ - copy ieee1394.agent to /etc/hotplug/ from
+ http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/linux-hotplug/admin/etc/hotplug/
+ - mkdir /etc/hotplug/ieee1394
+ - create /etc/hotplug/ieee1394/sbp2:
+ #!/bin/bash
+ if [ "${ACTION}" = "add" ]; then
+ . /etc/hotplug/ieee1394/rescan-scsi-bus.sh
+ else
+ . /etc/hotplug/ieee1394/rescan-scsi-bus.sh -r
+ fi
+ - chmod +rx /etc/hotplug/ieee1394/sbp2
+ - copy rescan-scsi-bus.sh to /etc/hotplug/ieee1394 from
+ http://www.garloff.de/kurt/linux/rescan-scsi-bus.sh
+ - just to be sure: restart hotplug:
+ /etc/init.d/hotplug restart
+
+6) Connect your iPod to your computer and wait until you see something
+ like the following on your system log (you can use the 'dmesg'
+ command to check).
+
+Jun 15 17:13:53 hatarakibachi kernel: ieee1394: Node 00:1023 changed to 01:1023
+Jun 15 17:13:55 hatarakibachi kernel: ieee1394: Node 01:1023 changed to 00:1023
+Jun 15 17:13:57 hatarakibachi kernel: ieee1394: sbp2: Logged into SBP-2 device
+Jun 15 17:13:57 hatarakibachi kernel: ieee1394: Device added: Node[00:1023] GUID[000a2700020680b5] [Apple Computer, Inc.]
+Jun 15 17:13:57 hatarakibachi kernel: ieee1394: Node 00:1023 changed to 01:1023
+Jun 15 17:13:57 hatarakibachi kernel: scsi singledevice 0 0 0 0
+Jun 15 17:13:57 hatarakibachi kernel: Vendor: Apple Model: iPod Rev: 1.30
+Jun 15 17:13:57 hatarakibachi kernel: Type: Direct-Access ANSI SCSI revision: 02
+Jun 15 17:13:57 hatarakibachi kernel: Attached scsi removable disk sda at scsi0, channel 0, id 0, lun 0
+Jun 15 17:13:57 hatarakibachi kernel: SCSI device sda: 39062520 512-byte hdwr sectors (20000 MB)
+Jun 15 17:13:57 hatarakibachi kernel: sda: test WP failed, assume Write Enabled
+Jun 15 17:13:58 hatarakibachi kernel: sda: sda1 sda2
+Jun 15 17:13:58 hatarakibachi kernel: scsi singledevice 0 0 1 0
+...
+
+7) Mount the iPod hard drive
+
+ mount /mnt/ipod
+
+8) do whatever you need to do (e.g. start gtkpod, see below)
+
+9) Unmount the iPod:
+
+ umount /mnt/ipod
+
+10) Unload the module sbp2 (as most likely as root):
+
+ rmmod sbp2
+
+11) Disconnect the iPod from your computer (ignore the "Do not
+ disconnect" message -- as long as you wait for the 'unmount' to
+ command to finish properly, everything should be fine).
+
+
+
+*--------------------------------------------------*
+| |
+| Connecting iPod to a Linux box using IEEE 1394 |
+| (kernel 2.4.20) |
+| (connecting to 2.4.21 seems to work slightly |
+| differently -- see above) |
+| |
+*--------------------------------------------------*
+
+1) You need a Windows iPod. See e.g.
+
+http://www.blinkenlights.ch/gnupod/gnupod.html#SEC6
+
+for information about how to convert your mac iPod to a windows iPod.
+
+Alternatively, I have received a report that Alan Cox's patches
+(2.4.21-rc8-ac1, but 2.4.21-ac1 should work as well) include hfsplus
+support. That should allow you to use hfs formatted iPods. But beware:
+hfsplus support is still beta.
+
+2) Get kernel source and configure
+Needed configuration:
+
+ * Code maturity level options - y
+ * SCSI support - y
+ * SCSI disk support - m
+ * IEEE1394 (FireWire)/IEEE 1394 (FireWire) support (Experimental) - y
+ * OHCI-1394 support - y
+ * SBP-2 support - m
+At least for the new 4Gs and iPod minis you should _disable_
+(CONFIG_EFI_PARTITION, see Troubleshooting for more information):
+ * File Systems -> Partition Types -> Advanced Partition Selection
+ * -> EFI GUID Partition support
+ * -> Native Language Support
+ * -> Codepage 437 (CONFIG_NLS_CODEPAGE_437)
+ * -> NLS ISO 8859-1 (CONFIG_NLS_ISO8859_1)
+
+3) Create /mnt/ipod:
+
+ mkdir /mnt/ipod
+
+4) Add a line to /etc/fstab. You should edit uid to match your user
+ id. Also, /dev/sda2 may not be appropriate, if you have other scsi
+ devices.
+
+/dev/sda2 /mnt/ipod vfat rw,user,noauto,noatime 0 0
+
+ (For HFS this line should read
+
+/dev/sda /mnt/ipod hfsplus rw,user,noauto,exec 0 0
+
+ please note that it's just '/dev/sda')
+
+
+NOTE: Some users have had problems with newer versions of mount(newer than
+mount-2.11h) The following fstab entry might work better for you.
+
+/dev/sda2 /mnt/ipod vfat rw,user,noauto,noatime,shortname=winnt 0 0
+
+NOTE: You can add ",umask=0" to the options to make the iPod
+readable/writable for all users.
+
+5) Connect your iPod to your computer and wait until you see something
+ like the following on your system log (you can use the 'dmesg'
+ command to check).
+
+Nov 28 21:58:06 hatarakibachi kernel: ieee1394: Node 00:1023 changed to 01:1023
+Nov 28 21:58:09 hatarakibachi kernel: ieee1394: Node 01:1023 changed to 00:1023
+Nov 28 21:58:12 hatarakibachi kernel: ieee1394: NodeMgr: hotplug policy returned -2
+Nov 28 21:58:12 hatarakibachi kernel: ieee1394: Device added: Node[00:1023] GUID[000a2700020680b5] [Apple Computer, Inc.]
+Nov 28 21:58:12 hatarakibachi kernel: ieee1394: Node 00:1023 changed to 01:1023
+
+6) Load the sbp2 module (most likely as root):
+
+ modprobe sbp2
+
+ You should see something like the following on your system log:
+
+Nov 28 21:58:38 hatarakibachi kernel: ieee1394: sbp2: Logged into SBP-2 device
+Nov 28 21:58:38 hatarakibachi kernel: scsi0 : IEEE-1394 SBP-2 protocol driver (host: ohci1394)
+Nov 28 21:58:38 hatarakibachi kernel: $Rev$ James Goodwin <jamesg at filanet.com>
+Nov 28 21:58:38 hatarakibachi kernel: SBP-2 module load options:
+Nov 28 21:58:38 hatarakibachi kernel: - Max speed supported: S400
+Nov 28 21:58:38 hatarakibachi kernel: - Max sectors per I/O supported: 255
+Nov 28 21:58:38 hatarakibachi kernel: - Max outstanding commands supported: 8
+Nov 28 21:58:38 hatarakibachi kernel: - Max outstanding commands per lun supported: 1
+Nov 28 21:58:38 hatarakibachi kernel: - Serialized I/O (debug): no
+Nov 28 21:58:38 hatarakibachi kernel: - Exclusive login: yes
+Nov 28 21:58:38 hatarakibachi kernel: Vendor: Apple Model: iPod Rev: 1.21
+Nov 28 21:58:38 hatarakibachi kernel: Type: Direct-Access ANSI SCSI revision: 02
+Nov 28 21:58:38 hatarakibachi kernel: Attached scsi removable disk sda at scsi0, channel 0, id 0, lun 0
+Nov 28 21:58:38 hatarakibachi kernel: SCSI device sda: 39062520 512-byte hdwr sectors (20000 MB)
+Nov 28 21:58:38 hatarakibachi kernel: sda: test WP failed, assume Write Enabled
+Nov 28 21:58:39 hatarakibachi kernel: sda: sda1 sda2
+
+7) Mount the iPod hard drive
+
+ mount /mnt/ipod
+
+8) do whatever you need to do (e.g. start gtkpod, see below)
+
+9) Unmount the iPod:
+
+ umount /mnt/ipod
+
+10) Unload the module sbp2 (as most likely as root):
+
+ rmmod sbp2
+
+11) Disconnect the iPod from your computer.
+
+
+*--------------------------------------------------*
+| |
+| Connecting iPod to a Linux box (USB) |
+| |
+*--------------------------------------------------*
+
+I don't have much information about this so far (I don't own a third
+generation iPod). Please help me to fill in the gaps.
+
+Stephen Drye sent me the following note:
+
+"I've figured out how to get a USB-connected iPod recognized...:
+
+The trick to it is that you have to
+
+- plug the iPod in
+
+- it'll fail to be recognized by the SCSI subsystem
+
+- now, even though your ipod says not to, unplug the USB cord and
+ immediately plug it back in.
+
+- since the iPod's hdd was already spun up, the SCSI subsystem now
+ recognizes it and mounts it as /dev/sda
+
+- You can then mount /dev/sda2 to /mnt/ipod as normal."
+
+On the other hand: with my 4G iPod under 2.6.9 and 2.6.10 I never had
+any problem whatsoever getting the iPod to work. With IEEE it was
+awful (would work some times, would not some other time).
+
+
+*----------------------------------*
+| |
+| Sick of loading the sbp2 |
+| modules by hand? |
+| |
+| Corey Donohoe |
+| <atmos at atmos dot org> |
+| March 22nd 2003 |
+| |
+*----------------------------------*
+
+Sick of loading the sbp2 modules by hand every time you want to use your
+ipod? Are you sick of mounting it too? Using sudo gtkpod can make manually
+interacting with the ipod filesystem a thing of the past. Note that you
+should have your ipod working with gtkpod before attempting this automated
+method, see the README that came with gtkpod in order to get things up and
+running.
+
+Here's a brief example of how I'm using gtkpod now in 8 easy steps.
+
+(Remark: the hotplug facility of new kernels can also load and unload
+the sbp2 module for you.)
+
+/**********/
+ * Step 1 *
+/**********/
+Using sudo allow users to load/remove the sbp2 module
+Example /etc/sudoers
+------------------------------- Begin Here ---------------------------------
+
+# Cmnd alias specification
+Cmnd_Alias IPOD=/sbin/modprobe sbp2 sbp2_force_inquiry_hack=1, /sbin/rmmod sbp2
+# User privilege specification
+atmos ALL=(ALL) ALL
+atmos ALL= NOPASSWD : IPOD
+
+------------------------------- End Here -----------------------------------
+I use the force inquiry hack cause I have an older iPod, if you normally can
+get by with /sbin/modprobe sbp2 then ignore the inquiry hack stuff. Note
+that explicitly specifying which module to probe/remove keeps the user from
+being able to add/remove arbitrary modules. This allows us to keep gtkpod
+as a user process, and execute commands the user wouldn't usually have
+enough rights to.
+
+/**********/
+ * Step 2 *
+/**********/
+Add a line similar to the below to your /etc/fstab, this will enable users
+to mount the ipod with read/write capabilities. Example line assumes your
+ipod mount point is /mnt/ipod and your ipod is detected as /dev/sda
+
+------------------------------- Begin Here ---------------------------------
+/dev/sda2 /mnt/ipod vfat rw,user,noauto 0 0
+------------------------------- End Here -----------------------------------
+
+
+/**********/
+ * Step 3 *
+/**********/
+Then setup your /etc/gtkpod/gtkpod.in file to load the module when gtkpod is
+started.
+Example /etc/gtkpod/gtkpod.in
+------------------------------- Begin Here ---------------------------------
+
+sudo /sbin/modprobe sbp2 sbp2_force_inquiry_hack=1
+
+------------------------------- End Here -----------------------------------
+
+/**********/
+ * Step 4 *
+/**********/
+
+Then setup your /etc/gtkpod/gtkpod.out file to unload the module when gtkpod
+is exited.
+Example /etc/gtkpod/gtkpod.out
+------------------------------- Begin Here ---------------------------------
+
+sudo /sbin/rmmod sbp2
+
+------------------------------- End Here -----------------------------------
+
+/**********/
+ * Step 5 *
+/**********/
+Then enable ipod automounting in the gtkpod prefs(in the misc tab).
+
+/**********/
+ * Step 6 *
+/**********/
+You're now ready to use gtkpod in a much nicer fashion. Start by
+plugging in your ipod. You should get a check mark with "OK to disconnect"
+displayed on your ipod.
+
+/**********/
+ * Step 7 *
+/**********/
+Start gtkpod, your ipod should be accessible(i.e. autoimport should work)
+A "Do Not Disconnect" message is displayed on your ipod while gtkpod is
+running.
+
+/**********/
+ * Step 8 *
+/**********/
+After you exit gtkpod, the "OK to disconnect" message should be displayed
+again. It's ok to unplug your ipod now.
+
+Good Luck.
+
+
+
+*----------------------------------*
+| |
+| Known bugs |
+| |
+*----------------------------------*
+
+
+- Display of large number of tracks is awfully slow (mainly because of
+ the use of the standard GTK2 tree views) -> deactivate "Automatically
+ select "All" in first filter tab" and/or deactivate "Automatically
+ select master playlist". You could also "block the display" to speed
+ up the display update. Further, decreasing the window size
+ considerably speeds up the display.
+
+ I also want to point out that updating the info window takes up a
+ considerable amount of time. Update may become more intelligent in
+ the future -- until then close the info window for more speed.
+
+- When changing selections in the filter tabs while importing the
+ iTunesDB, sometimes the interface freezes. I tried to track this
+ problem down but only found out that gtk+ does not return control
+ back to gtkpod. Selecting the "All" filter tabs seems to unfreeze the
+ interface again.
Deleted: gtkpod/tags/0.99.10-5/debian/NEWS
===================================================================
--- gtkpod/trunk/debian/NEWS 2007-11-13 14:54:03 UTC (rev 259)
+++ gtkpod/tags/0.99.10-5/debian/NEWS 2007-11-20 13:46:35 UTC (rev 280)
@@ -1,9 +0,0 @@
-gtkpod (0.85.0-1) unstable; urgency=low
-
- * I have changed the default configuration of gtkpod to
- use the mount point /media/ipod instead of /mnt/ipod.
- You may have to change either your gtkpod configuration
- or your /etc/fstab to get gtkpod working correctly again.
-
- -- Frank Lichtenheld <djpig at debian.org> Fri, 10 Dec 2004 02:04:02 +0100
-
Deleted: gtkpod/tags/0.99.10-5/debian/changelog
===================================================================
--- gtkpod/trunk/debian/changelog 2007-11-13 14:54:03 UTC (rev 259)
+++ gtkpod/tags/0.99.10-5/debian/changelog 2007-11-20 13:46:35 UTC (rev 280)
@@ -1,213 +0,0 @@
-gtkpod (0.99.10-3) unstable; urgency=low
-
- * Added missing fclose() call in mp3file.c to prevent too many open
- file descriptors (Closes: #441308).
- * Adapted .desktop file to current freedesktop standards.
-
- -- Nico Golde <nion at debian.org> Sun, 09 Sep 2007 20:13:31 +0200
-
-gtkpod (0.99.10-2) unstable; urgency=low
-
- * Upload to unstable
- * Update menu entry according to new menu policy
- * Lintian: Don't ignore all errors from "make distclean"
-
- -- Frank Lichtenheld <djpig at debian.org> Tue, 10 Jul 2007 00:25:04 +0200
-
-gtkpod (0.99.10-1) experimental; urgency=low
-
- * New upstream release
- - Allows resizing the preferences dialog (Closes: #428011)
- * Update man page debian/gtkpod.pod
-
- -- Frank Lichtenheld <djpig at debian.org> Thu, 28 Jun 2007 02:12:56 +0200
-
-gtkpod (0.99.8-3) unstable; urgency=low
-
- [ Frank Lichtenheld ]
- * Upload to unstable (Closes: #391812)
- * Change Maintainer to pkg-gtkpod-devel list. Add myself
- and Nico as Uploaders
- * Add Vcs-{Svn,Browser} fields
-
- [ Nico Golde ]
- * Added Homepage tag to control.
- * Bumped compat level since debhelper >= 5 is in etch.
-
- -- Nico Golde <nion at debian.org> Mon, 07 May 2007 17:40:39 +0200
-
-gtkpod (0.99.8-2) experimental; urgency=low
-
- * Adapt for libgpod >= 0.4.2 (Patch by upstream).
-
- -- Frank Lichtenheld <djpig at debian.org> Sat, 10 Feb 2007 14:22:53 +0100
-
-gtkpod (0.99.8-1) experimental; urgency=low
-
- * New upstream release
- + Update libgpod-dev build-dependency to (>= 0.4.0)
- and remove conflict against libgpod0
- (upload to experimental because this version isn't
- available in unstable yet)
- + Change /mnt/ipod to /media/ipod as usual in new scripts
- * Bump Standards-Version to 3.7.2 (no changes).
- * Remove glade file symlinks on clean. Found by Martin Zobel-Helas.
- (Closes: #395120)
-
- -- Frank Lichtenheld <djpig at debian.org> Fri, 22 Dec 2006 18:38:05 +0100
-
-gtkpod (0.99.4-2) unstable; urgency=low
-
- * Add conflict against libgpod0 >= 0.4.0
- to quiten up the BTS a bit.
- * Bump Standards-Version to 3.7.2 (no changes).
- * Remove glade file symlinks on clean. Found by Martin Zobel-Helas.
- (Closes: #395120)
-
- -- Frank Lichtenheld <djpig at debian.org> Thu, 30 Nov 2006 23:12:32 +0100
-
-gtkpod (0.99.4-1) unstable; urgency=low
-
- * New upstream release
-
- -- Frank Lichtenheld <djpig at debian.org> Sat, 8 Apr 2006 21:45:22 +0200
-
-gtkpod (0.99.2-1) unstable; urgency=low
-
- * New upstream release (Closes: #343856)
- + Fixes sorting bug (Closes: #330082)
- * Add build-depends on libgpod-dev
- * Add build-depends on flex
- * Add suggests on python since one of the scripts uses it
- * Update FSF address in debian/copyright
-
- -- Frank Lichtenheld <djpig at debian.org> Thu, 29 Dec 2005 17:38:38 +0100
-
-gtkpod (0.94.0-1) unstable; urgency=low
-
- * New upstream release (Closes: #319408)
- - support for new iTunes and new firmware version
- (Closes: #317701)
- * Add watch file, by Filippo Giunchedi (Closes: #318760)
-
- -- Frank Lichtenheld <djpig at debian.org> Fri, 22 Jul 2005 13:23:13 +0200
-
-gtkpod (0.93.1-1) unstable; urgency=low
-
- * New upstream release (Closes: #316399)
- - New build-dependency libglade2-dev
- * Bump Standards-Version to 3.6.2, no changes needed
- * Don't create glade files as absolute links as that fails miserably
- in a packaging situation
-
- -- Frank Lichtenheld <djpig at debian.org> Fri, 1 Jul 2005 02:24:13 +0200
-
-gtkpod (0.88.2-1) unstable; urgency=low
-
- * New upstream release
- - Fixes typo in preferences dialog reported by Michael Shields
- (Closes: #289087)
- - Included additional sync script previously offered for
- download separatly (Closes: #302361)
- * Include typo fixes for the German translation by Jens Seidel
- (Closes: #314053)
- * Add build dependency on gettext even though many other build
- dependecies already get it for us. We shouldn't rely on that
- * Fix syntax error in sync-notes.sh and change paths from
- /mnt/ipod to /media/ipod as usual
- * Add Suggests on recode as it is used in the scripts
- * Replace the outdated, buggy, and GFDL licensed man page written in
- docbook by the former Debian maintainer with an updated, more
- extensive, GPL licensed version written in POD by me. Replace
- build-depends on docbook-to-man by build-depends on perl.
- * Rework copyright file to be more precise about which file is
- copyrighted by whom
- * Fix path to scripts in preferences window
- * Replace ScsiEject code in src/misc.c with my new version from the
- eject package which uses the newer SG ioctl interface. Add new
- header check for scsi/sg.h to configure.in and regenerate configure
- and config.h.in.
-
- -- Frank Lichtenheld <djpig at debian.org> Thu, 16 Jun 2005 18:28:41 +0200
-
-gtkpod (0.88.1-1) unstable; urgency=low
-
- * New upstream release
- - fixes the iPod Shuffle support (Closes: #299768)
- Thanks to Jörg Kurlbaum for pointing this out
-
- -- Frank Lichtenheld <djpig at debian.org> Fri, 18 Mar 2005 13:15:17 +0100
-
-gtkpod (0.88-1) unstable; urgency=low
-
- * New upstream version (Closes: #299053)
- * Fix FTBFS with gcc-4.0; patch by Andreas Jochens
- (Closes: #298273)
-
- -- Frank Lichtenheld <djpig at debian.org> Fri, 11 Mar 2005 18:50:52 +0100
-
-gtkpod (0.87.3-1) unstable; urgency=low
-
- * New upstream version
-
- -- Frank Lichtenheld <djpig at debian.org> Fri, 4 Mar 2005 14:35:13 -0800
-
-gtkpod (0.85.0-1) unstable; urgency=low
-
- * New maintainer (Closes: #287988)
- Acknowledge my own NMU (Closes: #264682, #268340, #230898, #275363)
- * Apply patch by Andreas Jochens to let gtkpod compile
- with gcc-4.0 (Closes: #286926)
-
- -- Frank Lichtenheld <djpig at debian.org> Fri, 7 Jan 2005 01:01:58 +0100
-
-gtkpod (0.85.0-0.1) unstable; urgency=low
-
- * NMU since maintainer is unresponsive to any contact
- attempts for a log time now.
- * New upstream release (Closes: #264682)
- * debian/control:
- + Shorten short description (Closes: #268340)
- + Suggest mp3gain (Closes: #230898)
- + Adjust debhelper build-dependency so that we can use dh_desktop
- * debian/rules: Tidy up.
- * debian/docs: Don't install empty NEWS file
- * debian/menu:
- + Quote values
- + Use xpm icon created from the 32x32 icon
- * debian/gtkpod.sgml: fix some <arg> vs. <option> mistakes
- * debian/gtkpod.desktop: add .desktop file
- * Change all occourences of /mnt/ipod to /media/ipod (Closes: #275363)
- add a NEWS.Debian file to document this.
- * Fix UTF-8 characters in several files
- * Don't issue warning about not beeing able to "unsort" a table.
- It's quite annyoing and the user has no possibility to fix it.
-
- -- Frank Lichtenheld <djpig at debian.org> Thu, 9 Dec 2004 18:17:17 +0100
-
-gtkpod (0.72-2-2) unstable; urgency=low
-
- * Fix build dependencies (libid3tag0-dev).
- * Change priority to extra.
-
- -- Quôc Peyrot <chojin at debian.org> Sat, 7 Feb 2004 05:14:03 +0000
-
-gtkpod (0.72-2-1) unstable; urgency=low
-
- * New upstream release. Closes: #216155.
- * Update policy revision to 3.6.1 (use UTF-8).
- * Change the debian maintainer email to chojin at debian.org.
-
- -- Quôc Peyrot <chojin at debian.org> Tue, 3 Feb 2004 07:15:04 +0000
-
-gtkpod (0.51-1) unstable; urgency=low
-
- * New upstream release
-
- -- Quôc Peyrot <chojin at debian.org> Sat, 17 May 2003 04:15:02 +0000
-
-gtkpod (0.50-1) unstable; urgency=low
-
- * Initial Release. Closes: #182289.
-
- -- Quôc Peyrot <chojin at debian.org> Tue, 22 Apr 2003 05:16:37 +0000
Copied: gtkpod/tags/0.99.10-5/debian/changelog (from rev 279, gtkpod/trunk/debian/changelog)
===================================================================
--- gtkpod/tags/0.99.10-5/debian/changelog (rev 0)
+++ gtkpod/tags/0.99.10-5/debian/changelog 2007-11-20 13:46:35 UTC (rev 280)
@@ -0,0 +1,234 @@
+gtkpod (0.99.10-5) unstable; urgency=low
+
+ * Add changing mountpoint as well in prefs.c
+ to 01_mountpoint (Closes: #452056).
+ * Removed NEWS file as its last entry was before sarge.
+
+ -- Nico Golde <nion at debian.org> Tue, 20 Nov 2007 14:22:12 +0100
+
+gtkpod (0.99.10-4) unstable; urgency=low
+
+ * Switched from Xs-Vcs to Vcs control field, dpkg supports them now.
+ * Switched from old Homepage tag to the new Homepage control field.
+ * New dependency on dpatch as we don't want to modify the source
+ directly any longer.
+ * Added previously modified source code as dpatch patches:
+ 01_mountpoint, 02_missing_fclose
+ * Included 03_itdb-set-local-to-imported.dpatch to fix inability to import
+ into local repos (Closes: #451749).
+
+ -- Nico Golde <nion at debian.org> Tue, 13 Nov 2007 16:18:58 +0100
+
+gtkpod (0.99.10-3) unstable; urgency=low
+
+ * Added missing fclose() call in mp3file.c to prevent too many open
+ file descriptors (Closes: #441308).
+ * Adapted .desktop file to current freedesktop standards.
+
+ -- Nico Golde <nion at debian.org> Sun, 09 Sep 2007 20:13:31 +0200
+
+gtkpod (0.99.10-2) unstable; urgency=low
+
+ * Upload to unstable
+ * Update menu entry according to new menu policy
+ * Lintian: Don't ignore all errors from "make distclean"
+
+ -- Frank Lichtenheld <djpig at debian.org> Tue, 10 Jul 2007 00:25:04 +0200
+
+gtkpod (0.99.10-1) experimental; urgency=low
+
+ * New upstream release
+ - Allows resizing the preferences dialog (Closes: #428011)
+ * Update man page debian/gtkpod.pod
+
+ -- Frank Lichtenheld <djpig at debian.org> Thu, 28 Jun 2007 02:12:56 +0200
+
+gtkpod (0.99.8-3) unstable; urgency=low
+
+ [ Frank Lichtenheld ]
+ * Upload to unstable (Closes: #391812)
+ * Change Maintainer to pkg-gtkpod-devel list. Add myself
+ and Nico as Uploaders
+ * Add Vcs-{Svn,Browser} fields
+
+ [ Nico Golde ]
+ * Added Homepage tag to control.
+ * Bumped compat level since debhelper >= 5 is in etch.
+
+ -- Nico Golde <nion at debian.org> Mon, 07 May 2007 17:40:39 +0200
+
+gtkpod (0.99.8-2) experimental; urgency=low
+
+ * Adapt for libgpod >= 0.4.2 (Patch by upstream).
+
+ -- Frank Lichtenheld <djpig at debian.org> Sat, 10 Feb 2007 14:22:53 +0100
+
+gtkpod (0.99.8-1) experimental; urgency=low
+
+ * New upstream release
+ + Update libgpod-dev build-dependency to (>= 0.4.0)
+ and remove conflict against libgpod0
+ (upload to experimental because this version isn't
+ available in unstable yet)
+ + Change /mnt/ipod to /media/ipod as usual in new scripts
+ * Bump Standards-Version to 3.7.2 (no changes).
+ * Remove glade file symlinks on clean. Found by Martin Zobel-Helas.
+ (Closes: #395120)
+
+ -- Frank Lichtenheld <djpig at debian.org> Fri, 22 Dec 2006 18:38:05 +0100
+
+gtkpod (0.99.4-2) unstable; urgency=low
+
+ * Add conflict against libgpod0 >= 0.4.0
+ to quiten up the BTS a bit.
+ * Bump Standards-Version to 3.7.2 (no changes).
+ * Remove glade file symlinks on clean. Found by Martin Zobel-Helas.
+ (Closes: #395120)
+
+ -- Frank Lichtenheld <djpig at debian.org> Thu, 30 Nov 2006 23:12:32 +0100
+
+gtkpod (0.99.4-1) unstable; urgency=low
+
+ * New upstream release
+
+ -- Frank Lichtenheld <djpig at debian.org> Sat, 8 Apr 2006 21:45:22 +0200
+
+gtkpod (0.99.2-1) unstable; urgency=low
+
+ * New upstream release (Closes: #343856)
+ + Fixes sorting bug (Closes: #330082)
+ * Add build-depends on libgpod-dev
+ * Add build-depends on flex
+ * Add suggests on python since one of the scripts uses it
+ * Update FSF address in debian/copyright
+
+ -- Frank Lichtenheld <djpig at debian.org> Thu, 29 Dec 2005 17:38:38 +0100
+
+gtkpod (0.94.0-1) unstable; urgency=low
+
+ * New upstream release (Closes: #319408)
+ - support for new iTunes and new firmware version
+ (Closes: #317701)
+ * Add watch file, by Filippo Giunchedi (Closes: #318760)
+
+ -- Frank Lichtenheld <djpig at debian.org> Fri, 22 Jul 2005 13:23:13 +0200
+
+gtkpod (0.93.1-1) unstable; urgency=low
+
+ * New upstream release (Closes: #316399)
+ - New build-dependency libglade2-dev
+ * Bump Standards-Version to 3.6.2, no changes needed
+ * Don't create glade files as absolute links as that fails miserably
+ in a packaging situation
+
+ -- Frank Lichtenheld <djpig at debian.org> Fri, 1 Jul 2005 02:24:13 +0200
+
+gtkpod (0.88.2-1) unstable; urgency=low
+
+ * New upstream release
+ - Fixes typo in preferences dialog reported by Michael Shields
+ (Closes: #289087)
+ - Included additional sync script previously offered for
+ download separatly (Closes: #302361)
+ * Include typo fixes for the German translation by Jens Seidel
+ (Closes: #314053)
+ * Add build dependency on gettext even though many other build
+ dependecies already get it for us. We shouldn't rely on that
+ * Fix syntax error in sync-notes.sh and change paths from
+ /mnt/ipod to /media/ipod as usual
+ * Add Suggests on recode as it is used in the scripts
+ * Replace the outdated, buggy, and GFDL licensed man page written in
+ docbook by the former Debian maintainer with an updated, more
+ extensive, GPL licensed version written in POD by me. Replace
+ build-depends on docbook-to-man by build-depends on perl.
+ * Rework copyright file to be more precise about which file is
+ copyrighted by whom
+ * Fix path to scripts in preferences window
+ * Replace ScsiEject code in src/misc.c with my new version from the
+ eject package which uses the newer SG ioctl interface. Add new
+ header check for scsi/sg.h to configure.in and regenerate configure
+ and config.h.in.
+
+ -- Frank Lichtenheld <djpig at debian.org> Thu, 16 Jun 2005 18:28:41 +0200
+
+gtkpod (0.88.1-1) unstable; urgency=low
+
+ * New upstream release
+ - fixes the iPod Shuffle support (Closes: #299768)
+ Thanks to Jörg Kurlbaum for pointing this out
+
+ -- Frank Lichtenheld <djpig at debian.org> Fri, 18 Mar 2005 13:15:17 +0100
+
+gtkpod (0.88-1) unstable; urgency=low
+
+ * New upstream version (Closes: #299053)
+ * Fix FTBFS with gcc-4.0; patch by Andreas Jochens
+ (Closes: #298273)
+
+ -- Frank Lichtenheld <djpig at debian.org> Fri, 11 Mar 2005 18:50:52 +0100
+
+gtkpod (0.87.3-1) unstable; urgency=low
+
+ * New upstream version
+
+ -- Frank Lichtenheld <djpig at debian.org> Fri, 4 Mar 2005 14:35:13 -0800
+
+gtkpod (0.85.0-1) unstable; urgency=low
+
+ * New maintainer (Closes: #287988)
+ Acknowledge my own NMU (Closes: #264682, #268340, #230898, #275363)
+ * Apply patch by Andreas Jochens to let gtkpod compile
+ with gcc-4.0 (Closes: #286926)
+
+ -- Frank Lichtenheld <djpig at debian.org> Fri, 7 Jan 2005 01:01:58 +0100
+
+gtkpod (0.85.0-0.1) unstable; urgency=low
+
+ * NMU since maintainer is unresponsive to any contact
+ attempts for a log time now.
+ * New upstream release (Closes: #264682)
+ * debian/control:
+ + Shorten short description (Closes: #268340)
+ + Suggest mp3gain (Closes: #230898)
+ + Adjust debhelper build-dependency so that we can use dh_desktop
+ * debian/rules: Tidy up.
+ * debian/docs: Don't install empty NEWS file
+ * debian/menu:
+ + Quote values
+ + Use xpm icon created from the 32x32 icon
+ * debian/gtkpod.sgml: fix some <arg> vs. <option> mistakes
+ * debian/gtkpod.desktop: add .desktop file
+ * Change all occourences of /mnt/ipod to /media/ipod (Closes: #275363)
+ add a NEWS.Debian file to document this.
+ * Fix UTF-8 characters in several files
+ * Don't issue warning about not beeing able to "unsort" a table.
+ It's quite annyoing and the user has no possibility to fix it.
+
+ -- Frank Lichtenheld <djpig at debian.org> Thu, 9 Dec 2004 18:17:17 +0100
+
+gtkpod (0.72-2-2) unstable; urgency=low
+
+ * Fix build dependencies (libid3tag0-dev).
+ * Change priority to extra.
+
+ -- Quôc Peyrot <chojin at debian.org> Sat, 7 Feb 2004 05:14:03 +0000
+
+gtkpod (0.72-2-1) unstable; urgency=low
+
+ * New upstream release. Closes: #216155.
+ * Update policy revision to 3.6.1 (use UTF-8).
+ * Change the debian maintainer email to chojin at debian.org.
+
+ -- Quôc Peyrot <chojin at debian.org> Tue, 3 Feb 2004 07:15:04 +0000
+
+gtkpod (0.51-1) unstable; urgency=low
+
+ * New upstream release
+
+ -- Quôc Peyrot <chojin at debian.org> Sat, 17 May 2003 04:15:02 +0000
+
+gtkpod (0.50-1) unstable; urgency=low
+
+ * Initial Release. Closes: #182289.
+
+ -- Quôc Peyrot <chojin at debian.org> Tue, 22 Apr 2003 05:16:37 +0000
Deleted: gtkpod/tags/0.99.10-5/debian/control
===================================================================
--- gtkpod/trunk/debian/control 2007-11-13 14:54:03 UTC (rev 259)
+++ gtkpod/tags/0.99.10-5/debian/control 2007-11-20 13:46:35 UTC (rev 280)
@@ -1,22 +0,0 @@
-Source: gtkpod
-Section: sound
-Priority: extra
-Maintainer: gtkpod Maintainers <pkg-gtkpod-devel at lists.alioth.debian.org>
-Uploaders: Frank Lichtenheld <djpig at debian.org>, Nico Golde <nion at debian.org>
-Build-Depends: debhelper (>= 5), gettext, flex, autotools-dev, perl, libxml-parser-perl, libgtk2.0-dev, libglade2-dev, libgnomecanvas2-dev, libgnomevfs2-dev, libid3tag0-dev, libvorbis-dev, libflac-dev, libgpod-dev (>= 0.5.2), libcurl4-gnutls-dev, libhal-dev
-Standards-Version: 3.7.2
-XS-Vcs-Svn: svn://svn.debian.org/svn/pkg-gtkpod/gtkpod/trunk
-XS-Vcs-Browser: http://svn.debian.org/wsvn/pkg-gtkpod/gtkpod/trunk
-
-Package: gtkpod
-Architecture: any
-Depends: ${shlibs:Depends}
-Suggests: mp3gain, recode, python
-Description: manage songs and playlists on an Apple iPod
- gtkpod is a platform independent GUI for Apple's iPod using GTK2. It
- allows you to upload songs and playlists to your iPod. It supports ID3
- tag editing, multiple charsets for ID3 tags, detects duplicate songs,
- allows offline modification of the database with later synchronisation,
- and more.
- .
- Homepage: http://www.gtkpod.org
Copied: gtkpod/tags/0.99.10-5/debian/control (from rev 265, gtkpod/trunk/debian/control)
===================================================================
--- gtkpod/tags/0.99.10-5/debian/control (rev 0)
+++ gtkpod/tags/0.99.10-5/debian/control 2007-11-20 13:46:35 UTC (rev 280)
@@ -0,0 +1,21 @@
+Source: gtkpod
+Section: sound
+Priority: extra
+Maintainer: gtkpod Maintainers <pkg-gtkpod-devel at lists.alioth.debian.org>
+Uploaders: Frank Lichtenheld <djpig at debian.org>, Nico Golde <nion at debian.org>
+Build-Depends: debhelper (>= 5), gettext, flex, autotools-dev, perl, libxml-parser-perl, libgtk2.0-dev, libglade2-dev, libgnomecanvas2-dev, libgnomevfs2-dev, libid3tag0-dev, libvorbis-dev, libflac-dev, libgpod-dev (>= 0.5.2), libcurl4-gnutls-dev, libhal-dev, dpatch
+Standards-Version: 3.7.2
+Homepage: http://www.gtkpod.org
+Vcs-Svn: svn://svn.debian.org/svn/pkg-gtkpod/gtkpod/trunk
+Vcs-Browser: http://svn.debian.org/wsvn/pkg-gtkpod/gtkpod/trunk
+
+Package: gtkpod
+Architecture: any
+Depends: ${shlibs:Depends}
+Suggests: mp3gain, recode, python
+Description: manage songs and playlists on an Apple iPod
+ gtkpod is a platform independent GUI for Apple's iPod using GTK2. It
+ allows you to upload songs and playlists to your iPod. It supports ID3
+ tag editing, multiple charsets for ID3 tags, detects duplicate songs,
+ allows offline modification of the database with later synchronisation,
+ and more.
Copied: gtkpod/tags/0.99.10-5/debian/patches (from rev 274, gtkpod/trunk/debian/patches)
Deleted: gtkpod/tags/0.99.10-5/debian/patches/01_mountpoint.dpatch
===================================================================
--- gtkpod/trunk/debian/patches/01_mountpoint.dpatch 2007-11-19 17:26:24 UTC (rev 274)
+++ gtkpod/tags/0.99.10-5/debian/patches/01_mountpoint.dpatch 2007-11-20 13:46:35 UTC (rev 280)
@@ -1,276 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## 01_mountpoint.dpatch by Nico Golde <nion at debian.org>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: No description.
-
- at DPATCH@
-diff -urNad trunk~/README trunk/README
---- trunk~/README 2007-11-18 16:47:22.000000000 +0100
-+++ trunk/README 2007-11-18 16:48:21.000000000 +0100
-@@ -52,7 +52,7 @@
- 1) If your iPod is not mounted automatically when connecting it to
- your computer follow steps 1-7 in the "Connecting your iPod to a
- Linux box" (basically you need to get the iPod partition mounted to
-- /mnt/ipod). In most cases this should not be necessary any more
-+ /media/ipod). In most cases this should not be necessary any more
- these days.
-
- 2) If you are using GNOME, starting with V1.0 of gtkpod your iPod will
-@@ -699,13 +699,13 @@
- (Obviously you need to change the filesystem type from 'vfat' to
- 'hfsplus' when you use an HFS formatted iPod.)
-
-- Then simply add a link from /mnt/ipod:
-+ Then simply add a link from /media/ipod:
-
-- ln -s /var/autofs/removable/ipod /mnt/ipod
-+ ln -s /var/autofs/removable/ipod /media/ipod
-
-
- Now your system is configured to mount the iPod every time you access
--/mnt/ipod and to unmount it again after two seconds of inactivity. You
-+/media/ipod and to unmount it again after two seconds of inactivity. You
- won't have to worry about doing mounting/unmouting yourself any more.
-
-
-@@ -750,19 +750,19 @@
- * -> NLS ISO 8859-1 (CONFIG_NLS_ISO8859_1)
-
-
--3) Create /mnt/ipod:
-+3) Create /media/ipod:
-
-- mkdir /mnt/ipod
-+ mkdir /media/ipod
-
- 4) Add a line to /etc/fstab. You should edit uid to match your user
- id. Also, /dev/sda2 may not be appropriate, if you have other scsi
- devices.
-
--/dev/sda2 /mnt/ipod vfat rw,user,noauto,noatime,errors=remount 0 0
-+/dev/sda2 /media/ipod vfat rw,user,noauto,noatime,errors=remount 0 0
-
- (For HFS this line should read
-
--/dev/sda /mnt/ipod hfsplus rw,user,noauto,exec 0 0
-+/dev/sda /media/ipod hfsplus rw,user,noauto,exec 0 0
-
- please note that it's just '/dev/sda')
-
-@@ -770,7 +770,7 @@
- NOTE: Some users have had problems with newer versions of mount(newer than
- mount-2.11h) The following fstab entry might work better for you.
-
--/dev/sda2 /mnt/ipod vfat rw,user,noauto,noatime,shortname=winnt 0 0
-+/dev/sda2 /media/ipod vfat rw,user,noauto,noatime,shortname=winnt 0 0
-
- 5) Install the hotplug utilities
- (http://linux-hotplug.sourceforge.net/, debian package: 'hotplug')
-@@ -819,13 +819,13 @@
-
- 7) Mount the iPod hard drive
-
-- mount /mnt/ipod
-+ mount /media/ipod
-
- 8) do whatever you need to do (e.g. start gtkpod, see below)
-
- 9) Unmount the iPod:
-
-- umount /mnt/ipod
-+ umount /media/ipod
-
- 10) Unload the module sbp2 (as most likely as root):
-
-@@ -874,19 +874,19 @@
- * -> Codepage 437 (CONFIG_NLS_CODEPAGE_437)
- * -> NLS ISO 8859-1 (CONFIG_NLS_ISO8859_1)
-
--3) Create /mnt/ipod:
-+3) Create /media/ipod:
-
-- mkdir /mnt/ipod
-+ mkdir /media/ipod
-
- 4) Add a line to /etc/fstab. You should edit uid to match your user
- id. Also, /dev/sda2 may not be appropriate, if you have other scsi
- devices.
-
--/dev/sda2 /mnt/ipod vfat rw,user,noauto,noatime 0 0
-+/dev/sda2 /media/ipod vfat rw,user,noauto,noatime 0 0
-
- (For HFS this line should read
-
--/dev/sda /mnt/ipod hfsplus rw,user,noauto,exec 0 0
-+/dev/sda /media/ipod hfsplus rw,user,noauto,exec 0 0
-
- please note that it's just '/dev/sda')
-
-@@ -894,7 +894,7 @@
- NOTE: Some users have had problems with newer versions of mount(newer than
- mount-2.11h) The following fstab entry might work better for you.
-
--/dev/sda2 /mnt/ipod vfat rw,user,noauto,noatime,shortname=winnt 0 0
-+/dev/sda2 /media/ipod vfat rw,user,noauto,noatime,shortname=winnt 0 0
-
- NOTE: You can add ",umask=0" to the options to make the iPod
- readable/writable for all users.
-@@ -934,13 +934,13 @@
-
- 7) Mount the iPod hard drive
-
-- mount /mnt/ipod
-+ mount /media/ipod
-
- 8) do whatever you need to do (e.g. start gtkpod, see below)
-
- 9) Unmount the iPod:
-
-- umount /mnt/ipod
-+ umount /media/ipod
-
- 10) Unload the module sbp2 (as most likely as root):
-
-@@ -974,7 +974,7 @@
- - since the iPod's hdd was already spun up, the SCSI subsystem now
- recognizes it and mounts it as /dev/sda
-
--- You can then mount /dev/sda2 to /mnt/ipod as normal."
-+- You can then mount /dev/sda2 to /media/ipod as normal."
-
- On the other hand: with my 4G iPod under 2.6.9 and 2.6.10 I never had
- any problem whatsoever getting the iPod to work. With IEEE it was
-@@ -1030,10 +1030,10 @@
- /**********/
- Add a line similar to the below to your /etc/fstab, this will enable users
- to mount the ipod with read/write capabilities. Example line assumes your
--ipod mount point is /mnt/ipod and your ipod is detected as /dev/sda
-+ipod mount point is /media/ipod and your ipod is detected as /dev/sda
-
- ------------------------------- Begin Here ---------------------------------
--/dev/sda2 /mnt/ipod vfat rw,user,noauto 0 0
-+/dev/sda2 /media/ipod vfat rw,user,noauto 0 0
- ------------------------------- End Here -----------------------------------
-
-
-diff -urNad trunk~/scripts/sync-abook.sh trunk/scripts/sync-abook.sh
---- trunk~/scripts/sync-abook.sh 2007-11-18 16:28:19.000000000 +0100
-+++ trunk/scripts/sync-abook.sh 2007-11-18 16:48:16.000000000 +0100
-@@ -9,7 +9,7 @@
- #
- # with the following defaults:
-
--IPOD_MOUNT='/mnt/ipod' # mount point of ipod
-+IPOD_MOUNT='/media/ipod' # mount point of ipod
- DATAFILE='~/.abook/addressbook' # the abook db
- ENCODING_FROM=UTF-8 # encoding used by abook
- ENCODING=ISO-8859-15 # encoding used by ipod
-diff -urNad trunk~/scripts/sync-evocalendar.sh trunk/scripts/sync-evocalendar.sh
---- trunk~/scripts/sync-evocalendar.sh 2007-11-18 16:28:23.000000000 +0100
-+++ trunk/scripts/sync-evocalendar.sh 2007-11-18 16:48:16.000000000 +0100
-@@ -10,7 +10,7 @@
- #
- # with the following defaults:
-
--IPOD_MOUNT=/mnt/ipod # mountpoint of ipod
-+IPOD_MOUNT=/media/ipod # mountpoint of ipod
-
- #the path to a script that will be passed the ical information from STDIN and filter, if needed
- #FILTER_SCRIPT=
-diff -urNad trunk~/scripts/sync-evolution.sh trunk/scripts/sync-evolution.sh
---- trunk~/scripts/sync-evolution.sh 2007-11-18 16:28:26.000000000 +0100
-+++ trunk/scripts/sync-evolution.sh 2007-11-18 16:48:16.000000000 +0100
-@@ -13,7 +13,7 @@
- #
- # with the following defaults:
-
--IPOD_MOUNT=/mnt/ipod # mountpoint of ipod
-+IPOD_MOUNT=/media/ipod # mountpoint of ipod
- EVOPATH='/opt/gnome/libexec/evolution/2.0:/usr/lib/evolution/2.0:/opt/gnome/bin' # additional path
- ENCODING=ISO-8859-15 # encoding used by ipod
-
-diff -urNad trunk~/scripts/sync-kaddressbook.sh trunk/scripts/sync-kaddressbook.sh
---- trunk~/scripts/sync-kaddressbook.sh 2007-11-18 16:28:29.000000000 +0100
-+++ trunk/scripts/sync-kaddressbook.sh 2007-11-18 16:48:16.000000000 +0100
-@@ -9,7 +9,7 @@
- #
- # with the following defaults:
-
--IPOD_MOUNT=/mnt/ipod # mountpoint of ipod
-+IPOD_MOUNT=/media/ipod # mountpoint of ipod
- DATAFILE=~/.kde/share/apps/kabc/std.vcf # vcard file
- ENCODING=ISO-8859-15 # encoding used by ipod
-
-diff -urNad trunk~/scripts/sync-korganizer.sh trunk/scripts/sync-korganizer.sh
---- trunk~/scripts/sync-korganizer.sh 2007-11-18 16:28:35.000000000 +0100
-+++ trunk/scripts/sync-korganizer.sh 2007-11-18 16:48:16.000000000 +0100
-@@ -9,7 +9,7 @@
- #
- # with the following defaults:
-
--IPOD_MOUNT=/mnt/ipod # mountpoint of ipod
-+IPOD_MOUNT=/media/ipod # mountpoint of ipod
- DATAFILE=~/.kde/share/apps/korganizer/std.ics # calendar data file
- ENCODING=ISO-8859-15 # encoding used by ipod
-
-diff -urNad trunk~/scripts/sync-ldif.sh trunk/scripts/sync-ldif.sh
---- trunk~/scripts/sync-ldif.sh 2007-11-18 16:28:40.000000000 +0100
-+++ trunk/scripts/sync-ldif.sh 2007-11-18 16:48:16.000000000 +0100
-@@ -15,7 +15,7 @@
- # differently...This is still Chinese for me!! :)
-
- export LDIFAMILYNAME=contactIPOD # Filenames will look like $LDIFAMILYNAMEXX.vcf, X=[0-9]
--export IPOD_MOUNT=/mnt/ipod # Mount point of the ipod
-+export IPOD_MOUNT=/media/ipod # Mount point of the ipod
- declare LDIFILE=addressbook.ldif # default filename 'addressbook.ldif'
- declare ENCODING=ISO-8859-15 # To try others encodings : 'iconv --list'
- declare DELETE="NO" # To delete old .vcf files by default? 'NO'!!
-@@ -41,9 +41,9 @@
- $(basename $0) doesn't delete old .vcf files by default, but overwrites.
-
- Options:
-- Syntax : $(basename $0) -f addbook.ldif -m /mnt/ipod -n contactIPOD -d (-h)
-+ Syntax : $(basename $0) -f addbook.ldif -m /media/ipod -n contactIPOD -d (-h)
- [-f] addbook.ldif : contains the .ldif Filename
-- [-m] /mnt/ipod : contains the ipod Mounted directory
-+ [-m] /media/ipod : contains the ipod Mounted directory
- [-n] contactIPOD : contains the .vcf family fileName
- [-d] : contains the option to Delete all old .vcf files
- [-h] : contains this Help
-diff -urNad trunk~/scripts/sync-thunderbird-nano.sh trunk/scripts/sync-thunderbird-nano.sh
---- trunk~/scripts/sync-thunderbird-nano.sh 2007-11-18 16:28:43.000000000 +0100
-+++ trunk/scripts/sync-thunderbird-nano.sh 2007-11-18 16:48:16.000000000 +0100
-@@ -25,7 +25,7 @@
-
- # with the following defaults:
-
--IPOD_MOUNT=/mnt/ipod # mountpoint of ipod
-+IPOD_MOUNT=/media/ipod # mountpoint of ipod
- ENCODING=ISO-8859-15 # encoding used by ipod
- NAME=thunderbird # default file export name
- FILE_FLAG='' # flag used to determine end of file
-diff -urNad trunk~/scripts/sync-thunderbird.sh trunk/scripts/sync-thunderbird.sh
---- trunk~/scripts/sync-thunderbird.sh 2007-11-18 16:28:46.000000000 +0100
-+++ trunk/scripts/sync-thunderbird.sh 2007-11-18 16:48:16.000000000 +0100
-@@ -18,7 +18,7 @@
-
- # with the following defaults:
-
--IPOD_MOUNT=/mnt/ipod # mountpoint of ipod
-+IPOD_MOUNT=/media/ipod # mountpoint of ipod
- ENCODING=ISO-8859-15 # encoding used by ipod
- NAME=thunderbird # default file export name
-
-diff -urNad trunk~/scripts/sync-webcalendar.sh trunk/scripts/sync-webcalendar.sh
---- trunk~/scripts/sync-webcalendar.sh 2007-11-18 16:28:52.000000000 +0100
-+++ trunk/scripts/sync-webcalendar.sh 2007-11-18 16:48:16.000000000 +0100
-@@ -9,7 +9,7 @@
- # with the following defaults:
-
- # mount point of ipod
--IPOD_MOUNT='/mnt/ipod'
-+IPOD_MOUNT='/media/ipod'
- # uri for webcalendar (example)
- DATAFILE='https://somewhere.local/calendar.ics'
- # calendar name
Copied: gtkpod/tags/0.99.10-5/debian/patches/01_mountpoint.dpatch (from rev 278, gtkpod/trunk/debian/patches/01_mountpoint.dpatch)
===================================================================
--- gtkpod/tags/0.99.10-5/debian/patches/01_mountpoint.dpatch (rev 0)
+++ gtkpod/tags/0.99.10-5/debian/patches/01_mountpoint.dpatch 2007-11-20 13:46:35 UTC (rev 280)
@@ -0,0 +1,276 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 01_mountpoint.dpatch by Nico Golde <nion at debian.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: No description.
+
+ at DPATCH@
+diff -urNad trunk~/README trunk/README
+--- trunk~/README 2007-11-18 16:47:22.000000000 +0100
++++ trunk/README 2007-11-20 14:20:36.000000000 +0100
+@@ -52,7 +52,7 @@
+ 1) If your iPod is not mounted automatically when connecting it to
+ your computer follow steps 1-7 in the "Connecting your iPod to a
+ Linux box" (basically you need to get the iPod partition mounted to
+- /mnt/ipod). In most cases this should not be necessary any more
++ /media/ipod). In most cases this should not be necessary any more
+ these days.
+
+ 2) If you are using GNOME, starting with V1.0 of gtkpod your iPod will
+@@ -699,13 +699,13 @@
+ (Obviously you need to change the filesystem type from 'vfat' to
+ 'hfsplus' when you use an HFS formatted iPod.)
+
+- Then simply add a link from /mnt/ipod:
++ Then simply add a link from /media/ipod:
+
+- ln -s /var/autofs/removable/ipod /mnt/ipod
++ ln -s /var/autofs/removable/ipod /media/ipod
+
+
+ Now your system is configured to mount the iPod every time you access
+-/mnt/ipod and to unmount it again after two seconds of inactivity. You
++/media/ipod and to unmount it again after two seconds of inactivity. You
+ won't have to worry about doing mounting/unmouting yourself any more.
+
+
+@@ -750,19 +750,19 @@
+ * -> NLS ISO 8859-1 (CONFIG_NLS_ISO8859_1)
+
+
+-3) Create /mnt/ipod:
++3) Create /media/ipod:
+
+- mkdir /mnt/ipod
++ mkdir /media/ipod
+
+ 4) Add a line to /etc/fstab. You should edit uid to match your user
+ id. Also, /dev/sda2 may not be appropriate, if you have other scsi
+ devices.
+
+-/dev/sda2 /mnt/ipod vfat rw,user,noauto,noatime,errors=remount 0 0
++/dev/sda2 /media/ipod vfat rw,user,noauto,noatime,errors=remount 0 0
+
+ (For HFS this line should read
+
+-/dev/sda /mnt/ipod hfsplus rw,user,noauto,exec 0 0
++/dev/sda /media/ipod hfsplus rw,user,noauto,exec 0 0
+
+ please note that it's just '/dev/sda')
+
+@@ -770,7 +770,7 @@
+ NOTE: Some users have had problems with newer versions of mount(newer than
+ mount-2.11h) The following fstab entry might work better for you.
+
+-/dev/sda2 /mnt/ipod vfat rw,user,noauto,noatime,shortname=winnt 0 0
++/dev/sda2 /media/ipod vfat rw,user,noauto,noatime,shortname=winnt 0 0
+
+ 5) Install the hotplug utilities
+ (http://linux-hotplug.sourceforge.net/, debian package: 'hotplug')
+@@ -819,13 +819,13 @@
+
+ 7) Mount the iPod hard drive
+
+- mount /mnt/ipod
++ mount /media/ipod
+
+ 8) do whatever you need to do (e.g. start gtkpod, see below)
+
+ 9) Unmount the iPod:
+
+- umount /mnt/ipod
++ umount /media/ipod
+
+ 10) Unload the module sbp2 (as most likely as root):
+
+@@ -874,19 +874,19 @@
+ * -> Codepage 437 (CONFIG_NLS_CODEPAGE_437)
+ * -> NLS ISO 8859-1 (CONFIG_NLS_ISO8859_1)
+
+-3) Create /mnt/ipod:
++3) Create /media/ipod:
+
+- mkdir /mnt/ipod
++ mkdir /media/ipod
+
+ 4) Add a line to /etc/fstab. You should edit uid to match your user
+ id. Also, /dev/sda2 may not be appropriate, if you have other scsi
+ devices.
+
+-/dev/sda2 /mnt/ipod vfat rw,user,noauto,noatime 0 0
++/dev/sda2 /media/ipod vfat rw,user,noauto,noatime 0 0
+
+ (For HFS this line should read
+
+-/dev/sda /mnt/ipod hfsplus rw,user,noauto,exec 0 0
++/dev/sda /media/ipod hfsplus rw,user,noauto,exec 0 0
+
+ please note that it's just '/dev/sda')
+
+@@ -894,7 +894,7 @@
+ NOTE: Some users have had problems with newer versions of mount(newer than
+ mount-2.11h) The following fstab entry might work better for you.
+
+-/dev/sda2 /mnt/ipod vfat rw,user,noauto,noatime,shortname=winnt 0 0
++/dev/sda2 /media/ipod vfat rw,user,noauto,noatime,shortname=winnt 0 0
+
+ NOTE: You can add ",umask=0" to the options to make the iPod
+ readable/writable for all users.
+@@ -934,13 +934,13 @@
+
+ 7) Mount the iPod hard drive
+
+- mount /mnt/ipod
++ mount /media/ipod
+
+ 8) do whatever you need to do (e.g. start gtkpod, see below)
+
+ 9) Unmount the iPod:
+
+- umount /mnt/ipod
++ umount /media/ipod
+
+ 10) Unload the module sbp2 (as most likely as root):
+
+@@ -974,7 +974,7 @@
+ - since the iPod's hdd was already spun up, the SCSI subsystem now
+ recognizes it and mounts it as /dev/sda
+
+-- You can then mount /dev/sda2 to /mnt/ipod as normal."
++- You can then mount /dev/sda2 to /media/ipod as normal."
+
+ On the other hand: with my 4G iPod under 2.6.9 and 2.6.10 I never had
+ any problem whatsoever getting the iPod to work. With IEEE it was
+@@ -1030,10 +1030,10 @@
+ /**********/
+ Add a line similar to the below to your /etc/fstab, this will enable users
+ to mount the ipod with read/write capabilities. Example line assumes your
+-ipod mount point is /mnt/ipod and your ipod is detected as /dev/sda
++ipod mount point is /media/ipod and your ipod is detected as /dev/sda
+
+ ------------------------------- Begin Here ---------------------------------
+-/dev/sda2 /mnt/ipod vfat rw,user,noauto 0 0
++/dev/sda2 /media/ipod vfat rw,user,noauto 0 0
+ ------------------------------- End Here -----------------------------------
+
+
+diff -urNad trunk~/scripts/sync-abook.sh trunk/scripts/sync-abook.sh
+--- trunk~/scripts/sync-abook.sh 2007-11-18 16:28:19.000000000 +0100
++++ trunk/scripts/sync-abook.sh 2007-11-20 14:20:36.000000000 +0100
+@@ -9,7 +9,7 @@
+ #
+ # with the following defaults:
+
+-IPOD_MOUNT='/mnt/ipod' # mount point of ipod
++IPOD_MOUNT='/media/ipod' # mount point of ipod
+ DATAFILE='~/.abook/addressbook' # the abook db
+ ENCODING_FROM=UTF-8 # encoding used by abook
+ ENCODING=ISO-8859-15 # encoding used by ipod
+diff -urNad trunk~/scripts/sync-evocalendar.sh trunk/scripts/sync-evocalendar.sh
+--- trunk~/scripts/sync-evocalendar.sh 2007-11-18 16:28:23.000000000 +0100
++++ trunk/scripts/sync-evocalendar.sh 2007-11-20 14:20:36.000000000 +0100
+@@ -10,7 +10,7 @@
+ #
+ # with the following defaults:
+
+-IPOD_MOUNT=/mnt/ipod # mountpoint of ipod
++IPOD_MOUNT=/media/ipod # mountpoint of ipod
+
+ #the path to a script that will be passed the ical information from STDIN and filter, if needed
+ #FILTER_SCRIPT=
+diff -urNad trunk~/scripts/sync-evolution.sh trunk/scripts/sync-evolution.sh
+--- trunk~/scripts/sync-evolution.sh 2007-11-18 16:28:26.000000000 +0100
++++ trunk/scripts/sync-evolution.sh 2007-11-20 14:20:36.000000000 +0100
+@@ -13,7 +13,7 @@
+ #
+ # with the following defaults:
+
+-IPOD_MOUNT=/mnt/ipod # mountpoint of ipod
++IPOD_MOUNT=/media/ipod # mountpoint of ipod
+ EVOPATH='/opt/gnome/libexec/evolution/2.0:/usr/lib/evolution/2.0:/opt/gnome/bin' # additional path
+ ENCODING=ISO-8859-15 # encoding used by ipod
+
+diff -urNad trunk~/scripts/sync-kaddressbook.sh trunk/scripts/sync-kaddressbook.sh
+--- trunk~/scripts/sync-kaddressbook.sh 2007-11-18 16:28:29.000000000 +0100
++++ trunk/scripts/sync-kaddressbook.sh 2007-11-20 14:20:36.000000000 +0100
+@@ -9,7 +9,7 @@
+ #
+ # with the following defaults:
+
+-IPOD_MOUNT=/mnt/ipod # mountpoint of ipod
++IPOD_MOUNT=/media/ipod # mountpoint of ipod
+ DATAFILE=~/.kde/share/apps/kabc/std.vcf # vcard file
+ ENCODING=ISO-8859-15 # encoding used by ipod
+
+diff -urNad trunk~/scripts/sync-korganizer.sh trunk/scripts/sync-korganizer.sh
+--- trunk~/scripts/sync-korganizer.sh 2007-11-18 16:28:35.000000000 +0100
++++ trunk/scripts/sync-korganizer.sh 2007-11-20 14:20:36.000000000 +0100
+@@ -9,7 +9,7 @@
+ #
+ # with the following defaults:
+
+-IPOD_MOUNT=/mnt/ipod # mountpoint of ipod
++IPOD_MOUNT=/media/ipod # mountpoint of ipod
+ DATAFILE=~/.kde/share/apps/korganizer/std.ics # calendar data file
+ ENCODING=ISO-8859-15 # encoding used by ipod
+
+diff -urNad trunk~/scripts/sync-ldif.sh trunk/scripts/sync-ldif.sh
+--- trunk~/scripts/sync-ldif.sh 2007-11-19 18:49:28.000000000 +0100
++++ trunk/scripts/sync-ldif.sh 2007-11-20 14:20:36.000000000 +0100
+@@ -15,7 +15,7 @@
+ # differently...This is still Chinese for me!! :)
+
+ export LDIFAMILYNAME=contactIPOD # Filenames will look like $LDIFAMILYNAMEXX.vcf, X=[0-9]
+-export IPOD_MOUNT=/mnt/ipod # Mount point of the ipod
++export IPOD_MOUNT=/media/ipod # Mount point of the ipod
+ declare LDIFILE=addressbook.ldif # default filename 'addressbook.ldif'
+ declare ENCODING=ISO-8859-15 # To try others encodings : 'iconv --list'
+ declare DELETE="NO" # To delete old .vcf files by default? 'NO'!!
+diff -urNad trunk~/scripts/sync-thunderbird-nano.sh trunk/scripts/sync-thunderbird-nano.sh
+--- trunk~/scripts/sync-thunderbird-nano.sh 2007-11-18 16:28:43.000000000 +0100
++++ trunk/scripts/sync-thunderbird-nano.sh 2007-11-20 14:20:36.000000000 +0100
+@@ -25,7 +25,7 @@
+
+ # with the following defaults:
+
+-IPOD_MOUNT=/mnt/ipod # mountpoint of ipod
++IPOD_MOUNT=/media/ipod # mountpoint of ipod
+ ENCODING=ISO-8859-15 # encoding used by ipod
+ NAME=thunderbird # default file export name
+ FILE_FLAG='' # flag used to determine end of file
+diff -urNad trunk~/scripts/sync-thunderbird.sh trunk/scripts/sync-thunderbird.sh
+--- trunk~/scripts/sync-thunderbird.sh 2007-11-18 16:28:46.000000000 +0100
++++ trunk/scripts/sync-thunderbird.sh 2007-11-20 14:20:36.000000000 +0100
+@@ -18,7 +18,7 @@
+
+ # with the following defaults:
+
+-IPOD_MOUNT=/mnt/ipod # mountpoint of ipod
++IPOD_MOUNT=/media/ipod # mountpoint of ipod
+ ENCODING=ISO-8859-15 # encoding used by ipod
+ NAME=thunderbird # default file export name
+
+diff -urNad trunk~/scripts/sync-webcalendar.sh trunk/scripts/sync-webcalendar.sh
+--- trunk~/scripts/sync-webcalendar.sh 2007-11-18 16:28:52.000000000 +0100
++++ trunk/scripts/sync-webcalendar.sh 2007-11-20 14:20:36.000000000 +0100
+@@ -9,7 +9,7 @@
+ # with the following defaults:
+
+ # mount point of ipod
+-IPOD_MOUNT='/mnt/ipod'
++IPOD_MOUNT='/media/ipod'
+ # uri for webcalendar (example)
+ DATAFILE='https://somewhere.local/calendar.ics'
+ # calendar name
+diff -urNad trunk~/src/prefs.c trunk/src/prefs.c
+--- trunk~/src/prefs.c 2007-11-18 16:45:09.000000000 +0100
++++ trunk/src/prefs.c 2007-11-20 14:20:44.000000000 +0100
+@@ -178,7 +178,7 @@
+ prefs_set_int("delete_file", TRUE);
+ prefs_set_int("delete_local_file", TRUE);
+ prefs_set_int("delete_database", TRUE);
+- prefs_set_string("initial_mountpoint", "/mnt/ipod");
++ prefs_set_string("initial_mountpoint", "/media/ipod");
+ prefs_set_string ("path_play_now", "xmms %s");
+ prefs_set_string ("path_play_enqueue", "xmms -e %s");
+ prefs_set_string ("path_mserv_trackinfo_root", "/var/lib/mserv/trackinfo/");
Deleted: gtkpod/tags/0.99.10-5/debian/rules
===================================================================
--- gtkpod/trunk/debian/rules 2007-11-13 14:54:03 UTC (rev 259)
+++ gtkpod/tags/0.99.10-5/debian/rules 2007-11-20 13:46:35 UTC (rev 280)
@@ -1,64 +0,0 @@
-#!/usr/bin/make -f
-
-DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
-DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
-
-CFLAGS = -Wall -g
-
-ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
- CFLAGS += -O0
-else
- CFLAGS += -O2
-endif
-
-config.status: configure
- dh_testdir
- CFLAGS="$(CFLAGS)" ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info
-
-build: build-stamp
-
-build-stamp: config.status
- dh_testdir
-
- $(MAKE)
- pod2man --release "gtkpod 0.99.10" --center "gtkpod Manual" debian/gtkpod.pod >gtkpod.1
- touch build-stamp
-
-clean:
- dh_testdir
- dh_testroot
- rm -f build-stamp gtkpod.1 pixmaps/gtkpod.glade*
- [ ! -f Makefile ] || $(MAKE) distclean
- dh_clean
-
-install: build
- dh_testdir
- dh_testroot
- dh_clean -k
- dh_installdirs
- $(MAKE) install DESTDIR=$(CURDIR)/debian/gtkpod
-
-binary-indep: build install
-
-binary-arch: build install
- dh_testdir
- dh_testroot
- dh_installchangelogs ChangeLog
- dh_installdocs
- dh_installmenu
- dh_installman gtkpod.1
- dh_install
- dh_desktop
- dh_link
- dh_strip
- dh_compress
- dh_fixperms
- dh_makeshlibs
- dh_installdeb
- dh_shlibdeps
- dh_gencontrol
- dh_md5sums
- dh_builddeb
-
-binary: binary-indep binary-arch
-.PHONY: build clean binary-indep binary-arch binary install
Copied: gtkpod/tags/0.99.10-5/debian/rules (from rev 265, gtkpod/trunk/debian/rules)
===================================================================
--- gtkpod/tags/0.99.10-5/debian/rules (rev 0)
+++ gtkpod/tags/0.99.10-5/debian/rules 2007-11-20 13:46:35 UTC (rev 280)
@@ -0,0 +1,66 @@
+#!/usr/bin/make -f
+
+DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
+DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
+
+CFLAGS = -Wall -g
+
+include /usr/share/dpatch/dpatch.make
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+ CFLAGS += -O0
+else
+ CFLAGS += -O2
+endif
+
+config.status: patch configure
+ dh_testdir
+ CFLAGS="$(CFLAGS)" ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info
+
+build: build-stamp
+
+build-stamp: config.status
+ dh_testdir
+
+ $(MAKE)
+ pod2man --release "gtkpod 0.99.10" --center "gtkpod Manual" debian/gtkpod.pod >gtkpod.1
+ touch build-stamp
+
+clean: unpatch
+ dh_testdir
+ dh_testroot
+ rm -f build-stamp gtkpod.1 pixmaps/gtkpod.glade*
+ [ ! -f Makefile ] || $(MAKE) distclean
+ dh_clean
+
+install: build
+ dh_testdir
+ dh_testroot
+ dh_clean -k
+ dh_installdirs
+ $(MAKE) install DESTDIR=$(CURDIR)/debian/gtkpod
+
+binary-indep: build install
+
+binary-arch: build install
+ dh_testdir
+ dh_testroot
+ dh_installchangelogs ChangeLog
+ dh_installdocs
+ dh_installmenu
+ dh_installman gtkpod.1
+ dh_install
+ dh_desktop
+ dh_link
+ dh_strip
+ dh_compress
+ dh_fixperms
+ dh_makeshlibs
+ dh_installdeb
+ dh_shlibdeps
+ dh_gencontrol
+ dh_md5sums
+ dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install
Deleted: gtkpod/tags/0.99.10-5/scripts/sync-abook.sh
===================================================================
--- gtkpod/trunk/scripts/sync-abook.sh 2007-11-13 14:54:03 UTC (rev 259)
+++ gtkpod/tags/0.99.10-5/scripts/sync-abook.sh 2007-11-20 13:46:35 UTC (rev 280)
@@ -1,74 +0,0 @@
-#!/bin/sh
-# (c) 2005 Daniel Kercher
-# Script to sync the ipod with abook
-
-# Usage:
-#
-# sync-abook.sh [-i <ipod mountpoint>] [-d <abook database>]
-# ... [-e <encoding ipod>] [-f <encoding abook>]
-#
-# with the following defaults:
-
-IPOD_MOUNT='/media/ipod' # mount point of ipod
-DATAFILE='~/.abook/addressbook' # the abook db
-ENCODING_FROM=UTF-8 # encoding used by abook
-ENCODING=ISO-8859-15 # encoding used by ipod
-
-# Unless called with "-e=none" this script requires "iconv" available
-# from http://www.gnu.org/software/libiconv/
-
-# About the encoding used by the iPod (by Jorg Schuler):
-#
-# For some reason the encoding used for the contact files and
-# calenader files depends on the language you have set your iPod
-# to. If you set your iPod to German, iso-8859-15 (or -1?) is
-# expected. If you set it to Japanese, SHIFT-JIS is expected. You need
-# to reboot the iPod to have the change take effect, however. (I'm
-# using firmware version 1.3.)
-#
-# If you know of more encodings, please let me know, so they can be
-# added here:
-#
-# iPod language encoding expected
-# ----------------------------------------
-# German ISO-8859-15
-# Japanese SHIFT-JIS
-
-# Changelog
-# 2005/06/15 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
-# Received original script from Daniel Kercher and added character
-# conversion and command line options.
-#
-# 2007/05/31 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
-# Set a more reasonable default datafile.
-#
-
-# overwrite default settings with optional command line arguments
-while getopts i:d:e:f: option; do
- case $option in
- i) IPOD_MOUNT=$OPTARG;;
- d) DATAFILE=$OPTARG;;
- e) ENCODING=$OPTARG;;
- f) ENCODING_FROM=$OPTARG;;
- \?) echo "Usage: `basename $0` [-i <ipod mountpoint>] [-d <abook database>] [-e <encoding ipod>] [-f <encoding abook>]"
- exit 1;;
- esac
-done
-
-# set the RECODE command
-if [ $ENCODING = "none" ] || [ $ENCODING = "NONE" ]; then
- RECODE="cat" # no conversion
-else
- RECODE="iconv -f $ENCODING_FROM -t $ENCODING"
-fi
-
-
-# check if DATAFILE exists
-if [ ! -f $DATAFILE ]; then
- echo "Error: $DATAFILE does not exist"
- exit 1
-fi
-
-echo -n "Syncing abook to iPod... "
-abook --convert --infile $DATAFILE --outformat gcrd | sed '/^$/d' | $RECODE > ${IPOD_MOUNT}/Contacts/abook.vcf
-echo "done!"
Copied: gtkpod/tags/0.99.10-5/scripts/sync-abook.sh (from rev 266, gtkpod/trunk/scripts/sync-abook.sh)
===================================================================
--- gtkpod/tags/0.99.10-5/scripts/sync-abook.sh (rev 0)
+++ gtkpod/tags/0.99.10-5/scripts/sync-abook.sh 2007-11-20 13:46:35 UTC (rev 280)
@@ -0,0 +1,74 @@
+#!/bin/sh
+# (c) 2005 Daniel Kercher
+# Script to sync the ipod with abook
+
+# Usage:
+#
+# sync-abook.sh [-i <ipod mountpoint>] [-d <abook database>]
+# ... [-e <encoding ipod>] [-f <encoding abook>]
+#
+# with the following defaults:
+
+IPOD_MOUNT='/mnt/ipod' # mount point of ipod
+DATAFILE='~/.abook/addressbook' # the abook db
+ENCODING_FROM=UTF-8 # encoding used by abook
+ENCODING=ISO-8859-15 # encoding used by ipod
+
+# Unless called with "-e=none" this script requires "iconv" available
+# from http://www.gnu.org/software/libiconv/
+
+# About the encoding used by the iPod (by Jorg Schuler):
+#
+# For some reason the encoding used for the contact files and
+# calenader files depends on the language you have set your iPod
+# to. If you set your iPod to German, iso-8859-15 (or -1?) is
+# expected. If you set it to Japanese, SHIFT-JIS is expected. You need
+# to reboot the iPod to have the change take effect, however. (I'm
+# using firmware version 1.3.)
+#
+# If you know of more encodings, please let me know, so they can be
+# added here:
+#
+# iPod language encoding expected
+# ----------------------------------------
+# German ISO-8859-15
+# Japanese SHIFT-JIS
+
+# Changelog
+# 2005/06/15 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
+# Received original script from Daniel Kercher and added character
+# conversion and command line options.
+#
+# 2007/05/31 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
+# Set a more reasonable default datafile.
+#
+
+# overwrite default settings with optional command line arguments
+while getopts i:d:e:f: option; do
+ case $option in
+ i) IPOD_MOUNT=$OPTARG;;
+ d) DATAFILE=$OPTARG;;
+ e) ENCODING=$OPTARG;;
+ f) ENCODING_FROM=$OPTARG;;
+ \?) echo "Usage: `basename $0` [-i <ipod mountpoint>] [-d <abook database>] [-e <encoding ipod>] [-f <encoding abook>]"
+ exit 1;;
+ esac
+done
+
+# set the RECODE command
+if [ $ENCODING = "none" ] || [ $ENCODING = "NONE" ]; then
+ RECODE="cat" # no conversion
+else
+ RECODE="iconv -f $ENCODING_FROM -t $ENCODING"
+fi
+
+
+# check if DATAFILE exists
+if [ ! -f $DATAFILE ]; then
+ echo "Error: $DATAFILE does not exist"
+ exit 1
+fi
+
+echo -n "Syncing abook to iPod... "
+abook --convert --infile $DATAFILE --outformat gcrd | sed '/^$/d' | $RECODE > ${IPOD_MOUNT}/Contacts/abook.vcf
+echo "done!"
Deleted: gtkpod/tags/0.99.10-5/scripts/sync-evocalendar.sh
===================================================================
--- gtkpod/trunk/scripts/sync-evocalendar.sh 2007-11-13 14:54:03 UTC (rev 259)
+++ gtkpod/tags/0.99.10-5/scripts/sync-evocalendar.sh 2007-11-20 13:46:35 UTC (rev 280)
@@ -1,127 +0,0 @@
-#!/bin/sh
-# (c) 2004 Markus Gaugusch <markus at gaugusch.at>
-# Script for syncing evolution calendar and task data with iPod
-
-# Usage:
-#
-# sync-evocalendar.sh [-i <ipod mountpoint>] [-e <encoding>]
-# ... [-c <evolution calendar file>] [-t <evolution tasks file>]
-# ... [-f <ical filter script>]
-#
-# with the following defaults:
-
-IPOD_MOUNT=/media/ipod # mountpoint of ipod
-
-#the path to a script that will be passed the ical information from STDIN and filter, if needed
-#FILTER_SCRIPT=
-
-#get all the local evolution calendars
-CALFILES=`find ~/.evolution/calendar/local/ -name "calendar.ics"`
-
-#get all the local evolution tasks
-TASKFILES=`find ~/.evolution/tasks/local/ -name "tasks.ics"`
-
-ENCODING=ISO-8859-15 # encoding used by ipod
-
-# Unless called with "-e none" this script requires "iconv" available
-# from http://www.gnu.org/software/libiconv/
-
-# About the encoding used by the iPod (by Jorg Schuler):
-#
-# For some reason the encoding used for the contact files and
-# calenader files depends on the language you have set your iPod
-# to. If you set your iPod to German, iso-8859-15 (or -1?) is
-# expected. If you set it to Japanese, SHIFT-JIS is expected. You need
-# to reboot the iPod to have the change take effect, however. (I'm
-# using firmware version 1.3.)
-#
-# If you know of more encodings, please let me know, so they can be
-# added here:
-#
-# iPod language encoding expected
-# ----------------------------------------
-# German ISO-8859-15
-# Japanese SHIFT-JIS
-
-
-# Changelog:
-#
-# 2006/03/08 (Michele C. Soccio <michele at soccio dot it>:
-# Changed to get all the local calendar and task files
-#
-# Changed to correct the calendar file(s) and task file(s) command line option
-#
-# 2004/06/27 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
-# Changed to accept ipod-mountpath and encoding as command line
-# option
-#
-# Split into two files -- one for contacts, one for calendar.
-#
-# Placed under GPL in agreement with Markus Gaugusch.
-#
-# Added note about encoding used by the iPod.
-#
-# 2004/07/02 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
-# Added Usage-line, added check for vcard file, rearranged source
-#
-# 2004/07/03 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
-# Made "iconv" optional (call with "-e none")
-#
-# Removed "dos2unix" as my iPod (firmware 1.3) happily accepted
-# DOS-type vcards as well. Instead changed the "grep" pattern to
-# catch \cr\lf as well.
-#
-# 2004/12/15 (Clinton Gormley <clint at traveljury dot com>):
-# adapted sync-korganiser to work with evolution.
-
-
-# overwrite default settings with optional command line arguments
-while getopts i:c:t:e: option; do
- case $option in
- i) IPOD_MOUNT=$OPTARG;;
- c) CALFILES=$OPTARG;;
- t) TASKFILES=$OPTARG;;
- e) ENCODING=$OPTARG;;
- f) FILTER=$OPTARG;;
- \?) echo "Usage: `basename $0` [-i <ipod mountpoint>] [-c <evolution calendar file>] [-t <evolution tasks file>] [-f <filter script>] [-e <encoding>]"
- exit 1;;
- esac
-done
-
-
-# set the RECODE command
-if [ $ENCODING = "none" ] || [ $ENCODING = "NONE" ]; then
- RECODE="cat" # no conversion
-else
- RECODE="iconv -f UTF-8 -t $ENCODING"
-fi
-
-if [ $FILTER_SCRIPT ]; then
- FILTER=$FILTER_SCRIPT
-else
- FILTER="cat"
-fi
-
-# check if CALFILES exist
-for i in $CALFILES; do
- if [ ! -f $CALFILE ]; then
- echo "Error: $i does not exist"
- exit 1
- fi
-done
-
-# check if each TASKFILES exist
-for j in $TASKFILES; do
- if [ ! -f $j ]; then
- echo "Error: $TASKFILE does not exist"
- exit 1
- fi
-done
-
-echo $CALFILES
-echo $TASKFILES
-
-# remove all empty lines and recode if necessary
-echo -n "Syncing iPod ... [Calendar] "
- cat $CALFILES $TASKFILES | grep -v '^[[:space:]]$\|^$' | $FILTER | $RECODE > $IPOD_MOUNT/Calendars/evolution
-echo "done!"
Copied: gtkpod/tags/0.99.10-5/scripts/sync-evocalendar.sh (from rev 266, gtkpod/trunk/scripts/sync-evocalendar.sh)
===================================================================
--- gtkpod/tags/0.99.10-5/scripts/sync-evocalendar.sh (rev 0)
+++ gtkpod/tags/0.99.10-5/scripts/sync-evocalendar.sh 2007-11-20 13:46:35 UTC (rev 280)
@@ -0,0 +1,127 @@
+#!/bin/sh
+# (c) 2004 Markus Gaugusch <markus at gaugusch.at>
+# Script for syncing evolution calendar and task data with iPod
+
+# Usage:
+#
+# sync-evocalendar.sh [-i <ipod mountpoint>] [-e <encoding>]
+# ... [-c <evolution calendar file>] [-t <evolution tasks file>]
+# ... [-f <ical filter script>]
+#
+# with the following defaults:
+
+IPOD_MOUNT=/mnt/ipod # mountpoint of ipod
+
+#the path to a script that will be passed the ical information from STDIN and filter, if needed
+#FILTER_SCRIPT=
+
+#get all the local evolution calendars
+CALFILES=`find ~/.evolution/calendar/local/ -name "calendar.ics"`
+
+#get all the local evolution tasks
+TASKFILES=`find ~/.evolution/tasks/local/ -name "tasks.ics"`
+
+ENCODING=ISO-8859-15 # encoding used by ipod
+
+# Unless called with "-e none" this script requires "iconv" available
+# from http://www.gnu.org/software/libiconv/
+
+# About the encoding used by the iPod (by Jorg Schuler):
+#
+# For some reason the encoding used for the contact files and
+# calenader files depends on the language you have set your iPod
+# to. If you set your iPod to German, iso-8859-15 (or -1?) is
+# expected. If you set it to Japanese, SHIFT-JIS is expected. You need
+# to reboot the iPod to have the change take effect, however. (I'm
+# using firmware version 1.3.)
+#
+# If you know of more encodings, please let me know, so they can be
+# added here:
+#
+# iPod language encoding expected
+# ----------------------------------------
+# German ISO-8859-15
+# Japanese SHIFT-JIS
+
+
+# Changelog:
+#
+# 2006/03/08 (Michele C. Soccio <michele at soccio dot it>:
+# Changed to get all the local calendar and task files
+#
+# Changed to correct the calendar file(s) and task file(s) command line option
+#
+# 2004/06/27 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
+# Changed to accept ipod-mountpath and encoding as command line
+# option
+#
+# Split into two files -- one for contacts, one for calendar.
+#
+# Placed under GPL in agreement with Markus Gaugusch.
+#
+# Added note about encoding used by the iPod.
+#
+# 2004/07/02 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
+# Added Usage-line, added check for vcard file, rearranged source
+#
+# 2004/07/03 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
+# Made "iconv" optional (call with "-e none")
+#
+# Removed "dos2unix" as my iPod (firmware 1.3) happily accepted
+# DOS-type vcards as well. Instead changed the "grep" pattern to
+# catch \cr\lf as well.
+#
+# 2004/12/15 (Clinton Gormley <clint at traveljury dot com>):
+# adapted sync-korganiser to work with evolution.
+
+
+# overwrite default settings with optional command line arguments
+while getopts i:c:t:e: option; do
+ case $option in
+ i) IPOD_MOUNT=$OPTARG;;
+ c) CALFILES=$OPTARG;;
+ t) TASKFILES=$OPTARG;;
+ e) ENCODING=$OPTARG;;
+ f) FILTER=$OPTARG;;
+ \?) echo "Usage: `basename $0` [-i <ipod mountpoint>] [-c <evolution calendar file>] [-t <evolution tasks file>] [-f <filter script>] [-e <encoding>]"
+ exit 1;;
+ esac
+done
+
+
+# set the RECODE command
+if [ $ENCODING = "none" ] || [ $ENCODING = "NONE" ]; then
+ RECODE="cat" # no conversion
+else
+ RECODE="iconv -f UTF-8 -t $ENCODING"
+fi
+
+if [ $FILTER_SCRIPT ]; then
+ FILTER=$FILTER_SCRIPT
+else
+ FILTER="cat"
+fi
+
+# check if CALFILES exist
+for i in $CALFILES; do
+ if [ ! -f $CALFILE ]; then
+ echo "Error: $i does not exist"
+ exit 1
+ fi
+done
+
+# check if each TASKFILES exist
+for j in $TASKFILES; do
+ if [ ! -f $j ]; then
+ echo "Error: $TASKFILE does not exist"
+ exit 1
+ fi
+done
+
+echo $CALFILES
+echo $TASKFILES
+
+# remove all empty lines and recode if necessary
+echo -n "Syncing iPod ... [Calendar] "
+ cat $CALFILES $TASKFILES | grep -v '^[[:space:]]$\|^$' | $FILTER | $RECODE > $IPOD_MOUNT/Calendars/evolution
+echo "done!"
Deleted: gtkpod/tags/0.99.10-5/scripts/sync-evolution.sh
===================================================================
--- gtkpod/trunk/scripts/sync-evolution.sh 2007-11-13 14:54:03 UTC (rev 259)
+++ gtkpod/tags/0.99.10-5/scripts/sync-evolution.sh 2007-11-20 13:46:35 UTC (rev 280)
@@ -1,95 +0,0 @@
-#!/bin/sh
-# Script for syncing evolution addressbook data with iPod
-# (c) 2004 Clinton Gormley <clint at traveljury dot com>
-#
-
-# Usage:
-#
-# sync-addressbooks.sh [-i <ipod mountpoint>] [-e <encoding>]
-# [-d <path to evolution-addressbook-export>]
-#
-# (specify '-d' if evolution-addressbook-export is not in your default
-# path)
-#
-# with the following defaults:
-
-IPOD_MOUNT=/media/ipod # mountpoint of ipod
-EVOPATH='/opt/gnome/libexec/evolution/2.0:/usr/lib/evolution/2.0:/opt/gnome/bin' # additional path
-ENCODING=ISO-8859-15 # encoding used by ipod
-
-# Unless called with "-e=none" this script requires "iconv" available
-# from http://www.gnu.org/software/libiconv/
-
-# About the encoding used by the iPod (by Jorg Schuler):
-#
-# For some reason the encoding used for the contact files and
-# calender files depends on the language you have set your iPod
-# to. If you set your iPod to German, iso-8859-15 (or -1?) is
-# expected. If you set it to Japanese, SHIFT-JIS is expected. You need
-# to reboot the iPod to have the change take effect, however. (I'm
-# using firmware version 1.3.)
-#
-# If you know of more encodings, please let me know, so they can be
-# added here:
-#
-# iPod language encoding expected
-# ----------------------------------------
-# German ISO-8859-15
-# Japanese SHIFT-JIS
-
-
-# Changelog:
-#
-# 2004/12/07 (Clinton Gormley <clint at traveljury dot com>):
-# adapted sync-kaddressbook to work with evolution.
-#
-# 2004/12/15 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
-# Split evolution support into a new file.
-#
-# 2007/04/02 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
-# Allow syncing of contacts containing pictures. Thanks to Lars Friedrichs.
-
-
-# overwrite default settings with optional command line arguments
-while getopts i:d:e: option; do
- case $option in
- i) IPOD_MOUNT=$OPTARG;;
- d) EVOPATH=$OPTARG;;
- e) ENCODING=$OPTARG;;
-
- \?) echo "Usage: `basename $0 ` [-i <ipod mountpoint>] [-e <encoding>] [-d <path to evolution-addressbook-export>]"
- exit 1;;
- esac
-done
-
-
-# set the RECODE command
-if [ $ENCODING = "none" ] || [ $ENCODING = "NONE" ]; then
- RECODE="cat" # no conversion
-else
- RECODE="iconv -f UTF-8 -t $ENCODING"
-fi
-
-
-echo "Trying to export from evolution:"
-
-# adjust path to find evolution-addressbook-export
-PATH=$EVOPATH:$PATH
-
-# check if evolution-addressbook-export is in PATH
-evolution-addressbook-export --help >/dev/null 2>&1
-
-if [ ! $? == 0 ]; then
- echo "** Error: Couldn't find evolution-addressbook-export in your PATH:"
- echo $PATH
- echo ""
- echo "Please specify \"-d <path to evolution-addressbook-export>\" when you call this script"
- exit 1
-fi
-
-
-# remove all empty lines and recode if necessary
-echo -n "Syncing iPod ... [Contacts] "
-# Redirect STDERR to avoid the "FIXME : wait for completion unimplemented" warning
-evolution-addressbook-export 2>&1 | grep -v '^[[:space:]]$\|^$' | $RECODE | sed -e "s/PHOTO;ENCODING=b;TYPE=\"X-EVOLUTION-UNKNOWN\"/PHOTO;BASE64/g" > $IPOD_MOUNT/Contacts/evolution
-echo "done!"
Copied: gtkpod/tags/0.99.10-5/scripts/sync-evolution.sh (from rev 266, gtkpod/trunk/scripts/sync-evolution.sh)
===================================================================
--- gtkpod/tags/0.99.10-5/scripts/sync-evolution.sh (rev 0)
+++ gtkpod/tags/0.99.10-5/scripts/sync-evolution.sh 2007-11-20 13:46:35 UTC (rev 280)
@@ -0,0 +1,95 @@
+#!/bin/sh
+# Script for syncing evolution addressbook data with iPod
+# (c) 2004 Clinton Gormley <clint at traveljury dot com>
+#
+
+# Usage:
+#
+# sync-addressbooks.sh [-i <ipod mountpoint>] [-e <encoding>]
+# [-d <path to evolution-addressbook-export>]
+#
+# (specify '-d' if evolution-addressbook-export is not in your default
+# path)
+#
+# with the following defaults:
+
+IPOD_MOUNT=/mnt/ipod # mountpoint of ipod
+EVOPATH='/opt/gnome/libexec/evolution/2.0:/usr/lib/evolution/2.0:/opt/gnome/bin' # additional path
+ENCODING=ISO-8859-15 # encoding used by ipod
+
+# Unless called with "-e=none" this script requires "iconv" available
+# from http://www.gnu.org/software/libiconv/
+
+# About the encoding used by the iPod (by Jorg Schuler):
+#
+# For some reason the encoding used for the contact files and
+# calender files depends on the language you have set your iPod
+# to. If you set your iPod to German, iso-8859-15 (or -1?) is
+# expected. If you set it to Japanese, SHIFT-JIS is expected. You need
+# to reboot the iPod to have the change take effect, however. (I'm
+# using firmware version 1.3.)
+#
+# If you know of more encodings, please let me know, so they can be
+# added here:
+#
+# iPod language encoding expected
+# ----------------------------------------
+# German ISO-8859-15
+# Japanese SHIFT-JIS
+
+
+# Changelog:
+#
+# 2004/12/07 (Clinton Gormley <clint at traveljury dot com>):
+# adapted sync-kaddressbook to work with evolution.
+#
+# 2004/12/15 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
+# Split evolution support into a new file.
+#
+# 2007/04/02 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
+# Allow syncing of contacts containing pictures. Thanks to Lars Friedrichs.
+
+
+# overwrite default settings with optional command line arguments
+while getopts i:d:e: option; do
+ case $option in
+ i) IPOD_MOUNT=$OPTARG;;
+ d) EVOPATH=$OPTARG;;
+ e) ENCODING=$OPTARG;;
+
+ \?) echo "Usage: `basename $0 ` [-i <ipod mountpoint>] [-e <encoding>] [-d <path to evolution-addressbook-export>]"
+ exit 1;;
+ esac
+done
+
+
+# set the RECODE command
+if [ $ENCODING = "none" ] || [ $ENCODING = "NONE" ]; then
+ RECODE="cat" # no conversion
+else
+ RECODE="iconv -f UTF-8 -t $ENCODING"
+fi
+
+
+echo "Trying to export from evolution:"
+
+# adjust path to find evolution-addressbook-export
+PATH=$EVOPATH:$PATH
+
+# check if evolution-addressbook-export is in PATH
+evolution-addressbook-export --help >/dev/null 2>&1
+
+if [ ! $? == 0 ]; then
+ echo "** Error: Couldn't find evolution-addressbook-export in your PATH:"
+ echo $PATH
+ echo ""
+ echo "Please specify \"-d <path to evolution-addressbook-export>\" when you call this script"
+ exit 1
+fi
+
+
+# remove all empty lines and recode if necessary
+echo -n "Syncing iPod ... [Contacts] "
+# Redirect STDERR to avoid the "FIXME : wait for completion unimplemented" warning
+evolution-addressbook-export 2>&1 | grep -v '^[[:space:]]$\|^$' | $RECODE | sed -e "s/PHOTO;ENCODING=b;TYPE=\"X-EVOLUTION-UNKNOWN\"/PHOTO;BASE64/g" > $IPOD_MOUNT/Contacts/evolution
+echo "done!"
Deleted: gtkpod/tags/0.99.10-5/scripts/sync-kaddressbook.sh
===================================================================
--- gtkpod/trunk/scripts/sync-kaddressbook.sh 2007-11-13 14:54:03 UTC (rev 259)
+++ gtkpod/tags/0.99.10-5/scripts/sync-kaddressbook.sh 2007-11-20 13:46:35 UTC (rev 280)
@@ -1,90 +0,0 @@
-#!/bin/sh
-# (c) 2004 Markus Gaugusch <markus at gaugusch dot at>
-# Script for syncing kaddressbook data with iPod
-
-# Usage:
-#
-# sync-kaddressbook.sh [-i <ipod mountpoint>] [-d <kaddressbook data file>]
-# ... [-e <encoding>]
-#
-# with the following defaults:
-
-IPOD_MOUNT=/media/ipod # mountpoint of ipod
-DATAFILE=~/.kde/share/apps/kabc/std.vcf # vcard file
-ENCODING=ISO-8859-15 # encoding used by ipod
-
-# Unless called with "-e none" this script requires "iconv" available
-# from http://www.gnu.org/software/libiconv/
-
-# About the encoding used by the iPod (by Jorg Schuler):
-#
-# For some reason the encoding used for the contact files and
-# calenader files depends on the language you have set your iPod
-# to. If you set your iPod to German, iso-8859-15 (or -1?) is
-# expected. If you set it to Japanese, SHIFT-JIS is expected. You need
-# to reboot the iPod to have the change take effect, however. (I'm
-# using firmware version 1.3.)
-#
-# If you know of more encodings, please let me know, so they can be
-# added here:
-#
-# iPod language encoding expected
-# ----------------------------------------
-# German ISO-8859-15
-# Japanese SHIFT-JIS
-
-
-# Changelog:
-#
-# 2004/06/27 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
-# Changed to accept ipod-mountpath and encoding as command line
-# option
-#
-# Split into two files -- one for contacts, one for calendar.
-#
-# Placed under GPL in agreement with Markus Gaugusch.
-#
-# Added note about encoding used by the iPod.
-#
-# 2004/07/02 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
-# Added Usage-line, added check for vcard file, rearranged source
-#
-# 2004/07/03 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
-# Made "iconv" optional (call with "-e none")
-#
-# Removed "dos2unix" as my iPod (firmware 1.3) happily accepted
-# DOS-type vcards as well. Instead changed the "grep" pattern to
-# catch \cr\lf as well.
-
-
-# overwrite default settings with optional command line arguments
-while getopts i:d:e: option; do
- case $option in
- i) IPOD_MOUNT=$OPTARG;;
- d) DATAFILE=$OPTARG;;
- e) ENCODING=$OPTARG;;
- \?) echo "Usage: `basename $0` [-i <ipod mountpoint>] [-d <kaddressbook data file>] [-e <encoding>]"
- exit 1;;
- esac
-done
-
-
-# set the RECODE command
-if [ $ENCODING = "none" ] || [ $ENCODING = "NONE" ]; then
- RECODE="cat" # no conversion
-else
- RECODE="iconv -f UTF-8 -t $ENCODING"
-fi
-
-
-# check if DATAFILE exists
-if [ ! -f $DATAFILE ]; then
- echo "Error: $DATAFILE does not exist"
- exit 1
-fi
-
-
-# remove all empty lines and recode if necessary
-echo -n "Syncing iPod ... [Contacts] "
-cat $DATAFILE | grep -v '^[[:space:]]$\|^$' | $RECODE > $IPOD_MOUNT/Contacts/`basename $DATAFILE`
-echo "done!"
Copied: gtkpod/tags/0.99.10-5/scripts/sync-kaddressbook.sh (from rev 266, gtkpod/trunk/scripts/sync-kaddressbook.sh)
===================================================================
--- gtkpod/tags/0.99.10-5/scripts/sync-kaddressbook.sh (rev 0)
+++ gtkpod/tags/0.99.10-5/scripts/sync-kaddressbook.sh 2007-11-20 13:46:35 UTC (rev 280)
@@ -0,0 +1,90 @@
+#!/bin/sh
+# (c) 2004 Markus Gaugusch <markus at gaugusch dot at>
+# Script for syncing kaddressbook data with iPod
+
+# Usage:
+#
+# sync-kaddressbook.sh [-i <ipod mountpoint>] [-d <kaddressbook data file>]
+# ... [-e <encoding>]
+#
+# with the following defaults:
+
+IPOD_MOUNT=/mnt/ipod # mountpoint of ipod
+DATAFILE=~/.kde/share/apps/kabc/std.vcf # vcard file
+ENCODING=ISO-8859-15 # encoding used by ipod
+
+# Unless called with "-e none" this script requires "iconv" available
+# from http://www.gnu.org/software/libiconv/
+
+# About the encoding used by the iPod (by Jorg Schuler):
+#
+# For some reason the encoding used for the contact files and
+# calenader files depends on the language you have set your iPod
+# to. If you set your iPod to German, iso-8859-15 (or -1?) is
+# expected. If you set it to Japanese, SHIFT-JIS is expected. You need
+# to reboot the iPod to have the change take effect, however. (I'm
+# using firmware version 1.3.)
+#
+# If you know of more encodings, please let me know, so they can be
+# added here:
+#
+# iPod language encoding expected
+# ----------------------------------------
+# German ISO-8859-15
+# Japanese SHIFT-JIS
+
+
+# Changelog:
+#
+# 2004/06/27 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
+# Changed to accept ipod-mountpath and encoding as command line
+# option
+#
+# Split into two files -- one for contacts, one for calendar.
+#
+# Placed under GPL in agreement with Markus Gaugusch.
+#
+# Added note about encoding used by the iPod.
+#
+# 2004/07/02 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
+# Added Usage-line, added check for vcard file, rearranged source
+#
+# 2004/07/03 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
+# Made "iconv" optional (call with "-e none")
+#
+# Removed "dos2unix" as my iPod (firmware 1.3) happily accepted
+# DOS-type vcards as well. Instead changed the "grep" pattern to
+# catch \cr\lf as well.
+
+
+# overwrite default settings with optional command line arguments
+while getopts i:d:e: option; do
+ case $option in
+ i) IPOD_MOUNT=$OPTARG;;
+ d) DATAFILE=$OPTARG;;
+ e) ENCODING=$OPTARG;;
+ \?) echo "Usage: `basename $0` [-i <ipod mountpoint>] [-d <kaddressbook data file>] [-e <encoding>]"
+ exit 1;;
+ esac
+done
+
+
+# set the RECODE command
+if [ $ENCODING = "none" ] || [ $ENCODING = "NONE" ]; then
+ RECODE="cat" # no conversion
+else
+ RECODE="iconv -f UTF-8 -t $ENCODING"
+fi
+
+
+# check if DATAFILE exists
+if [ ! -f $DATAFILE ]; then
+ echo "Error: $DATAFILE does not exist"
+ exit 1
+fi
+
+
+# remove all empty lines and recode if necessary
+echo -n "Syncing iPod ... [Contacts] "
+cat $DATAFILE | grep -v '^[[:space:]]$\|^$' | $RECODE > $IPOD_MOUNT/Contacts/`basename $DATAFILE`
+echo "done!"
Deleted: gtkpod/tags/0.99.10-5/scripts/sync-korganizer.sh
===================================================================
--- gtkpod/trunk/scripts/sync-korganizer.sh 2007-11-13 14:54:03 UTC (rev 259)
+++ gtkpod/tags/0.99.10-5/scripts/sync-korganizer.sh 2007-11-20 13:46:35 UTC (rev 280)
@@ -1,90 +0,0 @@
-#!/bin/sh
-# (c) 2004 Markus Gaugusch <markus at gaugusch.at>
-# Script for syncing korganizer data with iPod
-
-# Usage:
-#
-# sync-kaddressbook.sh [-i <ipod mountpoint>] [-d <korganizer data file>]
-# ... [-e <encoding>]
-#
-# with the following defaults:
-
-IPOD_MOUNT=/media/ipod # mountpoint of ipod
-DATAFILE=~/.kde/share/apps/korganizer/std.ics # calendar data file
-ENCODING=ISO-8859-15 # encoding used by ipod
-
-# Unless called with "-e none" this script requires "iconv" available
-# from http://www.gnu.org/software/libiconv/
-
-# About the encoding used by the iPod (by Jorg Schuler):
-#
-# For some reason the encoding used for the contact files and
-# calenader files depends on the language you have set your iPod
-# to. If you set your iPod to German, iso-8859-15 (or -1?) is
-# expected. If you set it to Japanese, SHIFT-JIS is expected. You need
-# to reboot the iPod to have the change take effect, however. (I'm
-# using firmware version 1.3.)
-#
-# If you know of more encodings, please let me know, so they can be
-# added here:
-#
-# iPod language encoding expected
-# ----------------------------------------
-# German ISO-8859-15
-# Japanese SHIFT-JIS
-
-
-# Changelog:
-#
-# 2004/06/27 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
-# Changed to accept ipod-mountpath and encoding as command line
-# option
-#
-# Split into two files -- one for contacts, one for calendar.
-#
-# Placed under GPL in agreement with Markus Gaugusch.
-#
-# Added note about encoding used by the iPod.
-#
-# 2004/07/02 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
-# Added Usage-line, added check for vcard file, rearranged source
-#
-# 2004/07/03 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
-# Made "iconv" optional (call with "-e none")
-#
-# Removed "dos2unix" as my iPod (firmware 1.3) happily accepted
-# DOS-type vcards as well. Instead changed the "grep" pattern to
-# catch \cr\lf as well.
-
-
-# overwrite default settings with optional command line arguments
-while getopts i:d:e: option; do
- case $option in
- i) IPOD_MOUNT=$OPTARG;;
- d) DATAFILE=$OPTARG;;
- e) ENCODING=$OPTARG;;
- \?) echo "Usage: `basename $0` [-i <ipod mountpoint>] [-d <korganizer data file>] [-e <encoding>]"
- exit 1;;
- esac
-done
-
-
-# set the RECODE command
-if [ $ENCODING = "none" ] || [ $ENCODING = "NONE" ]; then
- RECODE="cat" # no conversion
-else
- RECODE="iconv -f UTF-8 -t $ENCODING"
-fi
-
-
-# check if DATAFILE exists
-if [ ! -f $DATAFILE ]; then
- echo "Error: $DATAFILE does not exist"
- exit 1
-fi
-
-
-# remove all empty lines and recode if necessary
-echo -n "Syncing iPod ... [Calendar] "
-cat $DATAFILE | grep -v '^[[:space:]]$\|^$' | $RECODE > $IPOD_MOUNT/Calendars/`basename $DATAFILE`
-echo "done!"
Copied: gtkpod/tags/0.99.10-5/scripts/sync-korganizer.sh (from rev 266, gtkpod/trunk/scripts/sync-korganizer.sh)
===================================================================
--- gtkpod/tags/0.99.10-5/scripts/sync-korganizer.sh (rev 0)
+++ gtkpod/tags/0.99.10-5/scripts/sync-korganizer.sh 2007-11-20 13:46:35 UTC (rev 280)
@@ -0,0 +1,90 @@
+#!/bin/sh
+# (c) 2004 Markus Gaugusch <markus at gaugusch.at>
+# Script for syncing korganizer data with iPod
+
+# Usage:
+#
+# sync-kaddressbook.sh [-i <ipod mountpoint>] [-d <korganizer data file>]
+# ... [-e <encoding>]
+#
+# with the following defaults:
+
+IPOD_MOUNT=/mnt/ipod # mountpoint of ipod
+DATAFILE=~/.kde/share/apps/korganizer/std.ics # calendar data file
+ENCODING=ISO-8859-15 # encoding used by ipod
+
+# Unless called with "-e none" this script requires "iconv" available
+# from http://www.gnu.org/software/libiconv/
+
+# About the encoding used by the iPod (by Jorg Schuler):
+#
+# For some reason the encoding used for the contact files and
+# calenader files depends on the language you have set your iPod
+# to. If you set your iPod to German, iso-8859-15 (or -1?) is
+# expected. If you set it to Japanese, SHIFT-JIS is expected. You need
+# to reboot the iPod to have the change take effect, however. (I'm
+# using firmware version 1.3.)
+#
+# If you know of more encodings, please let me know, so they can be
+# added here:
+#
+# iPod language encoding expected
+# ----------------------------------------
+# German ISO-8859-15
+# Japanese SHIFT-JIS
+
+
+# Changelog:
+#
+# 2004/06/27 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
+# Changed to accept ipod-mountpath and encoding as command line
+# option
+#
+# Split into two files -- one for contacts, one for calendar.
+#
+# Placed under GPL in agreement with Markus Gaugusch.
+#
+# Added note about encoding used by the iPod.
+#
+# 2004/07/02 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
+# Added Usage-line, added check for vcard file, rearranged source
+#
+# 2004/07/03 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
+# Made "iconv" optional (call with "-e none")
+#
+# Removed "dos2unix" as my iPod (firmware 1.3) happily accepted
+# DOS-type vcards as well. Instead changed the "grep" pattern to
+# catch \cr\lf as well.
+
+
+# overwrite default settings with optional command line arguments
+while getopts i:d:e: option; do
+ case $option in
+ i) IPOD_MOUNT=$OPTARG;;
+ d) DATAFILE=$OPTARG;;
+ e) ENCODING=$OPTARG;;
+ \?) echo "Usage: `basename $0` [-i <ipod mountpoint>] [-d <korganizer data file>] [-e <encoding>]"
+ exit 1;;
+ esac
+done
+
+
+# set the RECODE command
+if [ $ENCODING = "none" ] || [ $ENCODING = "NONE" ]; then
+ RECODE="cat" # no conversion
+else
+ RECODE="iconv -f UTF-8 -t $ENCODING"
+fi
+
+
+# check if DATAFILE exists
+if [ ! -f $DATAFILE ]; then
+ echo "Error: $DATAFILE does not exist"
+ exit 1
+fi
+
+
+# remove all empty lines and recode if necessary
+echo -n "Syncing iPod ... [Calendar] "
+cat $DATAFILE | grep -v '^[[:space:]]$\|^$' | $RECODE > $IPOD_MOUNT/Calendars/`basename $DATAFILE`
+echo "done!"
Deleted: gtkpod/tags/0.99.10-5/scripts/sync-ldif.sh
===================================================================
--- gtkpod/trunk/scripts/sync-ldif.sh 2007-11-13 14:54:03 UTC (rev 259)
+++ gtkpod/tags/0.99.10-5/scripts/sync-ldif.sh 2007-11-20 13:46:35 UTC (rev 280)
@@ -1,158 +0,0 @@
-#! /bin/sh
-
-# Placed under GPL; to know more, see:
-# http://www.gnu.org/licenses/licenses.html
-#
-# if you make any change, I would be happy to be kept advised by
-# sending an email at <sberidot at libertysurf dot fr>.
-#
-# Write "[sync-ldif.sh]" in the subject, otherwise the message is
-# bound to be considered as spam... :(
-#
-#
-# RESTRICTION : I haven't managed yet to read correctly data from
-# ldif files when accents are used, Thunderbird writes the names
-# differently...This is still Chinese for me!! :)
-
-export LDIFAMILYNAME=contactIPOD # Filenames will look like $LDIFAMILYNAMEXX.vcf, X=[0-9]
-export IPOD_MOUNT=/media/ipod # Mount point of the ipod
-declare LDIFILE=addressbook.ldif # default filename 'addressbook.ldif'
-declare ENCODING=ISO-8859-15 # To try others encodings : 'iconv --list'
-declare DELETE="NO" # To delete old .vcf files by default? 'NO'!!
-
-# Exiting function
-function EXITING {
- export -n LDIFAMILYNAME
- export -n IPOD_MOUNT
-}
-
-# Please HELP!!! :)
-function DISPLAY_HELP {
- cat <<- EOF
- Beware not to share the same familyname with old .vcf in the ipod directory;
- no one precaution is taken, so files will be overwritten. :(
- For the moment, I did not manage to make accents be displayed properly,
- but still working on it. Enjoy!
-
- Default options:
- Current Ipod directory is : $IPOD_MOUNT
- Current Encoding : $ENCODING
- Current template for filenames : $LDIFAMILYNAME[1-9*].vcf
- $(basename $0) doesn't delete old .vcf files by default, but overwrites.
-
- Options:
- Syntax : $(basename $0) -f addbook.ldif -m /media/ipod -n contactIPOD -d (-h)
- [-f] addbook.ldif : contains the .ldif Filename
- [-m] /media/ipod : contains the ipod Mounted directory
- [-n] contactIPOD : contains the .vcf family fileName
- [-d] : contains the option to Delete all old .vcf files
- [-h] : contains this Help
- EOF
-}
-
-# $1 contains the directory to be tested
-# Is/Are .vcf file(s) present?
-function TST_VCF {
- local j
- for j in "${1%%/}/"* ; do
- if [ "${j##*.}" = "vcf" ] ; then
- return 0
- break
- fi
- done
- return 1
-}
-
-# $1 contains the util name
-# Is $1 already installed?
-function TST_UTIL {
- which "$1" >/dev/null 2>&1
- if [ "$?" != "0" ]; then
- echo "[INSTALL] $1 utility not found, please install $1 package first!"
- EXITING
- exit 3
- fi
-}
-
-# $1 contains the .vcf filename
-# extracts names from .vcf filename
-function EXTRACT_CONTACT_FROM_VCF {
- local NAME="UNKNOWN"
- if [ -e "$1" ] ; then
- NAME=$(grep "fn:" "$1")
- NAME=${NAME:3}
- fi
- echo "$NAME"
-}
-
-function DELETE_VCFILE_FROM_IPOD {
- # if no .vcf file's found, exit!
- if ! TST_VCF "$IPOD_MOUNT"/Contacts/ ; then
- echo "[DELETING] no file detected"
- return
- fi
- # begin to delete
- local i
- for i in "$IPOD_MOUNT"/Contacts/*.vcf ; do
- echo "[DELETING] " $(EXTRACT_CONTACT_FROM_VCF "$i") "from ${i##*/}"
- rm -f "$i"
- done
-}
-
-# Is Ipod Directory valid?
-function IS_IPOD_DIR_VALID {
- # Test of the $IPOD_MOUNT directory
- if [ ! -d "$IPOD_MOUNT/Contacts/" ]; then
- echo "$IPOD_MOUNT/Contacts invalid... Exiting."
- EXITING
- exit 2
- fi
-}
-
-# Program's starting here!
-
-# Testing awk and iconv utils...
-TST_UTIL "awk"
-TST_UTIL "iconv"
-
-# picking up and processing parameters from prompt...
-while getopts ":f:m:n:dh:" option ; do
- case $option in
- f ) LDIFILE="$OPTARG";;
- m ) IPOD_MOUNT="${OPTARG%%/}";;
- n ) LDIFAMILYNAME="$OPTARG";;
- d ) DELETE="OK";;
- h | * ) DISPLAY_HELP; EXITING; exit 1;;
- esac
-done
-
-# check, if not valid, exit!
-IS_IPOD_DIR_VALID
-
-# Is LDIFILE really a ldif file? just testing the extension, and if the file exists...
-if [ "${LDIFILE##*.}" == "ldif" ] || [ "${LDIFILE##*.}" == "LDIF" ] && [ -e "$LDIFILE" ] ; then
- # The $IPOD_MOUNT/Contacts/ directory will be emptied if '-d' option!
- if [ "$DELETE" == "OK" ]; then
- echo "Old contacts being deleted from $IPOD_MOUNT. Work in progress..."
- DELETE_VCFILE_FROM_IPOD
- sleep 1
- fi
-
- echo "New contacts being synchronised from $LDIFILE. Work in progress..."
- # Translation from LDIF into VCF, in order to cut standard output in vcf files...
- # Converting into vcf stream | converting to ENCODING | detection of VCF card
- # and writing it into the Ipod
- ldif2vcf.sh < "$LDIFILE" | iconv -f UTF-8 -t $ENCODING | awk 'BEGIN{RS="\n"; NAME=""; CARD=""; VCFILE=""; NCARD=1} /^fn:/ {NAME=substr($0,4)} /^$/{next} /^end:vcard/ {VCFILE = ENVIRON["IPOD_MOUNT"] "/Contacts/" ENVIRON["LDIFAMILYNAME"] (NCARD-1) ".vcf"; print "[WRITING] " NAME " in " ENVIRON["LDIFAMILYNAME"] (NCARD-1) ".vcf"; print CARD "end:vcard" > VCFILE; CARD=""; VCFILE=""; NCARD++; next} {CARD=CARD $0 RS} END{print (NCARD-1) " vcards added."}' # >/dev/null 2>&1
-
- if [ "$?" != "0" ]; then
- echo "[ERROR] An error occured, exiting, sorry for that... Please Report!"
- EXITING
- exit 1
- fi
- echo "complete!"
-else
- DISPLAY_HELP
-fi
-
-EXITING
-exit 0
Copied: gtkpod/tags/0.99.10-5/scripts/sync-ldif.sh (from rev 275, gtkpod/trunk/scripts/sync-ldif.sh)
===================================================================
--- gtkpod/tags/0.99.10-5/scripts/sync-ldif.sh (rev 0)
+++ gtkpod/tags/0.99.10-5/scripts/sync-ldif.sh 2007-11-20 13:46:35 UTC (rev 280)
@@ -0,0 +1,158 @@
+#! /bin/sh
+
+# Placed under GPL; to know more, see:
+# http://www.gnu.org/licenses/licenses.html
+#
+# if you make any change, I would be happy to be kept advised by
+# sending an email at <sberidot at libertysurf dot fr>.
+#
+# Write "[sync-ldif.sh]" in the subject, otherwise the message is
+# bound to be considered as spam... :(
+#
+#
+# RESTRICTION : I haven't managed yet to read correctly data from
+# ldif files when accents are used, Thunderbird writes the names
+# differently...This is still Chinese for me!! :)
+
+export LDIFAMILYNAME=contactIPOD # Filenames will look like $LDIFAMILYNAMEXX.vcf, X=[0-9]
+export IPOD_MOUNT=/mnt/ipod # Mount point of the ipod
+declare LDIFILE=addressbook.ldif # default filename 'addressbook.ldif'
+declare ENCODING=ISO-8859-15 # To try others encodings : 'iconv --list'
+declare DELETE="NO" # To delete old .vcf files by default? 'NO'!!
+
+# Exiting function
+function EXITING {
+ export -n LDIFAMILYNAME
+ export -n IPOD_MOUNT
+}
+
+# Please HELP!!! :)
+function DISPLAY_HELP {
+ cat <<- EOF
+ Beware not to share the same familyname with old .vcf in the ipod directory;
+ no one precaution is taken, so files will be overwritten. :(
+ For the moment, I did not manage to make accents be displayed properly,
+ but still working on it. Enjoy!
+
+ Default options:
+ Current Ipod directory is : $IPOD_MOUNT
+ Current Encoding : $ENCODING
+ Current template for filenames : $LDIFAMILYNAME[1-9*].vcf
+ $(basename $0) doesn't delete old .vcf files by default, but overwrites.
+
+ Options:
+ Syntax : $(basename $0) -f addbook.ldif -m /media/ipod -n contactIPOD -d (-h)
+ [-f] addbook.ldif : contains the .ldif Filename
+ [-m] /media/ipod : contains the ipod Mounted directory
+ [-n] contactIPOD : contains the .vcf family fileName
+ [-d] : contains the option to Delete all old .vcf files
+ [-h] : contains this Help
+ EOF
+}
+
+# $1 contains the directory to be tested
+# Is/Are .vcf file(s) present?
+function TST_VCF {
+ local j
+ for j in "${1%%/}/"* ; do
+ if [ "${j##*.}" = "vcf" ] ; then
+ return 0
+ break
+ fi
+ done
+ return 1
+}
+
+# $1 contains the util name
+# Is $1 already installed?
+function TST_UTIL {
+ which "$1" >/dev/null 2>&1
+ if [ "$?" != "0" ]; then
+ echo "[INSTALL] $1 utility not found, please install $1 package first!"
+ EXITING
+ exit 3
+ fi
+}
+
+# $1 contains the .vcf filename
+# extracts names from .vcf filename
+function EXTRACT_CONTACT_FROM_VCF {
+ local NAME="UNKNOWN"
+ if [ -e "$1" ] ; then
+ NAME=$(grep "fn:" "$1")
+ NAME=${NAME:3}
+ fi
+ echo "$NAME"
+}
+
+function DELETE_VCFILE_FROM_IPOD {
+ # if no .vcf file's found, exit!
+ if ! TST_VCF "$IPOD_MOUNT"/Contacts/ ; then
+ echo "[DELETING] no file detected"
+ return
+ fi
+ # begin to delete
+ local i
+ for i in "$IPOD_MOUNT"/Contacts/*.vcf ; do
+ echo "[DELETING] " $(EXTRACT_CONTACT_FROM_VCF "$i") "from ${i##*/}"
+ rm -f "$i"
+ done
+}
+
+# Is Ipod Directory valid?
+function IS_IPOD_DIR_VALID {
+ # Test of the $IPOD_MOUNT directory
+ if [ ! -d "$IPOD_MOUNT/Contacts/" ]; then
+ echo "$IPOD_MOUNT/Contacts invalid... Exiting."
+ EXITING
+ exit 2
+ fi
+}
+
+# Program's starting here!
+
+# Testing awk and iconv utils...
+TST_UTIL "awk"
+TST_UTIL "iconv"
+
+# picking up and processing parameters from prompt...
+while getopts ":f:m:n:dh:" option ; do
+ case $option in
+ f ) LDIFILE="$OPTARG";;
+ m ) IPOD_MOUNT="${OPTARG%%/}";;
+ n ) LDIFAMILYNAME="$OPTARG";;
+ d ) DELETE="OK";;
+ h | * ) DISPLAY_HELP; EXITING; exit 1;;
+ esac
+done
+
+# check, if not valid, exit!
+IS_IPOD_DIR_VALID
+
+# Is LDIFILE really a ldif file? just testing the extension, and if the file exists...
+if [ "${LDIFILE##*.}" == "ldif" ] || [ "${LDIFILE##*.}" == "LDIF" ] && [ -e "$LDIFILE" ] ; then
+ # The $IPOD_MOUNT/Contacts/ directory will be emptied if '-d' option!
+ if [ "$DELETE" == "OK" ]; then
+ echo "Old contacts being deleted from $IPOD_MOUNT. Work in progress..."
+ DELETE_VCFILE_FROM_IPOD
+ sleep 1
+ fi
+
+ echo "New contacts being synchronised from $LDIFILE. Work in progress..."
+ # Translation from LDIF into VCF, in order to cut standard output in vcf files...
+ # Converting into vcf stream | converting to ENCODING | detection of VCF card
+ # and writing it into the Ipod
+ ldif2vcf.sh < "$LDIFILE" | iconv -f UTF-8 -t $ENCODING | awk 'BEGIN{RS="\n"; NAME=""; CARD=""; VCFILE=""; NCARD=1} /^fn:/ {NAME=substr($0,4)} /^$/{next} /^end:vcard/ {VCFILE = ENVIRON["IPOD_MOUNT"] "/Contacts/" ENVIRON["LDIFAMILYNAME"] (NCARD-1) ".vcf"; print "[WRITING] " NAME " in " ENVIRON["LDIFAMILYNAME"] (NCARD-1) ".vcf"; print CARD "end:vcard" > VCFILE; CARD=""; VCFILE=""; NCARD++; next} {CARD=CARD $0 RS} END{print (NCARD-1) " vcards added."}' # >/dev/null 2>&1
+
+ if [ "$?" != "0" ]; then
+ echo "[ERROR] An error occured, exiting, sorry for that... Please Report!"
+ EXITING
+ exit 1
+ fi
+ echo "complete!"
+else
+ DISPLAY_HELP
+fi
+
+EXITING
+exit 0
Deleted: gtkpod/tags/0.99.10-5/scripts/sync-thunderbird-nano.sh
===================================================================
--- gtkpod/trunk/scripts/sync-thunderbird-nano.sh 2007-11-13 14:54:03 UTC (rev 259)
+++ gtkpod/tags/0.99.10-5/scripts/sync-thunderbird-nano.sh 2007-11-20 13:46:35 UTC (rev 280)
@@ -1,97 +0,0 @@
-#!/bin/sh
-#
-# Script for syncing thunderbird addressbook data with iPod Nano
-#
-# It appears as if the old iPod Nano firmware only displayed the first
-# entry of a vcf file (the issue doesn't seem to exist with current
-# versions of the firmware). This script writes one vcf file per
-# address in your address book and could therefore also be useful
-# non-Nano users.
-#
-# (c) 2006 Paul Oremland <paul at oremland dot net>
-
-# Usage:
-#
-# sync-thunderbird-nano.sh [-i <ipod mountpoint>] [-e <encoding>]
-# [-d <path to thunderbird address book>]
-# [-n <name of exported file>]
-#
-# specify '-d' if your thunderbird address book is not in
-# ~/.thunderbird/
-#
-# specify '-n' if you want to export more than one address book
-# (otherwise the second call to this script will overwrite the output
-# of the first call)
-
-# with the following defaults:
-
-IPOD_MOUNT=/media/ipod # mountpoint of ipod
-ENCODING=ISO-8859-15 # encoding used by ipod
-NAME=thunderbird # default file export name
-FILE_FLAG='' # flag used to determine end of file
-let COUNT=0; # file counter
-
-# Unless called with "-e=none" this script requires "recode" available
-# from ftp://ftp.iro.umontreal.ca/pub/recode/recode-3.6.tar.gz
-
-# About the encoding used by the iPod (by Jorg Schuler):
-#
-# For some reason the encoding used for the contact files and
-# calender files depends on the language you have set your iPod
-# to. If you set your iPod to German, iso-8859-15 (or -1?) is
-# expected. If you set it to Japanese, SHIFT-JIS is expected. You need
-# to reboot the iPod to have the change take effect, however. (I'm
-# using firmware version 1.3.)
-#
-# If you know of more encodings, please let me know, so they can be
-# added here:
-#
-# iPod language encoding expected
-# ----------------------------------------
-# German ISO-8859-15
-# Japanese SHIFT-JIS
-
-
-# Changelog:
-#
-# 2006/04/10 (Paul Oremland <paul at oremland dot net>):
-# break vcf file out into individual vcf files per contact
-
-
-# overwrite default settings with optional command line arguments
-while getopts i:d:e:n: option; do
- case $option in
- i) IPOD_MOUNT=$OPTARG;;
- d) THUNPATH=$OPTARG;;
- e) ENCODING=$OPTARG;;
- n) NAME=$OPTARG;;
-
- \?) echo "Usage: `basename $0 ` [-i <ipod mountpoint>] [-e <encoding>] [-d <path to thunderbird address book>] [-n <name of exported file>]"
- exit 1;;
- esac
-done
-
-
-echo "Exporting Contacts:"
-SYNC="$(dirname $0)/sync-thunderbird.sh -i ${IPOD_MOUNT} -e ${ENCODING} -d ${THUNPATH} -n ${NAME}"
-$SYNC
-
-echo "Breaking apart VCF file into individual contacts"
-for line in $(cat $IPOD_MOUNT/Contacts/${NAME}.vcf | sed "s/\ /[54321]/g")
-do
- if [ "$FILE_FLAG" = 'END' ]; then
- let COUNT=$COUNT+1;
- fi
-
- echo $line | sed "s/\[54321\]/\ /g" >> $IPOD_MOUNT/Contacts/${NAME}$COUNT.vcf
-
- if [ "$line" = 'END:VCARD' ]; then
- echo "Finished Writing ${NAME}$COUNT.vcf"
- FILE_FLAG="END";
- else
- FILE_FLAG='';
- fi
-done
-
-echo "Removing ${NAME}.vcf"
-rm $IPOD_MOUNT/Contacts/${NAME}.vcf
Copied: gtkpod/tags/0.99.10-5/scripts/sync-thunderbird-nano.sh (from rev 266, gtkpod/trunk/scripts/sync-thunderbird-nano.sh)
===================================================================
--- gtkpod/tags/0.99.10-5/scripts/sync-thunderbird-nano.sh (rev 0)
+++ gtkpod/tags/0.99.10-5/scripts/sync-thunderbird-nano.sh 2007-11-20 13:46:35 UTC (rev 280)
@@ -0,0 +1,97 @@
+#!/bin/sh
+#
+# Script for syncing thunderbird addressbook data with iPod Nano
+#
+# It appears as if the old iPod Nano firmware only displayed the first
+# entry of a vcf file (the issue doesn't seem to exist with current
+# versions of the firmware). This script writes one vcf file per
+# address in your address book and could therefore also be useful
+# non-Nano users.
+#
+# (c) 2006 Paul Oremland <paul at oremland dot net>
+
+# Usage:
+#
+# sync-thunderbird-nano.sh [-i <ipod mountpoint>] [-e <encoding>]
+# [-d <path to thunderbird address book>]
+# [-n <name of exported file>]
+#
+# specify '-d' if your thunderbird address book is not in
+# ~/.thunderbird/
+#
+# specify '-n' if you want to export more than one address book
+# (otherwise the second call to this script will overwrite the output
+# of the first call)
+
+# with the following defaults:
+
+IPOD_MOUNT=/mnt/ipod # mountpoint of ipod
+ENCODING=ISO-8859-15 # encoding used by ipod
+NAME=thunderbird # default file export name
+FILE_FLAG='' # flag used to determine end of file
+let COUNT=0; # file counter
+
+# Unless called with "-e=none" this script requires "recode" available
+# from ftp://ftp.iro.umontreal.ca/pub/recode/recode-3.6.tar.gz
+
+# About the encoding used by the iPod (by Jorg Schuler):
+#
+# For some reason the encoding used for the contact files and
+# calender files depends on the language you have set your iPod
+# to. If you set your iPod to German, iso-8859-15 (or -1?) is
+# expected. If you set it to Japanese, SHIFT-JIS is expected. You need
+# to reboot the iPod to have the change take effect, however. (I'm
+# using firmware version 1.3.)
+#
+# If you know of more encodings, please let me know, so they can be
+# added here:
+#
+# iPod language encoding expected
+# ----------------------------------------
+# German ISO-8859-15
+# Japanese SHIFT-JIS
+
+
+# Changelog:
+#
+# 2006/04/10 (Paul Oremland <paul at oremland dot net>):
+# break vcf file out into individual vcf files per contact
+
+
+# overwrite default settings with optional command line arguments
+while getopts i:d:e:n: option; do
+ case $option in
+ i) IPOD_MOUNT=$OPTARG;;
+ d) THUNPATH=$OPTARG;;
+ e) ENCODING=$OPTARG;;
+ n) NAME=$OPTARG;;
+
+ \?) echo "Usage: `basename $0 ` [-i <ipod mountpoint>] [-e <encoding>] [-d <path to thunderbird address book>] [-n <name of exported file>]"
+ exit 1;;
+ esac
+done
+
+
+echo "Exporting Contacts:"
+SYNC="$(dirname $0)/sync-thunderbird.sh -i ${IPOD_MOUNT} -e ${ENCODING} -d ${THUNPATH} -n ${NAME}"
+$SYNC
+
+echo "Breaking apart VCF file into individual contacts"
+for line in $(cat $IPOD_MOUNT/Contacts/${NAME}.vcf | sed "s/\ /[54321]/g")
+do
+ if [ "$FILE_FLAG" = 'END' ]; then
+ let COUNT=$COUNT+1;
+ fi
+
+ echo $line | sed "s/\[54321\]/\ /g" >> $IPOD_MOUNT/Contacts/${NAME}$COUNT.vcf
+
+ if [ "$line" = 'END:VCARD' ]; then
+ echo "Finished Writing ${NAME}$COUNT.vcf"
+ FILE_FLAG="END";
+ else
+ FILE_FLAG='';
+ fi
+done
+
+echo "Removing ${NAME}.vcf"
+rm $IPOD_MOUNT/Contacts/${NAME}.vcf
Deleted: gtkpod/tags/0.99.10-5/scripts/sync-thunderbird.sh
===================================================================
--- gtkpod/trunk/scripts/sync-thunderbird.sh 2007-11-13 14:54:03 UTC (rev 259)
+++ gtkpod/tags/0.99.10-5/scripts/sync-thunderbird.sh 2007-11-20 13:46:35 UTC (rev 280)
@@ -1,87 +0,0 @@
-#!/bin/sh
-# Script for syncing thunderbird addressbook data with iPod
-# (c) 2004 Clinton Gormley <clint at traveljury dot com>
-#
-
-# Usage:
-#
-# sync-thunderbird.sh [-i <ipod mountpoint>] [-e <encoding>]
-# [-d <path to thunderbird address book>]
-# [-n <name of exported file>]
-#
-# specify '-d' if your thunderbird address book is not in
-# ~/.thunderbird/
-#
-# specify '-n' if you want to export more than one address book
-# (otherwise the second call to this script will overwrite the output
-# of the first call)
-
-# with the following defaults:
-
-IPOD_MOUNT=/media/ipod # mountpoint of ipod
-ENCODING=ISO-8859-15 # encoding used by ipod
-NAME=thunderbird # default file export name
-
-# Unless called with "-e=none" this script requires "recode" available
-# from ftp://ftp.iro.umontreal.ca/pub/recode/recode-3.6.tar.gz
-
-# About the encoding used by the iPod (by Jorg Schuler):
-#
-# For some reason the encoding used for the contact files and
-# calender files depends on the language you have set your iPod
-# to. If you set your iPod to German, iso-8859-15 (or -1?) is
-# expected. If you set it to Japanese, SHIFT-JIS is expected. You need
-# to reboot the iPod to have the change take effect, however. (I'm
-# using firmware version 1.3.)
-#
-# If you know of more encodings, please let me know, so they can be
-# added here:
-#
-# iPod language encoding expected
-# ----------------------------------------
-# German ISO-8859-15
-# Japanese SHIFT-JIS
-
-
-# Changelog:
-#
-# 2005/05/18 (Clinton Gormley <clint at traveljury dot com>):
-# adapted sync-kaddressbook to work with thunderbird.
-#
-# 2004/12/15 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
-# Split evolution support into a new file.
-#
-# 2005/06/23 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
-# use 'iconv' instead of 'recode'
-
-
-# overwrite default settings with optional command line arguments
-while getopts i:d:e:n: option; do
- case $option in
- i) IPOD_MOUNT=$OPTARG;;
- d) THUNPATH=$OPTARG;;
- e) ENCODING=$OPTARG;;
- n) NAME=$OPTARG;;
-
- \?) echo "Usage: `basename $0 ` [-i <ipod mountpoint>] [-e <encoding>] [-d <path to thunderbird address book>] [-n <name of exported file>]"
- exit 1;;
- esac
-done
-
-
-# set the RECODE command
-if [ $ENCODING = "none" ] || [ $ENCODING = "NONE" ]; then
- RECODE="cat" # no conversion
-else
- RECODE="iconv -f UTF-8 -t $ENCODING"
-fi
-
-
-echo "Trying to export from thunderbird:"
-
-MAB2VCARD=`dirname $0`/mab2vcard
-
-# remove all empty lines and recode if necessary
-echo -n "Syncing iPod ... [Contacts] "
-$MAB2VCARD $THUNPATH | grep -v '^[[:space:]]$\|^$' | $RECODE > $IPOD_MOUNT/Contacts/${NAME}.vcf
-echo "done!"
Copied: gtkpod/tags/0.99.10-5/scripts/sync-thunderbird.sh (from rev 266, gtkpod/trunk/scripts/sync-thunderbird.sh)
===================================================================
--- gtkpod/tags/0.99.10-5/scripts/sync-thunderbird.sh (rev 0)
+++ gtkpod/tags/0.99.10-5/scripts/sync-thunderbird.sh 2007-11-20 13:46:35 UTC (rev 280)
@@ -0,0 +1,87 @@
+#!/bin/sh
+# Script for syncing thunderbird addressbook data with iPod
+# (c) 2004 Clinton Gormley <clint at traveljury dot com>
+#
+
+# Usage:
+#
+# sync-thunderbird.sh [-i <ipod mountpoint>] [-e <encoding>]
+# [-d <path to thunderbird address book>]
+# [-n <name of exported file>]
+#
+# specify '-d' if your thunderbird address book is not in
+# ~/.thunderbird/
+#
+# specify '-n' if you want to export more than one address book
+# (otherwise the second call to this script will overwrite the output
+# of the first call)
+
+# with the following defaults:
+
+IPOD_MOUNT=/mnt/ipod # mountpoint of ipod
+ENCODING=ISO-8859-15 # encoding used by ipod
+NAME=thunderbird # default file export name
+
+# Unless called with "-e=none" this script requires "recode" available
+# from ftp://ftp.iro.umontreal.ca/pub/recode/recode-3.6.tar.gz
+
+# About the encoding used by the iPod (by Jorg Schuler):
+#
+# For some reason the encoding used for the contact files and
+# calender files depends on the language you have set your iPod
+# to. If you set your iPod to German, iso-8859-15 (or -1?) is
+# expected. If you set it to Japanese, SHIFT-JIS is expected. You need
+# to reboot the iPod to have the change take effect, however. (I'm
+# using firmware version 1.3.)
+#
+# If you know of more encodings, please let me know, so they can be
+# added here:
+#
+# iPod language encoding expected
+# ----------------------------------------
+# German ISO-8859-15
+# Japanese SHIFT-JIS
+
+
+# Changelog:
+#
+# 2005/05/18 (Clinton Gormley <clint at traveljury dot com>):
+# adapted sync-kaddressbook to work with thunderbird.
+#
+# 2004/12/15 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
+# Split evolution support into a new file.
+#
+# 2005/06/23 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
+# use 'iconv' instead of 'recode'
+
+
+# overwrite default settings with optional command line arguments
+while getopts i:d:e:n: option; do
+ case $option in
+ i) IPOD_MOUNT=$OPTARG;;
+ d) THUNPATH=$OPTARG;;
+ e) ENCODING=$OPTARG;;
+ n) NAME=$OPTARG;;
+
+ \?) echo "Usage: `basename $0 ` [-i <ipod mountpoint>] [-e <encoding>] [-d <path to thunderbird address book>] [-n <name of exported file>]"
+ exit 1;;
+ esac
+done
+
+
+# set the RECODE command
+if [ $ENCODING = "none" ] || [ $ENCODING = "NONE" ]; then
+ RECODE="cat" # no conversion
+else
+ RECODE="iconv -f UTF-8 -t $ENCODING"
+fi
+
+
+echo "Trying to export from thunderbird:"
+
+MAB2VCARD=`dirname $0`/mab2vcard
+
+# remove all empty lines and recode if necessary
+echo -n "Syncing iPod ... [Contacts] "
+$MAB2VCARD $THUNPATH | grep -v '^[[:space:]]$\|^$' | $RECODE > $IPOD_MOUNT/Contacts/${NAME}.vcf
+echo "done!"
Deleted: gtkpod/tags/0.99.10-5/scripts/sync-webcalendar.sh
===================================================================
--- gtkpod/trunk/scripts/sync-webcalendar.sh 2007-11-13 14:54:03 UTC (rev 259)
+++ gtkpod/tags/0.99.10-5/scripts/sync-webcalendar.sh 2007-11-20 13:46:35 UTC (rev 280)
@@ -1,63 +0,0 @@
-#!/bin/sh
-# (c) 2005 Daniel Kercher
-# sync ipod with webcalendar
-
-# Usage:
-#
-# sync-webcalendar.sh [-i <ipod mountpoint>] [-d <webcalendar uri>] [-c <calendar name>]
-#
-# with the following defaults:
-
-# mount point of ipod
-IPOD_MOUNT='/media/ipod'
-# uri for webcalendar (example)
-DATAFILE='https://somewhere.local/calendar.ics'
-# calendar name
-CALENDAR='webcalendar'
-# special options for wget
-WGET_OPTIONS='--no-check-certificate'
-
-# About the encoding used by the iPod (by Jorg Schuler):
-#
-# For some reason the encoding used for the contact files and
-# calenader files depends on the language you have set your iPod
-# to. If you set your iPod to German, iso-8859-15 (or -1?) is
-# expected. If you set it to Japanese, SHIFT-JIS is expected. You need
-# to reboot the iPod to have the change take effect, however. (I'm
-# using firmware version 1.3.)
-#
-# If you know of more encodings, please let me know, so they can be
-# added here:
-#
-# iPod language encoding expected
-# ----------------------------------------
-# German ISO-8859-15
-# Japanese SHIFT-JIS
-
-# Changelog
-#
-# 2007/02/01 (Giray Devlet <giray at devlet.cc>): Multi Calendar Support
-#
-# 2005/06/15 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
-# Received original script from Daniel Kercher and added command line
-# options
-#
-# 2007/05/31 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
-# Set a more reasonable default datafile.
-#
-# FIXME: some way to convert the character set
-
-# overwrite default settings with optional command line arguments
-while getopts i:d:c: option; do
- case $option in
- i) IPOD_MOUNT=$OPTARG;;
- d) DATAFILE=$OPTARG;;
- c) CALENDAR=$OPTARG;;
- \?) echo "Usage: `basename $0` [-i <ipod mountpoint>] [-d <webcalendar uri>] [-c <calendar_name>]"
- exit 1;;
- esac
-done
-
-echo -n "Syncing Web Calendar \"${CALENDAR}\" to iPod... "
-wget -q $WGET_OPTIONS -O ${IPOD_MOUNT}/Calendars/${CALENDAR}.ics $DATAFILE
-echo "done!"
Copied: gtkpod/tags/0.99.10-5/scripts/sync-webcalendar.sh (from rev 266, gtkpod/trunk/scripts/sync-webcalendar.sh)
===================================================================
--- gtkpod/tags/0.99.10-5/scripts/sync-webcalendar.sh (rev 0)
+++ gtkpod/tags/0.99.10-5/scripts/sync-webcalendar.sh 2007-11-20 13:46:35 UTC (rev 280)
@@ -0,0 +1,63 @@
+#!/bin/sh
+# (c) 2005 Daniel Kercher
+# sync ipod with webcalendar
+
+# Usage:
+#
+# sync-webcalendar.sh [-i <ipod mountpoint>] [-d <webcalendar uri>] [-c <calendar name>]
+#
+# with the following defaults:
+
+# mount point of ipod
+IPOD_MOUNT='/mnt/ipod'
+# uri for webcalendar (example)
+DATAFILE='https://somewhere.local/calendar.ics'
+# calendar name
+CALENDAR='webcalendar'
+# special options for wget
+WGET_OPTIONS='--no-check-certificate'
+
+# About the encoding used by the iPod (by Jorg Schuler):
+#
+# For some reason the encoding used for the contact files and
+# calenader files depends on the language you have set your iPod
+# to. If you set your iPod to German, iso-8859-15 (or -1?) is
+# expected. If you set it to Japanese, SHIFT-JIS is expected. You need
+# to reboot the iPod to have the change take effect, however. (I'm
+# using firmware version 1.3.)
+#
+# If you know of more encodings, please let me know, so they can be
+# added here:
+#
+# iPod language encoding expected
+# ----------------------------------------
+# German ISO-8859-15
+# Japanese SHIFT-JIS
+
+# Changelog
+#
+# 2007/02/01 (Giray Devlet <giray at devlet.cc>): Multi Calendar Support
+#
+# 2005/06/15 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
+# Received original script from Daniel Kercher and added command line
+# options
+#
+# 2007/05/31 (Jorg Schuler <jcsjcs at users dot sourceforge dot net>):
+# Set a more reasonable default datafile.
+#
+# FIXME: some way to convert the character set
+
+# overwrite default settings with optional command line arguments
+while getopts i:d:c: option; do
+ case $option in
+ i) IPOD_MOUNT=$OPTARG;;
+ d) DATAFILE=$OPTARG;;
+ c) CALENDAR=$OPTARG;;
+ \?) echo "Usage: `basename $0` [-i <ipod mountpoint>] [-d <webcalendar uri>] [-c <calendar_name>]"
+ exit 1;;
+ esac
+done
+
+echo -n "Syncing Web Calendar \"${CALENDAR}\" to iPod... "
+wget -q $WGET_OPTIONS -O ${IPOD_MOUNT}/Calendars/${CALENDAR}.ics $DATAFILE
+echo "done!"
Deleted: gtkpod/tags/0.99.10-5/src/mp3file.c
===================================================================
--- gtkpod/trunk/src/mp3file.c 2007-11-13 14:54:03 UTC (rev 259)
+++ gtkpod/tags/0.99.10-5/src/mp3file.c 2007-11-20 13:46:35 UTC (rev 280)
@@ -1,2678 +0,0 @@
-/* Time-stamp: <2007-06-26 00:39:11 jcs>
-|
-| Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
-| Part of the gtkpod project.
-|
-| URL: http://www.gtkpod.org/
-| URL: http://gtkpod.sourceforge.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
-|
-| iTunes and iPod are trademarks of Apple
-|
-| This product is not supported/written/published by Apple!
-|
-| $Id: mp3file.c 1591 2007-06-26 03:33:25Z tmzullinger $
-*/
-
-
-#define LOCALDEBUG 0
-
-
-/* The code in the first section of this file is taken from the
- * mp3info (http://www.ibiblio.org/mp3info/) project. Only the code
- * needed for the playlength calculation has been extracted. */
-
-/* The code in the second section of this file is taken from the
- * mpg123 code used in xmms-1.2.7 (Input/mpg123). Only the code needed
- * for the playlength calculation has been extracted. */
-
-/* The code in the last section of this file is original gtkpod
- * code. */
-
-/****************
- * Declarations *
- ****************/
-
-#include <glib.h>
-#include <math.h>
-/*
- * Description of each item of the TagList list
- */
-typedef struct _File_Tag File_Tag;
-typedef struct _GainData GainData;
-typedef struct _GaplessData GaplessData;
-
-struct _File_Tag
-{
- gchar *title; /* Title of track */
- gchar *artist; /* Artist name */
- gchar *album; /* Album name */
- gchar *year; /* Year of track */
- gchar *trackstring; /* Position of track in the album */
- gchar *track_total; /* The number of tracks for the album (ex: 12/20) */
- gchar *genre; /* Genre of song */
- gchar *comment; /* Comment */
- gchar *composer; /* Composer */
- guint32 songlen; /* Length of file in ms */
- gchar *cdnostring; /* Position of disc in the album */
- gchar *cdno_total; /* The number of discs in the album (ex: 1/2) */
- gchar *compilation; /* The track is a member of a compilation */
- gchar *podcasturl; /* The following are mainly used for podcasts */
- gchar *sort_artist;
- gchar *sort_title;
- gchar *sort_album;
- gchar *sort_albumartist;
- gchar *sort_composer;
- gchar *description;
- gchar *podcastrss;
- gchar *time_released;
- gchar *subtitle;
- gchar *BPM; /* beats per minute */
- gchar *lyrics; /* does not appear to be the full lyrics --
- only used to set the flag 'lyrics_flag'
- of the Track structure */
-};
-
-
-struct _GainData
-{
- guint32 peak_signal; /* LAME Peak Signal * 0x800000 */
- gdouble radio_gain; /* RadioGain in dB
- (as defined by www.replaygain.org) */
- gdouble audiophile_gain;/* AudiophileGain in dB
- (as defined by www.replaygain.org) */
- gboolean peak_signal_set; /* has the peak signal been set? */
- gboolean radio_gain_set; /* has the radio gain been set? */
- gboolean audiophile_gain_set;/* has the audiophile gain been set? */
-};
-
-struct _GaplessData
-{
- guint32 pregap; /* number of pregap samples */
- guint64 samplecount; /* number of actual music samples */
- guint32 postgap; /* number of postgap samples */
- guint32 gapless_data; /* number of bytes from the first sync frame to the 8th to last frame */
-};
-
-/* This code is taken from the mp3info code. Only the code needed for
- * the playlength calculation has been extracted */
-
-/*
- mp3tech.c - Functions for handling MP3 files and most MP3 data
- structure manipulation.
-
- Copyright (C) 2000-2001 Cedric Tefft <cedric at earthling.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., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- ***************************************************************************
-
- This file is based in part on:
-
- * MP3Info 0.5 by Ricardo Cerqueira <rmc at rccn.net>
- * MP3Stat 0.9 by Ed Sweetman <safemode at voicenet.com> and
- Johannes Overmann <overmann at iname.com>
-
-*/
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "mp3file.h"
-#include "charset.h"
-#include "itdb.h"
-#include "file.h"
-#include "misc.h"
-
-
-/* MIN_CONSEC_GOOD_FRAMES defines how many consecutive valid MP3 frames
- we need to see before we decide we are looking at a real MP3 file */
-#define MIN_CONSEC_GOOD_FRAMES 4
-#define FRAME_HEADER_SIZE 4
-#define MIN_FRAME_SIZE 21
-
-enum VBR_REPORT { VBR_VARIABLE, VBR_AVERAGE, VBR_MEDIAN };
-
-typedef struct {
- gulong sync;
- guint version;
- guint layer;
- guint crc;
- guint bitrate;
- guint freq;
- guint padding;
- guint extension;
- guint mode;
- guint mode_extension;
- guint copyright;
- guint original;
- guint emphasis;
-} MP3Header;
-
-typedef struct {
- gchar *filename;
- FILE *file;
- off_t datasize;
- gint header_isvalid;
- MP3Header header;
- gint id3_isvalid;
- gint vbr;
- float vbr_average;
- gint milliseconds;
- gint frames;
- gint badframes;
-} MP3Info;
-
-/* This is for xmms code */
-static guint get_track_time(gchar *path);
-
-
-
-/* ------------------------------------------------------------
-
- start of first section
-
- ------------------------------------------------------------ */
-void get_mp3_info(MP3Info *mp3);
-
-gint frequencies[3][4] = {
- {22050,24000,16000,50000}, /* MPEG 2.0 */
- {44100,48000,32000,50000}, /* MPEG 1.0 */
- {11025,12000,8000,50000} /* MPEG 2.5 */
-};
-
-/* "0" added by JCS */
-gint bitrate[2][3][16] = {
- { /* MPEG 2.0 */
- {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,0},/* layer 1 */
- {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0}, /* layer 2 */
- {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0} /* layer 3 */
- },
-
- { /* MPEG 1.0 */
- {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},/* layer 1 */
- {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0}, /* layer 2 */
- {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0} /* layer 3 */
- }
-};
-
-gint frame_size_index[] = {24000, 72000, 72000};
-
-
-gchar *mode_text[] = {
- "stereo", "joint stereo", "dual channel", "mono"
-};
-
-gchar *emphasis_text[] = {
- "none", "50/15 microsecs", "reserved", "CCITT J 17"
-};
-
-
-static gint mp3file_header_bitrate(MP3Header *h) {
- return bitrate[h->version & 1][3-h->layer][h->bitrate];
-}
-
-
-static gint mp3file_header_frequency(MP3Header *h) {
- return frequencies[h->version][h->freq];
-}
-
-
-gint frame_length(MP3Header *header) {
- return header->sync == 0xFFE ?
- (frame_size_index[3-header->layer]*((header->version&1)+1)*
- mp3file_header_bitrate(header)/(float)mp3file_header_frequency(header))+
- header->padding : 1;
-}
-
-/* Get next MP3 frame header.
- Return codes:
- positive value = Frame Length of this header
- 0 = No, we did not retrieve a valid frame header
-*/
-gint get_header(FILE *file,MP3Header *header)
-{
- guchar buffer[FRAME_HEADER_SIZE];
- gint fl;
-
- if(fread(&buffer,FRAME_HEADER_SIZE,1,file)<1) {
- header->sync=0;
- return 0;
- }
- header->sync=(((gint)buffer[0]<<4) | ((gint)(buffer[1]&0xE0)>>4));
- if(buffer[1] & 0x10) header->version=(buffer[1] >> 3) & 1;
- else header->version=2;
- header->layer=(buffer[1] >> 1) & 3;
- if (header->layer == 0)
- {
- header->layer = 1; /* sanity added by JCS */
- }
- if((header->sync != 0xFFE) || (header->layer != 1)) {
- header->sync=0;
- return 0;
- }
- header->crc=buffer[1] & 1;
- header->bitrate=(buffer[2] >> 4) & 0x0F;
- header->freq=(buffer[2] >> 2) & 0x3;
- header->padding=(buffer[2] >>1) & 0x1;
- header->extension=(buffer[2]) & 0x1;
- header->mode=(buffer[3] >> 6) & 0x3;
- header->mode_extension=(buffer[3] >> 4) & 0x3;
- header->copyright=(buffer[3] >> 3) & 0x1;
- header->original=(buffer[3] >> 2) & 0x1;
- header->emphasis=(buffer[3]) & 0x3;
-
- return ((fl=frame_length(header)) >= MIN_FRAME_SIZE ? fl : 0);
-}
-
-gint sameConstant(MP3Header *h1, MP3Header *h2) {
- if((*(guint*)h1) == (*(guint*)h2)) return 1;
-
- if((h1->version == h2->version ) &&
- (h1->layer == h2->layer ) &&
- (h1->crc == h2->crc ) &&
- (h1->freq == h2->freq ) &&
- (h1->mode == h2->mode ) &&
- (h1->copyright == h2->copyright ) &&
- (h1->original == h2->original ) &&
- (h1->emphasis == h2->emphasis ))
- return 1;
- else return 0;
-}
-
-
-gint get_first_header(MP3Info *mp3, long startpos)
-{
- gint k, l=0,c;
- MP3Header h, h2;
- long valid_start=0;
-
- fseek(mp3->file,startpos,SEEK_SET);
- while (1) {
- while((c=fgetc(mp3->file)) != 255 && (c != EOF));
- if(c == 255) {
- ungetc(c,mp3->file);
- valid_start=ftell(mp3->file);
- if((l=get_header(mp3->file,&h))) {
- fseek(mp3->file,l-FRAME_HEADER_SIZE,SEEK_CUR);
- for(k=1; (k < MIN_CONSEC_GOOD_FRAMES) && (mp3->datasize-ftell(mp3->file) >= FRAME_HEADER_SIZE); k++) {
- if(!(l=get_header(mp3->file,&h2))) break;
- if(!sameConstant(&h,&h2)) break;
- fseek(mp3->file,l-FRAME_HEADER_SIZE,SEEK_CUR);
- }
- if(k == MIN_CONSEC_GOOD_FRAMES) {
- fseek(mp3->file,valid_start,SEEK_SET);
- memcpy(&(mp3->header),&h2,sizeof(MP3Header));
- mp3->header_isvalid=1;
- return 1;
- }
- }
- } else {
- return 0;
- }
- }
-
- return 0;
-}
-
-
-/* get_next_header() - read header at current position or look for
- the next valid header if there isn't one at the current position
-*/
-gint get_next_header(MP3Info *mp3)
-{
- gint l=0,c,skip_bytes=0;
- MP3Header h;
-
- while(1) {
- while((c=fgetc(mp3->file)) != 255 && (ftell(mp3->file) < mp3->datasize)) skip_bytes++;
- if(c == 255) {
- ungetc(c,mp3->file);
- if((l=get_header(mp3->file,&h))) {
- if(skip_bytes) mp3->badframes++;
- fseek(mp3->file,l-FRAME_HEADER_SIZE,SEEK_CUR);
- return 15-h.bitrate;
- } else {
- skip_bytes += FRAME_HEADER_SIZE;
- }
- } else {
- if(skip_bytes) mp3->badframes++;
- return 0;
- }
- }
-}
-
-
-void get_mp3_info(MP3Info *mp3)
-{
- gint frame_type[15]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
- float milliseconds=0,total_rate=0;
- gint frames=0,frame_types=0,frames_so_far=0;
- gint vbr_median=-1;
- guint bitrate;
- gint counter=0;
- MP3Header header;
- struct stat filestat;
- off_t data_start=0;
-
-
- stat(mp3->filename,&filestat);
- mp3->datasize=filestat.st_size;
-
- if(get_first_header(mp3,0L)) {
- data_start=ftell(mp3->file);
- while((bitrate=get_next_header(mp3))) {
- if (bitrate < 15) /* sanity added by JCS */
- frame_type[15-bitrate]++;
- frames++;
- }
- memcpy(&header,&(mp3->header),sizeof(MP3Header));
- for(counter=0;counter<15;counter++) {
- if(frame_type[counter]) {
- float header_bitrate; /* introduced by JCS to speed up */
- frame_types++;
- header.bitrate=counter;
- frames_so_far += frame_type[counter];
- header_bitrate = mp3file_header_bitrate(&header);
- if (header_bitrate != 0)
- milliseconds += (float)(8*frame_length(&header)*frame_type[counter])/header_bitrate;
- total_rate += header_bitrate*frame_type[counter];
- if((vbr_median == -1) && (frames_so_far >= frames/2))
- vbr_median=counter;
- }
- }
- mp3->milliseconds=(gint)(milliseconds+0.5);
- mp3->header.bitrate=vbr_median;
- mp3->vbr_average=total_rate/(float)frames;
- mp3->frames=frames;
- if(frame_types > 1) {
- mp3->vbr=1;
- }
- }
-}
-
-
-
-
-/* ------------------------------------------------------------
-
- xmms code
-
-
- ------------------------------------------------------------ */
-
-/*
-| Changed by Jorg Schuler <jcsjcs at users.sourceforge.net> to
-| compile with the gtkpod project. 2003/04/01
-*/
-
-/* This code is taken from the mpg123 code used in xmms-1.2.7
- * (Input/mpg123). Only the code needed for the playlength calculation
- * has been extracted */
-
-#include "mp3file.h"
-#include <stdio.h>
-#include <string.h>
-
-#define FRAMES_FLAG 0x0001
-#define BYTES_FLAG 0x0002
-#define TOC_FLAG 0x0004
-#define VBR_SCALE_FLAG 0x0008
-
-#define SBLIMIT 32
-#define SCALE_BLOCK 12
-#define SSLIMIT 18
-
-#define MPG_MD_STEREO 0
-#define MPG_MD_JOINT_STEREO 1
-#define MPG_MD_DUAL_CHANNEL 2
-#define MPG_MD_MONO 3
-#define MAXFRAMESIZE 1792
-#define real float
-
-struct bitstream_info
-{
- int bitindex;
- unsigned char *wordpointer;
-};
-
-struct bitstream_info bsi;
-
-real mpg123_muls[27][64]; /* also used by layer 1 */
-
-int tabsel_123[2][3][16] =
-{
- {
- {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,},
- {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384,},
- {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,}},
-
- {
- {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,},
- {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,},
- {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}}
-};
-
-long mpg123_freqs[9] =
-{44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000};
-
-/*
- * structure to receive extracted header
- */
-typedef struct
-{
- int frames; /* total bit stream frames from Xing header data */
- int bytes; /* total bit stream bytes from Xing header data */
- unsigned char toc[100]; /* "table of contents" */
-} xing_header_t;
-
-struct al_table
-{
- short bits;
- short d;
-};
-
-struct frame
-{
- struct al_table *alloc;
- int (*synth) (real *, int, unsigned char *, int *);
- int (*synth_mono) (real *, unsigned char *, int *);
-#ifdef USE_3DNOW
- void (*dct36)(real *,real *,real *,real *,real *);
-#endif
- int stereo;
- int jsbound;
- int single;
- int II_sblimit;
- int down_sample_sblimit;
- int lsf;
- int mpeg25;
- int down_sample;
- int header_change;
- int lay;
- int (*do_layer) (struct frame * fr);
- int error_protection;
- int bitrate_index;
- int sampling_frequency;
- int padding;
- int extension;
- int mode;
- int mode_ext;
- int copyright;
- int original;
- int emphasis;
- int framesize; /* computed framesize */
-};
-
-static guint32 convert_to_header(guint8 * buf)
-{
-
- return (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3];
-}
-
-static int mpg123_head_check(unsigned long head)
-{
- if ((head & 0xffe00000) != 0xffe00000)
- return FALSE;
- if (!((head >> 17) & 3))
- return FALSE;
- if (((head >> 12) & 0xf) == 0xf)
- return FALSE;
- if (!((head >> 12) & 0xf))
- return FALSE;
- if (((head >> 10) & 0x3) == 0x3)
- return FALSE;
- if (((head >> 19) & 1) == 1 && ((head >> 17) & 3) == 3 && ((head >> 16) & 1) == 1)
- return FALSE;
- if ((head & 0xffff0000) == 0xfffe0000)
- return FALSE;
-
- return TRUE;
-}
-
-
-/*
- * the code a header and write the information
- * into the frame structure
- */
-static int mpg123_decode_header(struct frame *fr, unsigned long newhead)
-{
- int ssize;
-
- if (newhead & (1 << 20))
- {
- fr->lsf = (newhead & (1 << 19)) ? 0x0 : 0x1;
- fr->mpeg25 = 0;
- }
- else
- {
- fr->lsf = 1;
- fr->mpeg25 = 1;
- }
- fr->lay = 4 - ((newhead >> 17) & 3);
- if (fr->mpeg25)
- {
- fr->sampling_frequency = 6 + ((newhead >> 10) & 0x3);
- }
- else
- fr->sampling_frequency = ((newhead >> 10) & 0x3) + (fr->lsf * 3);
- fr->error_protection = ((newhead >> 16) & 0x1) ^ 0x1;
-
- fr->bitrate_index = ((newhead >> 12) & 0xf);
- fr->padding = ((newhead >> 9) & 0x1);
- fr->extension = ((newhead >> 8) & 0x1);
- fr->mode = ((newhead >> 6) & 0x3);
- fr->mode_ext = ((newhead >> 4) & 0x3);
- fr->copyright = ((newhead >> 3) & 0x1);
- fr->original = ((newhead >> 2) & 0x1);
- fr->emphasis = newhead & 0x3;
-
- fr->stereo = (fr->mode == MPG_MD_MONO) ? 1 : 2;
-
- ssize = 0;
-
- if (!fr->bitrate_index)
- return (0);
-
- switch (fr->lay)
- {
- case 1:
-/* fr->do_layer = mpg123_do_layer1; */
-/* mpg123_init_layer2(); /\* inits also shared tables with layer1 *\/ */
- fr->framesize = (long) tabsel_123[fr->lsf][0][fr->bitrate_index] * 12000;
- fr->framesize /= mpg123_freqs[fr->sampling_frequency];
- fr->framesize = ((fr->framesize + fr->padding) << 2) - 4;
- break;
- case 2:
-/* fr->do_layer = mpg123_do_layer2; */
-/* mpg123_init_layer2(); /\* inits also shared tables with layer1 *\/ */
- fr->framesize = (long) tabsel_123[fr->lsf][1][fr->bitrate_index] * 144000;
- fr->framesize /= mpg123_freqs[fr->sampling_frequency];
- fr->framesize += fr->padding - 4;
- break;
- case 3:
-/* fr->do_layer = mpg123_do_layer3; */
- if (fr->lsf)
- ssize = (fr->stereo == 1) ? 9 : 17;
- else
- ssize = (fr->stereo == 1) ? 17 : 32;
- if (fr->error_protection)
- ssize += 2;
- fr->framesize = (long) tabsel_123[fr->lsf][2][fr->bitrate_index] * 144000;
- fr->framesize /= mpg123_freqs[fr->sampling_frequency] << (fr->lsf);
- fr->framesize = fr->framesize + fr->padding - 4;
- break;
- default:
- return (0);
- }
- if(fr->framesize > MAXFRAMESIZE)
- return 0;
- return 1;
-}
-
-#define GET_INT32BE(b) \
-(i = (b[0] << 24) | (b[1] << 16) | b[2] << 8 | b[3], b += 4, i)
-
-static int mpg123_get_xing_header(xing_header_t * xing, unsigned char *buf)
-{
- int i, head_flags;
- int id, mode;
-
- memset(xing, 0, sizeof(xing_header_t));
-
- /* get selected MPEG header data */
- id = (buf[1] >> 3) & 1;
- mode = (buf[3] >> 6) & 3;
- buf += 4;
-
- /* Skip the sub band data */
- if (id)
- {
- /* mpeg1 */
- if (mode != 3)
- buf += 32;
- else
- buf += 17;
- }
- else
- {
- /* mpeg2 */
- if (mode != 3)
- buf += 17;
- else
- buf += 9;
- }
-
- if (strncmp(buf, "Xing", 4))
- return 0;
- buf += 4;
-
- head_flags = GET_INT32BE(buf);
-
- if (head_flags & FRAMES_FLAG)
- xing->frames = GET_INT32BE(buf);
- if (xing->frames < 1)
- xing->frames = 1;
- if (head_flags & BYTES_FLAG)
- xing->bytes = GET_INT32BE(buf);
-
- if (head_flags & TOC_FLAG)
- {
- for (i = 0; i < 100; i++)
- xing->toc[i] = buf[i];
- buf += 100;
- }
-
-#ifdef XING_DEBUG
- for (i = 0; i < 100; i++)
- {
- if ((i % 10) == 0)
- fprintf(stderr, "\n");
- fprintf(stderr, " %3d", xing->toc[i]);
- }
-#endif
-
- return 1;
-}
-
-static double mpg123_compute_tpf(struct frame *fr)
-{
- const int bs[4] = {0, 384, 1152, 1152};
- double tpf;
-
- tpf = bs[fr->lay];
- tpf /= mpg123_freqs[fr->sampling_frequency] << (fr->lsf);
- return tpf;
-}
-
-static double mpg123_compute_bpf(struct frame *fr)
-{
- double bpf;
-
- switch (fr->lay)
- {
- case 1:
- bpf = tabsel_123[fr->lsf][0][fr->bitrate_index];
- bpf *= 12000.0 * 4.0;
- bpf /= mpg123_freqs[fr->sampling_frequency] << (fr->lsf);
- break;
- case 2:
- case 3:
- bpf = tabsel_123[fr->lsf][fr->lay - 1][fr->bitrate_index];
- bpf *= 144000;
- bpf /= mpg123_freqs[fr->sampling_frequency] << (fr->lsf);
- break;
- default:
- bpf = 1.0;
- }
-
- return bpf;
-}
-
-
-unsigned int mpg123_getbits(int number_of_bits)
-{
- unsigned long rval;
-
-#ifdef DEBUG_GETBITS
- fprintf(stderr, "g%d", number_of_bits);
-#endif
-
- if(!number_of_bits)
- return 0;
-
-#if 0
- check_buffer_range(number_of_bits + bsi.bitindex);
-#endif
-
- {
- rval = bsi.wordpointer[0];
- rval <<= 8;
- rval |= bsi.wordpointer[1];
- rval <<= 8;
- rval |= bsi.wordpointer[2];
-
- rval <<= bsi.bitindex;
- rval &= 0xffffff;
-
- bsi.bitindex += number_of_bits;
-
- rval >>= (24-number_of_bits);
-
- bsi.wordpointer += (bsi.bitindex >> 3);
- bsi.bitindex &= 7;
- }
-
-#ifdef DEBUG_GETBITS
- fprintf(stderr,":%x ",rval);
-#endif
-
- return rval;
-}
-
-
-void I_step_one(unsigned int balloc[], unsigned int scale_index[2][SBLIMIT], struct frame *fr)
-{
- unsigned int *ba = balloc;
- unsigned int *sca = (unsigned int *) scale_index;
-
- if (fr->stereo)
- {
- int i;
- int jsbound = fr->jsbound;
-
- for (i = 0; i < jsbound; i++)
- {
- *ba++ = mpg123_getbits(4);
- *ba++ = mpg123_getbits(4);
- }
- for (i = jsbound; i < SBLIMIT; i++)
- *ba++ = mpg123_getbits(4);
-
- ba = balloc;
-
- for (i = 0; i < jsbound; i++)
- {
- if ((*ba++))
- *sca++ = mpg123_getbits(6);
- if ((*ba++))
- *sca++ = mpg123_getbits(6);
- }
- for (i = jsbound; i < SBLIMIT; i++)
- if ((*ba++))
- {
- *sca++ = mpg123_getbits(6);
- *sca++ = mpg123_getbits(6);
- }
- }
- else
- {
- int i;
-
- for (i = 0; i < SBLIMIT; i++)
- *ba++ = mpg123_getbits(4);
- ba = balloc;
- for (i = 0; i < SBLIMIT; i++)
- if ((*ba++))
- *sca++ = mpg123_getbits(6);
- }
-}
-
-void I_step_two(real fraction[2][SBLIMIT], unsigned int balloc[2 * SBLIMIT],
- unsigned int scale_index[2][SBLIMIT], struct frame *fr)
-{
- int i, n;
- int smpb[2 * SBLIMIT]; /* values: 0-65535 */
- int *sample;
- register unsigned int *ba;
- register unsigned int *sca = (unsigned int *) scale_index;
-
- if (fr->stereo)
- {
- int jsbound = fr->jsbound;
- register real *f0 = fraction[0];
- register real *f1 = fraction[1];
-
- ba = balloc;
- for (sample = smpb, i = 0; i < jsbound; i++)
- {
- if ((n = *ba++))
- *sample++ = mpg123_getbits(n + 1);
- if ((n = *ba++))
- *sample++ = mpg123_getbits(n + 1);
- }
- for (i = jsbound; i < SBLIMIT; i++)
- if ((n = *ba++))
- *sample++ = mpg123_getbits(n + 1);
-
- ba = balloc;
- for (sample = smpb, i = 0; i < jsbound; i++)
- {
- if ((n = *ba++))
- *f0++ = (real) (((-1) << n) + (*sample++) + 1) * mpg123_muls[n + 1][*sca++];
- else
- *f0++ = 0.0;
- if ((n = *ba++))
- *f1++ = (real) (((-1) << n) + (*sample++) + 1) * mpg123_muls[n + 1][*sca++];
- else
- *f1++ = 0.0;
- }
- for (i = jsbound; i < SBLIMIT; i++)
- {
- if ((n = *ba++))
- {
- real samp = (((-1) << n) + (*sample++) + 1);
-
- *f0++ = samp * mpg123_muls[n + 1][*sca++];
- *f1++ = samp * mpg123_muls[n + 1][*sca++];
- }
- else
- *f0++ = *f1++ = 0.0;
- }
- for (i = fr->down_sample_sblimit; i < 32; i++)
- fraction[0][i] = fraction[1][i] = 0.0;
- }
- else
- {
- register real *f0 = fraction[0];
-
- ba = balloc;
- for (sample = smpb, i = 0; i < SBLIMIT; i++)
- if ((n = *ba++))
- *sample++ = mpg123_getbits(n + 1);
- ba = balloc;
- for (sample = smpb, i = 0; i < SBLIMIT; i++)
- {
- if ((n = *ba++))
- *f0++ = (real) (((-1) << n) + (*sample++) + 1) * mpg123_muls[n + 1][*sca++];
- else
- *f0++ = 0.0;
- }
- for (i = fr->down_sample_sblimit; i < 32; i++)
- fraction[0][i] = 0.0;
- }
-}
-
-static guint get_track_time_file(FILE * file)
-{
- guint32 head;
- guchar tmp[4], *buf;
- struct frame frm;
- xing_header_t xing_header;
- double tpf, bpf;
- guint32 len;
-
- if (!file)
- return -1;
-
- fseek(file, 0, SEEK_SET);
- if (fread(tmp, 1, 4, file) != 4)
- return 0;
- head = convert_to_header(tmp);
- while (!mpg123_head_check(head))
- {
- head <<= 8;
- if (fread(tmp, 1, 1, file) != 1)
- return 0;
- head |= tmp[0];
- }
- if (mpg123_decode_header(&frm, head))
- {
- buf = g_malloc(frm.framesize + 4);
- fseek(file, -4, SEEK_CUR);
- fread(buf, 1, frm.framesize + 4, file);
- tpf = mpg123_compute_tpf(&frm);
- if (mpg123_get_xing_header(&xing_header, buf))
- {
- g_free(buf);
- return ((guint) (tpf * xing_header.frames * 1000));
- }
- g_free(buf);
- bpf = mpg123_compute_bpf(&frm);
- fseek(file, 0, SEEK_END);
- len = ftell(file);
- fseek(file, -128, SEEK_END);
- fread(tmp, 1, 3, file);
- if (!strncmp(tmp, "TAG", 3))
- len -= 128;
- return ((guint) ((guint)(len / bpf) * tpf * 1000));
- }
- return 0;
-}
-
-static guint get_track_time (gchar *path)
-{
- guint result = 0;
-
- if (path)
- {
- FILE *file = fopen (path, "r");
- result = get_track_time_file (file);
- if (file) fclose (file);
- }
- return result;
-}
-
-
-/* libid3tag stuff */
-
-#include <id3tag.h>
-#include "prefs.h"
-
-#ifndef ID3_FRAME_GROUP
-#define ID3_FRAME_GROUP "TPE2"
-#endif
-
-
-
-static const gchar* id3_get_binary (struct id3_tag *tag,
- char *frame_name,
- id3_length_t *len,
- int index)
-{
- const id3_byte_t *binary = NULL;
- struct id3_frame *frame;
- union id3_field *field;
-
- g_return_val_if_fail (len, NULL);
-
- *len = 0;
-
- frame = id3_tag_findframe (tag, frame_name, index);
-#if LOCALDEBUG
- printf ("frame: %p\n", frame);
-#endif
-
- if (!frame) return NULL;
-
-#if LOCALDEBUG
- printf (" nfields: %d\n", frame->nfields);
- if (strncmp (frame_name, "APIC", 4) == 0)
- {
- field = id3_frame_field (frame, 2);
- printf (" picture type: %ld\n", field->number.value);
- }
-#endif
-
-
-#if 0
-/*-----------------*/
-/* just to show that this field (before last) contains the d8 ff e0 ff
- part of the start of a jpeg file when the coverart war embedded by iTunes */
-
- const id3_ucs4_t *string = NULL;
- gchar *raw = NULL;
-
- /* The last field contains the data */
- field = id3_frame_field (frame, frame->nfields-2);
-
-#if LOCALDEBUG
- printf (" field: %p\n", field);
-#endif
-
- if (!field) return NULL;
-
-#if LOCALDEBUG
- printf (" type: %d\n", field->type);
-#endif
-
- switch (field->type)
- {
- case ID3_FIELD_TYPE_STRING:
- string = id3_field_getstring (field);
- break;
- default:
- break;
- }
-
- /* ISO_8859_1 is just a "marker" -- most people just drop
- whatever coding system they are using into it, so we use
- charset_to_utf8() to convert to utf8 */
-
- if (string)
- {
- raw = id3_ucs4_latin1duplicate (string);
- }
-
-
-#if LOCALDEBUG
- {
- FILE *file;
- printf (" string len: %d\n", raw?strlen(raw):0);
- file = fopen ("/tmp/folder1.jpg", "w");
- fwrite (raw, 1, raw?strlen(raw):0, file);
- fclose (file);
- }
-#endif
- g_free (raw);
-
-/*-----------------*/
-#endif
-
- /* The last field contains the data */
- field = id3_frame_field (frame, frame->nfields-1);
-
-#if LOCALDEBUG
- printf (" field: %p\n", field);
-#endif
-
- if (!field) return NULL;
-
-#if LOCALDEBUG
- printf (" type: %d\n", field->type);
-#endif
-
- switch (field->type)
- {
- case ID3_FIELD_TYPE_BINARYDATA:
- binary = id3_field_getbinarydata(field, len);
- break;
- default:
- break;
- }
-
-#if LOCALDEBUG
- {
- FILE *file;
- printf (" binary len: %ld\n", *len);
- file = fopen ("/tmp/folder2.jpg", "w");
- fwrite (binary, 1, *len, file);
- fclose (file);
- }
-#endif
-
-
-
- return binary;
-}
-
-
-
-static gchar* id3_get_string (struct id3_tag *tag, char *frame_name)
-{
- const id3_ucs4_t *string = NULL;
- const id3_byte_t *binary = NULL;
- id3_length_t len = 0;
- struct id3_frame *frame;
- union id3_field *field;
- gchar *utf8 = NULL;
- enum id3_field_textencoding encoding = ID3_FIELD_TEXTENCODING_ISO_8859_1;
-
- frame = id3_tag_findframe (tag, frame_name, 0);
-#if LOCALDEGUB
- printf ("frame: %p\n", frame);
-#endif
-
- if (!frame) return NULL;
-
- /* Find the encoding used for the field */
- field = id3_frame_field (frame, 0);
-#if LOCALDEBUG
- printf ("field: %p\n", field);
- printf ("type: %d\n", id3_field_type (field));
-#endif
-
- if (field && (id3_field_type (field) == ID3_FIELD_TYPE_TEXTENCODING))
- {
- encoding = field->number.value;
-#if LOCALDEBUG
- printf ("encoding: %d\n", encoding);
-#endif
- }
-
- /* The last field contains the data */
- field = id3_frame_field (frame, frame->nfields-1);
-
-#if LOCALDEBUG
- printf ("field: %p\n", field);
-#endif
-
- if (!field) return NULL;
-
-#if LOCALDEBUG
- printf ("type: %d\n", field->type);
-#endif
-
-
- switch (field->type)
- {
- case ID3_FIELD_TYPE_STRINGLIST:
- string = id3_field_getstrings (field, 0);
- break;
- case ID3_FIELD_TYPE_STRINGFULL:
- string = id3_field_getfullstring (field);
- break;
- case ID3_FIELD_TYPE_BINARYDATA:
- binary = id3_field_getbinarydata(field, &len);
-#if LOCALDEBUG
- printf ("len: %ld\nbinary: %s\n", len, binary+1);
-#endif
- if (len > 0)
- return charset_to_utf8 (binary+1);
- break;
- default:
- break;
- }
-
-/* printf ("string: %p\n", string); */
-
- if (!string) return NULL;
-
- if (strcmp (frame_name, ID3_FRAME_GENRE) == 0)
- string = id3_genre_name (string);
-
- if (encoding == ID3_FIELD_TEXTENCODING_ISO_8859_1)
- {
- /* ISO_8859_1 is just a "marker" -- most people just drop
- whatever coding system they are using into it, so we use
- charset_to_utf8() to convert to utf8 */
- id3_latin1_t *raw = id3_ucs4_latin1duplicate (string);
- utf8 = charset_to_utf8 (raw);
- g_free (raw);
- }
- else
- {
- /* Standard unicode is being used -- we won't have to worry
- about charsets then. */
- utf8 = id3_ucs4_utf8duplicate (string);
- }
- return utf8;
-}
-
-static void id3_set_string (struct id3_tag *tag,
- const char *frame_name,
- const char *data,
- enum id3_field_textencoding encoding)
-{
- int res;
- struct id3_frame *frame;
- union id3_field *field;
- id3_ucs4_t *ucs4;
-
- /* clear the frame, because of bug in libid3tag see
- http://www.mars.org/mailman/public/mad-dev/2004-October/001113.html
- */
- while ((frame = id3_tag_findframe (tag, frame_name, 0)))
- {
- id3_tag_detachframe (tag, frame);
- id3_frame_delete (frame);
- }
-
- if ((data == NULL) || (strlen(data) == 0))
- return;
-
- frame = id3_frame_new (frame_name);
- id3_tag_attachframe (tag, frame);
-
- /* Use the specified text encoding */
- field = id3_frame_field (frame, 0);
- id3_field_settextencoding(field, encoding);
-
- if (strcmp (frame_name, ID3_FRAME_COMMENT) == 0)
- {
- field = id3_frame_field (frame, 3);
- field->type = ID3_FIELD_TYPE_STRINGFULL;
- }
- else
- {
- field = id3_frame_field (frame, 1);
- field->type = ID3_FIELD_TYPE_STRINGLIST;
- }
-
-
- /* maybe could be optimized see
- http://www.mars.org/mailman/public/mad-dev/2002-October/000739.html
- */
- if (strcmp (frame_name, ID3_FRAME_GENRE) == 0)
- {
- id3_ucs4_t *tmp_ucs4 = id3_utf8_ucs4duplicate ((id3_utf8_t *)data);
- int index = id3_genre_number (tmp_ucs4);
- if (index != -1)
- {
- /* valid genre -- simply store the genre number */
- gchar *tmp = g_strdup_printf("%d", index);
- ucs4 = id3_latin1_ucs4duplicate (tmp);
- g_free (tmp);
- }
- else
- {
- /* oups -- not a valid genre -- save the entire genre string */
- if (encoding == ID3_FIELD_TEXTENCODING_ISO_8859_1)
- {
- /* we read 'ISO_8859_1' to stand for 'any locale
- charset' -- most programs seem to work that way */
- id3_latin1_t *raw = charset_from_utf8 (data);
- ucs4 = id3_latin1_ucs4duplicate (raw);
- g_free (raw);
- }
- else
- {
- /* Yeah! We use unicode encoding and won't have to
- worry about charsets */
- ucs4 = tmp_ucs4;
- tmp_ucs4 = NULL;
- }
- }
- g_free (tmp_ucs4);
- }
- else
- {
- if (encoding == ID3_FIELD_TEXTENCODING_ISO_8859_1)
- {
- /* we read 'ISO_8859_1' to stand for 'any locale charset'
- -- most programs seem to work that way */
- id3_latin1_t *raw = charset_from_utf8 (data);
- ucs4 = id3_latin1_ucs4duplicate (raw);
- g_free (raw);
- }
- else
- {
- /* Yeah! We use unicode encoding and won't have to
- worry about charsets */
- ucs4 = id3_utf8_ucs4duplicate ((id3_utf8_t *)data);
- }
- }
-
- if (strcmp (frame_name, ID3_FRAME_COMMENT) == 0)
- res = id3_field_setfullstring (field, ucs4);
- else
- res = id3_field_setstrings (field, 1, &ucs4);
-
- g_free (ucs4);
-
- if (res != 0)
- g_print(_("Error setting ID3 field: %s\n"), frame_name);
-}
-
-
-/***
- * Reads id3v1.x / id3v2 apic data
- * @returns: TRUE on success, else FALSE.
- */
-static gboolean id3_apic_read (gchar *filename,
- guchar **image_data, gsize *image_data_len)
-{
- struct id3_file *id3file;
- struct id3_tag *id3tag;
-
- g_return_val_if_fail (filename, FALSE);
- g_return_val_if_fail (image_data, FALSE);
- g_return_val_if_fail (image_data_len, FALSE);
-
- *image_data = NULL;
- *image_data_len = 0;
-
- if (!(id3file = id3_file_open (filename, ID3_FILE_MODE_READONLY)))
- {
- gchar *fbuf = charset_to_utf8 (filename);
- g_print(_("ERROR while opening file: '%s' (%s).\n"),
- fbuf, g_strerror(errno));
- g_free (fbuf);
- return FALSE;
- }
-
- if ((id3tag = id3_file_tag(id3file)))
- {
- id3_length_t len;
- const guchar *coverart = NULL;
- int i;
- struct id3_frame *frame;
-
- /* Loop through APIC tags and set coverart. The picture type should be
- * 3 -- Cover (front), but iTunes has been known to use 0 -- Other. */
- for (i = 0; (frame = id3_tag_findframe(id3tag, "APIC", i)) != NULL; i++)
- {
- union id3_field *field = id3_frame_field (frame, 2);
- int pictype = field->number.value;
-/* printf ("%s: found apic type %d\n", filename, pictype);*/
-
- /* We'll prefer type 3 (cover) over type 0 (other) */
- if (pictype == 3)
- {
- coverart = id3_get_binary (id3tag, "APIC", &len, i);
- break;
- }
- if ((pictype == 0) && !coverart)
- {
- coverart = id3_get_binary (id3tag, "APIC", &len, i);
- }
- }
-
- if (coverart)
- { /* I guess iTunes is doing something wrong -- the
- * beginning of the coverart data ends up in a different
- field... We'll just add the missing data manually. */
- const guchar itunes_broken_jfif_marker[] =
- { 0x10, 'J', 'F', 'I', 'F'};
- if (len >= 5)
- {
- if (strncmp (itunes_broken_jfif_marker, coverart, 5) == 0)
- {
- const guchar itunes_missing_header[] =
- { 0xff, 0xd8, 0xff, 0xe0, 0x00 };
- *image_data = g_malloc (len+5);
- memcpy (*image_data, itunes_missing_header, 5);
- memcpy ((*image_data)+5, coverart, len);
- *image_data_len = len+5;
- }
- }
- if (!*image_data)
- {
- *image_data = g_malloc (len);
- memcpy (*image_data, coverart, len);
- *image_data_len = len;
- }
-#if LOCALDEBUG
- if (*image_data)
- {
- FILE *file;
- file = fopen ("/tmp/folder.jpg", "w");
- fwrite (*image_data, 1, *image_data_len, file);
- fclose (file);
- }
-#endif
- }
- }
- id3_file_close (id3file);
- return TRUE;
-}
-
-/***
- * Reads id3v1.x / id3v2 tag and load data into the Id3tag structure.
- * If a tag entry exists (ex: title), we allocate memory, else value
- * stays to NULL
- * @returns: TRUE on success, else FALSE.
- */
-gboolean id3_tag_read (gchar *filename, File_Tag *tag)
-{
- struct id3_file *id3file;
- struct id3_tag *id3tag;
- gchar* string;
- gchar* string2;
-
- g_return_val_if_fail (filename, FALSE);
- g_return_val_if_fail (tag, FALSE);
-
- memset (tag, 0, sizeof (File_Tag));
-
- if (!(id3file = id3_file_open (filename, ID3_FILE_MODE_READONLY)))
- {
- gchar *fbuf = charset_to_utf8 (filename);
- g_print(_("ERROR while opening file: '%s' (%s).\n"),
- fbuf, g_strerror(errno));
- g_free (fbuf);
- return FALSE;
- }
-
- if ((id3tag = id3_file_tag(id3file)))
- {
- tag->title = id3_get_string (id3tag, ID3_FRAME_TITLE);
- tag->artist = id3_get_string (id3tag, ID3_FRAME_GROUP);
- if (!tag->artist || !*tag->artist)
- {
- g_free (tag->artist);
- tag->artist = id3_get_string (id3tag, ID3_FRAME_ARTIST);
- }
- tag->album = id3_get_string (id3tag, ID3_FRAME_ALBUM);
- tag->year = id3_get_string (id3tag, ID3_FRAME_YEAR);
- tag->composer = id3_get_string (id3tag, "TCOM");
- tag->comment = id3_get_string (id3tag, ID3_FRAME_COMMENT);
- tag->genre = id3_get_string (id3tag, ID3_FRAME_GENRE);
- tag->compilation = id3_get_string (id3tag, "TCMP");
- tag->subtitle = id3_get_string (id3tag, "TIT3");
- tag->lyrics = id3_get_string (id3tag, "USLT");
- tag->podcasturl = id3_get_string (id3tag, "YTID");
- tag->podcastrss = id3_get_string (id3tag, "YWFD");
- tag->description = id3_get_string (id3tag, "YTDS");
- tag->time_released = id3_get_string (id3tag, "YTDR");
- tag->BPM = id3_get_string (id3tag, "TBPM");
- tag->sort_artist = id3_get_string (id3tag, "TSOP");
- tag->sort_album = id3_get_string (id3tag, "TSOA");
- tag->sort_title = id3_get_string (id3tag, "TSOT");
- tag->sort_albumartist = id3_get_string (id3tag, "TSO2");
- tag->sort_composer = id3_get_string (id3tag, "TSOC");
-
- string = id3_get_string (id3tag, "TLEN");
- if (string)
- {
- tag->songlen = (guint32) strtoul (string, 0, 10);
- g_free (string);
- }
-
- string = id3_get_string (id3tag, ID3_FRAME_TRACK);
- if (string)
- {
- string2 = strchr(string,'/');
- if (string2)
- {
- tag->track_total = g_strdup_printf ("%.2d", atoi (string2+1));
- *string2 = '\0';
- }
- tag->trackstring = g_strdup_printf ("%.2d", atoi (string));
- g_free(string);
- }
-
- /* CD/disc number tag handling */
- string = id3_get_string (id3tag, "TPOS");
- if (string)
- {
- string2 = strchr(string,'/');
- if (string2)
- {
- tag->cdno_total = g_strdup_printf ("%.2d", atoi (string2+1));
- *string2 = '\0';
- }
- tag->cdnostring = g_strdup_printf ("%.2d", atoi (string));
- g_free(string);
- }
- }
-
- id3_file_close (id3file);
- return TRUE;
-}
-
-
-
-static enum id3_field_textencoding get_encoding_of (struct id3_tag *tag, const char *frame_name)
-{
- struct id3_frame *frame;
- enum id3_field_textencoding encoding = -1;
-
- frame = id3_tag_findframe (tag, frame_name, 0);
- if (frame)
- {
- union id3_field *field = id3_frame_field (frame, 0);
- if (field && (id3_field_type (field) == ID3_FIELD_TYPE_TEXTENCODING))
- encoding = field->number.value;
- }
- return encoding;
-}
-
-/* Find out which encoding is being used. If in doubt, return
- * latin1. This code assumes that the same encoding is used in all
- * fields. */
-static enum id3_field_textencoding get_encoding (struct id3_tag *tag)
-{
- enum id3_field_textencoding enc;
-
- enc = get_encoding_of (tag, ID3_FRAME_TITLE);
- if (enc != -1) return enc;
- enc = get_encoding_of (tag, ID3_FRAME_ARTIST);
- if (enc != -1) return enc;
- enc = get_encoding_of (tag, ID3_FRAME_ALBUM);
- if (enc != -1) return enc;
- enc = get_encoding_of (tag, "TCOM");
- if (enc != -1) return enc;
- enc = get_encoding_of (tag, ID3_FRAME_COMMENT);
- if (enc != -1) return enc;
- enc = get_encoding_of (tag, ID3_FRAME_YEAR);
- if (enc != -1) return enc;
- return ID3_FIELD_TEXTENCODING_ISO_8859_1;
-}
-
-
-/* I'm not really sure about this: The original TAG identifier was
- "TID", but no matter what I do I end up writing "YTID" */
-void set_uncommon_tag (struct id3_tag *id3tag,
- const gchar *id,
- const gchar *text,
- enum id3_field_textencoding encoding)
-{
-#if 0
- struct id3_frame *frame;
-
- frame = id3_tag_findframe (id3tag, id, 0);
- union id3_field *field;
- frame->flags = 0;
- field = id3_frame_field (frame, 0);
- if (field)
- {
- string1 = g_strdup_printf ("%c%s", '\0',
- track->podcasturl);
- id3_field_setbinarydata (field, string1,
- strlen(track->podcasturl)+1);
- g_free (string1);
- }
-
-#endif
-}
-
-
-
-/**
- * Write the ID3 tags to the file.
- * @returns: TRUE on success, else FALSE.
- */
-gboolean mp3_write_file_info (gchar *filename, Track *track)
-{
- struct id3_tag* id3tag;
- struct id3_file* id3file;
- gint error = 0;
-
- id3file = id3_file_open (filename, ID3_FILE_MODE_READWRITE);
- if (!id3file)
- {
- gchar *fbuf = charset_to_utf8 (filename);
- g_print(_("ERROR while opening file: '%s' (%s).\n"),
- fbuf, g_strerror(errno));
- g_free (fbuf);
- return FALSE;
- }
-
- if ((id3tag = id3_file_tag(id3file)))
- {
- char *string1;
-
- enum id3_field_textencoding encoding;
-
- /* use the same coding as before... */
- encoding = get_encoding (id3tag);
- /* ...unless it's ISO_8859_1 and prefs say we should use
- unicode (i.e. ID3v2.4) */
- if (prefs_get_int("id3_write_id3v24") &&
- (encoding == ID3_FIELD_TEXTENCODING_ISO_8859_1))
- encoding = ID3_FIELD_TEXTENCODING_UTF_8;
-
- /* always render id3v1 to prevent dj studio from crashing */
- id3_tag_options(id3tag, ID3_TAG_OPTION_ID3V1, ~0);
-
- /* turn off frame compression and crc information to let
- itunes read tags see
- http://www.mars.org/mailman/public/mad-dev/2002-October/000742.html
- */
- id3_tag_options(id3tag, ID3_TAG_OPTION_COMPRESSION, 0);
- id3_tag_options(id3tag, ID3_TAG_OPTION_CRC, 0);
-
- id3_set_string (id3tag, ID3_FRAME_TITLE, track->title, encoding);
- id3_set_string (id3tag, ID3_FRAME_ARTIST, track->artist, encoding);
- id3_set_string (id3tag, ID3_FRAME_ALBUM, track->album, encoding);
- id3_set_string (id3tag, ID3_FRAME_GENRE, track->genre, encoding);
- id3_set_string (id3tag, ID3_FRAME_COMMENT, track->comment, encoding);
- id3_set_string (id3tag, "TIT3", track->subtitle, encoding);
- id3_set_string (id3tag, "TSOP", track->sort_artist, encoding);
- id3_set_string (id3tag, "TSOA", track->sort_album, encoding);
- id3_set_string (id3tag, "TSOT", track->sort_title, encoding);
- id3_set_string (id3tag, "TSO2", track->sort_albumartist, encoding);
- id3_set_string (id3tag, "TSOC", track->sort_composer, encoding);
-
- set_uncommon_tag (id3tag, "YTID", track->podcasturl, encoding);
- set_uncommon_tag (id3tag, "YTDS", track->description, encoding);
- set_uncommon_tag (id3tag, "YWFD", track->podcastrss, encoding);
-
- id3_set_string (id3tag, "TCOM", track->composer, encoding);
-
- string1 = g_strdup_printf("%d", track->year);
- id3_set_string(id3tag, ID3_FRAME_YEAR, string1, encoding);
- g_free(string1);
-
- string1 = g_strdup_printf("%d", track->BPM);
- id3_set_string(id3tag, "TBPM", string1, encoding);
- g_free(string1);
-
- if (track->tracks)
- string1 = g_strdup_printf ("%d/%d",
- track->track_nr, track->tracks);
- else
- string1 = g_strdup_printf ("%d", track->track_nr);
- id3_set_string (id3tag, ID3_FRAME_TRACK, string1, encoding);
- g_free(string1);
-
- if (track->cds)
- string1 = g_strdup_printf ("%d/%d",
- track->cd_nr, track->cds);
- else
- string1 = g_strdup_printf ("%d", track->cd_nr);
- id3_set_string (id3tag, "TPOS", string1, encoding);
- g_free(string1);
-
- string1 = g_strdup_printf ("%d", track->compilation);
- id3_set_string (id3tag, "TCMP", string1, encoding);
- g_free(string1);
- }
-
- if (id3_file_update(id3file) != 0)
- {
- gchar *fbuf = charset_to_utf8 (filename);
- g_print(_("ERROR while writing tag to file: '%s' (%s).\n"),
- fbuf, g_strerror(errno));
- g_free (fbuf);
- return FALSE;
- }
-
- id3_file_close (id3file);
-
- if (error) return FALSE;
- else return TRUE;
-}
-
-
-/*
- * Code to read the ReplayGain Values stored by LAME in its own tag.
- *
- * Most of the relevant information has been extracted from them LAME sources
- * (http://lame.sourceforge.net/).
- * The "Mp3 info Tag rev 1 specifications - draft 0"
- * (http://gabriel.mp3-tech.org/mp3infotag.html) by Gabriel Bouvigne describes
- * the actual Tag (except for small changes).
- * Details on the actual ReplayGain fields have been obtained from
- * http://www.replaygain.org .
- *
- * Apart from that, some information has been derived from phwip's LameTag
- * (http://www.silisoftware.com/applets/?scriptname=LameTag)
- *
- *
- * Code to read the ReplayGain Values stored in an Ape tag.
- *
- * Info on Lyrics3 V2.00 can be found at:
- * http://www.id3.org/lyrics3200.html
- * On the actual Ape Tag V2.0:
- * http://www.personal.uni-jena.de/~pfk/mpp/sv8/apetag.html
- *
- * Copyright (C) 2004 Jens Taprogge <jens.taprogge at post.rwth-aachen.de>
- *
- * Provided under GPL according to Jens Taprogge. (JCS -- 12 March 2004)
- */
-
-#define TAG_FOOTER 0x10
-#define LAME_OFFSET 0x74
-#define SIDEINFO_MPEG1_MONO 17
-#define SIDEINFO_MPEG1_MULTI 32
-#define SIDEINFO_MPEG2_MONO 9
-#define SIDEINFO_MPEG2_MULTI 17
-#define ID3V1_SIZE 0x80
-#define APE_FOOTER_SIZE 0x20
-#define LYRICS_FOOTER_SIZE 0x0f
-
-
-static gint lame_vcmp(gchar a[5], gchar b[5]) {
- int r;
-
- r = strncmp(a, b, 4);
- if (r) return r;
-
- if (a[4] == b[4]) return 0;
-
- /* check for '.': indicates subminor version */
- if (a[4] == '.') return 1;
- if (b[4] == '.') return -1;
-
- /* check for alpha or beta versions */
- if (a[4] == ' ') return 1;
- if (b[4] == ' ') return -1;
-
- /* check for alpha, beta etc. indicated by a, b... */
- return strncmp(&a[4], &b[4], 1);
-}
-
-
-/* buf[] must be declared unsigned -- otherwise the casts, shifts and
- additions below produce funny results */
-static void read_lame_replaygain(unsigned char buf[],
- GainData *gd, int gain_adjust) {
- char oc, nc;
- gint gain;
-
- g_return_if_fail (gd);
-
- /* buf[0] and buf[1] are a bit field:
- 3 bits: name (mask: 0xe0 = 11100000)
- 3 bits: originator (mask: 0x1c = 00011100)
- 1 bit: negative if set (mask: 0x02 = 00000010)
- 9 bits: value
- */
-
- /* check originator */
- oc = (buf[0] & 0x1c) >> 2;
- if ((oc <= 0) || (oc > 3)) return;
-
- /* check name code */
- nc = buf[0] & 0xe0;
- if (!((nc == 0x20) || (nc == 0x40))) return;
-
- gain = ((((guint)buf[0]) & 0x1) << 8) + buf[1];
-
- /* This would be a value of -0.
- * That value however is illegal by current standards and reserved for
- * future use. */
- if ((!gain) && (buf[0] & 0x02)) return;
-
- if (buf[0] & 2) gain = -gain;
-
- gain += gain_adjust;
-
- switch (nc) {
- case 0x20:
- if (gd->radio_gain_set) return;
- gd->radio_gain = (gdouble)gain / 10;
- gd->radio_gain_set = TRUE;
-/* printf("radio_gain (lame): %i\n", gd->radio_gain); */
- break;
- case 0x40:
- if (gd->audiophile_gain_set) return;
- gd->audiophile_gain = (gdouble)gain / 10;
- gd->audiophile_gain_set = TRUE;
-/* printf("audiophile_gain (lame): %i\n",
- gd->audiophile_gain);*/
- break;
- }
-}
-
-
-static inline guint32 parse_ape_uint32(char *buf) {
- return (buf[0] & 0xff) | (buf[1] & 0xff) << 8
- | (buf[2] & 0xff) << 16 | (buf[3] & 0xff) << 24;
-}
-
-static inline guint32 parse_lame_uint32(char *buf) {
- return (buf[0] & 0xff) << 24 | (buf[1] & 0xff) << 16
- | (buf[2] & 0xff) << 8 | (buf[3] & 0xff);
-}
-
-
-/*
- * mp3_get_track_lame_replaygain - read the specified file and scan for LAME Tag
- * ReplayGain information.
- *
- * @path: localtion of the file
- * @track: structure holding track information
- *
- * FIXME: Are there other encoders writing a LAME Tag using a different magic
- * string?
- * TODO: Check CRC.
- */
-
-gboolean mp3_get_track_lame_replaygain (gchar *path, GainData *gd)
-{
- struct {
- /* All members are defined in terms of chars so padding does not
- * occur. Is there a cleaner way to keep the compiler from
- * padding? */
-
- char id[3];
- char version[2];
- char flags;
- char size[4];
- } id3head;
-
- FILE *file = NULL;
- char buf[4], version[5];
- int gain_adjust = 0;
- int sideinfo;
- guint32 ps;
-
- g_return_val_if_fail (gd, FALSE);
-
- gd->radio_gain = 0;
- gd->audiophile_gain = 0;
- gd->peak_signal = 0;
- gd->radio_gain_set = FALSE;
- gd->audiophile_gain_set = FALSE;
- gd->peak_signal_set = FALSE;
-
- if (!path)
- goto rg_fail;
-
- file = fopen (path, "r");
-
- if (!file)
- goto rg_fail;
-
- /* Skip ID3 header if appropriate */
- if (fread(&id3head, 1, sizeof(id3head), file) !=
- sizeof(id3head))
- goto rg_fail;
-
- if (!strncmp(id3head.id, "ID3", 3)) {
- int realsize = 0;
-
- realsize = (id3head.size[0] & 0x7f) << 21
- | (id3head.size[1] & 0x7f) << 14
- | (id3head.size[2] & 0x7f) << 7
- | (id3head.size[3] & 0x7f);
-
- if (id3head.flags & TAG_FOOTER) {
- /* footer is copy of header */
- realsize += sizeof(id3head);
- }
-
- if (fseek(file, realsize-1, SEEK_CUR) ||
- (!fread(&buf[0], 1, 1, file)))
- goto rg_fail;
- } else {
- /* no ID3 Tag - go back */
- fseek(file, -sizeof(id3head), SEEK_CUR);
- }
-
- /* Search Xing header. The location is dependant on the MPEG Layer and
- * whether the stream is mono or not. */
- if (fread(buf, 1, 4, file) != 4) goto rg_fail;
-
- /* should start with 0xff 0xf? (synch) */
- if (((buf[0] & 0xff) != 0xff)
- || ((buf[1] & 0xf0) != 0xf0)) goto rg_fail;
-
- /* determine the length of the sideinfo */
- if (buf[1] & 0x08) {
- sideinfo = ((buf[3] & 0xc0) == 0xc0) ?
- SIDEINFO_MPEG1_MONO : SIDEINFO_MPEG1_MULTI;
- } else {
- sideinfo = ((buf[3] & 0xc0) == 0xc0) ?
- SIDEINFO_MPEG2_MONO : SIDEINFO_MPEG2_MULTI;
- }
-
- if (fseek(file, sideinfo, SEEK_CUR) ||
- (fread(&buf[0], 1, 4, file) != 4))
- goto rg_fail;
-
- /* Is this really a Xing or Info Header?
- * FIXME: Apparently (according to madplay sources) there is a different
- * possible location for the Xing header ("due to an unfortunate
- * historical event"). I do not thing we need to care though since
- * RaplayGain information is only conatined in recent files. */
- if (strncmp(buf, "Xing", 4) && strncmp(buf, "Info", 4))
- goto rg_fail;
-
- /* Check for LAME Tag */
- if (fseek(file, LAME_OFFSET, SEEK_CUR) ||
- (fread(&buf[0], 1, 4, file) != 4))
- goto rg_fail;
- if (strncmp(buf, "LAME", 4))
- goto rg_fail;
-
- /* Check LAME Version */
- if (fread(version, 1, 5, file) != 5)
- goto rg_fail;
-
- /* Skip really old versions altogether. I am not sure when radio_gain
- * information was introduced. 3.89 does not seem to supprt it though.
- * */
- if (lame_vcmp(version, "3.90") < 0) {
-/* fprintf(stderr, "Old lame version (%c%c%c%c%c). Not used.\n",
- version[0], version[1], version[2], version[3], version[4]); */
- goto rg_fail;
- }
-
- if (fseek(file, 0x2, SEEK_CUR) || (fread(buf, 1, 4, file) != 4))
- goto rg_fail;
-
- /* get the peak signal. */
- ps = parse_lame_uint32(buf);
-
- /* Don't know when fixed-point PeakSingleAmplitude
- * was introduced exactly. 3.94b will be used for now.) */
- if ((lame_vcmp(version, "3.94b") >= 0)) {
- if ((!gd->peak_signal_set) && ps) {
- gd->peak_signal = ps;
- gd->peak_signal_set = TRUE;
-/* printf("peak_signal (lame): %f\n", (double)
- gd->peak_signal / 0x800000);*/
- }
- } else {
- float f = *((float *) (void *) (&ps)) * 0x800000;
- gd->peak_signal = (guint32) f;
- /* I would like to see an example of that. */
-/* printf("peak_signal (lame floating point): %f. PLEASE report.\n",
- (double) gd->peak_signal / 0x800000);*/
- }
-
- /*
- * Versions prior to 3.95.1 used a reference volume of 83dB.
- * (As compared to the currently used 89dB.)
- */
- if ((lame_vcmp(version, "3.95.") < 0)) {
- gain_adjust = 60;
-/* fprintf(stderr, "Old lame version (%c%c%c%c%c). Adjusting gain.\n",
- version[0], version[1], version[2], version[3], version[4]); */
- }
-
- if (fread(&buf[0], 1, 2, file) != 2)
- goto rg_fail;
-
- /* radio gain */
- read_lame_replaygain (buf, gd, gain_adjust);
-
- if (fread(&buf[0], 1, 2, file) != 2)
- goto rg_fail;
-
- /* audiophile gain */
- read_lame_replaygain (buf, gd, gain_adjust);
-
- fclose(file);
- return TRUE;
-
-rg_fail:
- if (file)
- fclose(file);
- return FALSE;
-}
-
-
-/*
- * mp3_get_track_ape_replaygain - read the specified file and scan for Ape Tag
- * ReplayGain information.
- *
- * @path: localtion of the file
- * @track: structure holding track information
- *
- * The function only modifies the gains if they have not previously been set.
- */
-
-gboolean mp3_get_track_ape_replaygain(gchar *path, GainData *gd)
-{
- /* The Ape Tag is located a t the end of the file. Or at least that
- * seems where it can most likely be found. Either it is at the very end
- * or before a trailing ID3v1 Tag. Sometimes a Lyrics3 Tag is placed
- * between the ID3v1 and the Ape Tag.
- * If you find files that have the Tags located in different
- * positions please let me know. */
-
- FILE *file = NULL;
- char buf[16];
- char *dbuf = NULL, *ep;
-
- int offset = 0;
- int i;
- int pos = 0, pos2 = 0;
- guint32 version;
- guint32 data_length;
- guint32 entry_length = 0;
- guint32 entries;
- double d;
-
- g_return_val_if_fail (gd, FALSE);
- g_return_val_if_fail (path, FALSE);
-
- file = fopen (path, "r");
-
- if (!file)
- goto rg_fail;
-
- /* check for ID3v1 Tag */
- if (fseek(file, -ID3V1_SIZE, SEEK_END) ||
- fread(&buf, 1, 3, file) != 3)
- goto rg_fail;
- if (!strncmp(buf, "TAG", 3)) offset -= ID3V1_SIZE;
-
- /* check for Lyrics3 Tag */
- if (fseek(file, -9 + offset, SEEK_END) ||
- fread(&buf, 1, 9, file) != 9)
- goto rg_fail;
- if (!strncmp(buf, "LYRICS200", 9)) {
- if (fseek(file, -LYRICS_FOOTER_SIZE + offset, SEEK_END) ||
- fread(&buf, 1, 9, file) != 9)
- goto rg_fail;
- data_length = buf[0] - '0';
- for (i = 1; i < 6; i++) {
- data_length *= 10;
- data_length += buf[i] - '0';
- }
- if (fseek(file, -LYRICS_FOOTER_SIZE - data_length + offset,
- SEEK_END) ||
- fread(&buf, 1, 11, file) != 11)
- goto rg_fail;
- if (!strncmp(buf, "LYRICSBEGIN", 11))
- offset -= LYRICS_FOOTER_SIZE + data_length;
- }
-
- /* check for APE Tag */
- if (fseek(file, -APE_FOOTER_SIZE + offset, SEEK_END) ||
- fread(&buf, 1, 8, file) != 8)
- goto rg_fail;
- if (strncmp(buf, "APETAGEX", 8)) goto rg_fail;
-
- /* Check the version of the tag. 1000 and 2000 (v1.0 and 2.0) are the
- * only ones I know about. Make suer things do not break in the future.
- * */
- if (fread(&buf, 1, 4, file) != 4)
- goto rg_fail;
- version = parse_ape_uint32(buf);
- if (version != 1000 && version != 2000)
- goto rg_fail;
-
- /* determine data length */
- if (fread(&buf, 1, 4, file) != 4)
- goto rg_fail;
- data_length = parse_ape_uint32(buf) - APE_FOOTER_SIZE;
-
- /* determine number of entries */
- if (fread(&buf, 1, 4, file) != 4)
- goto rg_fail;
- entries = parse_ape_uint32(buf);
-
- /* seek to first entry and read the whole buffer*/
- if (fseek(file, -APE_FOOTER_SIZE + offset - data_length, SEEK_END))
- goto rg_fail;
- if (!(dbuf = malloc(data_length)))
- goto rg_fail;
- if (fread(dbuf, 1, data_length, file) != data_length)
- goto rg_fail;
-
- for (i = 0; i < entries; i++) {
- if (gd->radio_gain_set && gd->peak_signal_set) break;
- pos = pos2 + entry_length;
- if (pos > data_length - 10) break;
-
- entry_length = parse_ape_uint32(&dbuf[pos]); pos += 4;
- pos += 4;
-
- pos2 = pos;
- while (dbuf[pos2] && pos2 < data_length) pos2++;
- if (pos2 == data_length) break;
- pos2++;
-
- if (entry_length + 1 > sizeof(buf))
- continue;
-/* printf ("%s:%d:%d\n",&dbuf[pos], pos2, pos); */
- if (!gd->radio_gain_set && !strcasecmp(&dbuf[pos],
- "REPLAYGAIN_TRACK_GAIN")) {
- memcpy(buf, &dbuf[pos2], entry_length);
- buf[entry_length] = '\0';
-
- d = g_ascii_strtod(buf, &ep);
-/* printf("%f\n", d); */
- if ((ep == buf + entry_length - 3)
- && (!strncasecmp(ep, " dB", 3))) {
- gd->radio_gain = d;
- gd->radio_gain_set = TRUE;
-/* printf("radio_gain (ape): %i\n", gd->radio_gain);*/
- }
-
- continue;
- }
- if (!gd->peak_signal_set && !strcasecmp(&dbuf[pos],
- "REPLAYGAIN_TRACK_PEAK")) {
- memcpy(buf, &dbuf[pos2], entry_length);
- buf[entry_length] = '\0';
-
- d = g_ascii_strtod(buf, &ep);
- if (ep == buf + entry_length) {
- d *= 0x800000;
- gd->peak_signal = (guint32) floor(d + 0.5);
- gd->peak_signal_set = TRUE;
-/* printf("peak_signal (ape): %f\n", (double) gd->peak_signal / 0x800000);*/
- }
-
- continue;
- }
- }
-
- free(dbuf);
- fclose(file);
- return TRUE;
-
-rg_fail:
- if (dbuf)
- free(dbuf);
- if (file)
- fclose(file);
- return FALSE;
-}
-
-
-/* ----------------------------------------------------------------------
-
- mp3gain code
-
----------------------------------------------------------------------- */
-
-#include <sys/wait.h>
-#include <fcntl.h>
-
-
-
-
-
-
-/**
- * mp3_read_soundcheck:
- *
- * try to read the ReplayGain values from the LAME or Ape Tags and set
- * the track's soundcheck field accordingly.
- *
- * @path: localtion of the file
- * @track: structure holding track information
- *
- * The function always rereads the gain from the file.
- *
- * Returns TRUE if the soundcheck field could be set.
- */
-gboolean mp3_read_soundcheck (gchar *path, Track *track)
-{
- GainData gd;
-
- g_return_val_if_fail (track, FALSE);
-
- memset (&gd, 0, sizeof (GainData));
-
- gd.radio_gain_set = FALSE;
- gd.audiophile_gain_set = FALSE;
- gd.peak_signal_set = FALSE;
-
- mp3_get_track_lame_replaygain (path, &gd);
- if (gd.radio_gain_set)
- {
- track->soundcheck = replaygain_to_soundcheck (gd.radio_gain);
- return TRUE;
- }
-
- mp3_get_track_ape_replaygain (path, &gd);
- if (gd.radio_gain_set)
- {
- track->soundcheck = replaygain_to_soundcheck (gd.radio_gain);
- return TRUE;
- }
-
- return FALSE;
-}
-
-
-
-
-
-
-/* mp3 slot size in bytes */
-int slotsize[3] = {4,1,1}; /* layer 1, layer 2, layer 3 */
-
-int samplesperframe[2][3] = {
- { /* MPEG 2.0 */
- 384,1152,576 /* layer 1, layer 2, layer 3 */
- },
-
- { /* MPEG 1.0 */
- 384,1152,1152 /* layer 1, layer 2, layer 3 */
- }
-};
-
-
-/*
- * mp3_get_track_lame_gapless - read the specified file and scan for LAME Tag
- * gapless information.
- *
- * @path: localtion of the file
- * @track: structure holding track information
- *
- * TODO: Split off non-LAME stuff (samplecount, gapless_data) to a separate function since it's generic
- */
-gboolean mp3_get_track_lame_gapless (gchar *path, GaplessData *gd)
-{
- FILE *file = NULL;
- char buf[4], version[5];
- unsigned char ubuf[4];
- int sideinfo;
- int i;
-
- g_return_val_if_fail (gd, FALSE);
-
- if (!path)
- goto gp_fail;
-
- file = fopen (path, "rb");
-
- if (!file)
- goto gp_fail;
-
- /* use get_first_header() to seek to the first mp3 header */
- MP3Info *mp3i = NULL;
- mp3i = g_malloc0 (sizeof (MP3Info));
- mp3i->filename = path;
- mp3i->file = file;
- get_mp3_info (mp3i);
- get_first_header (mp3i, 0);
-
- int xing_header_offset = ftell (file);
-
- MP3Header h;
- if (!get_header (file, &h))
- goto gp_fail;
-
- int mysamplesperframe = samplesperframe[h.version & 1][3 - h.layer];
-
- /* Determine offset of Xing header based on sideinfo size */
- if (h.version & 0x1)
- {
- sideinfo = (h.mode & 0x2) ?
- SIDEINFO_MPEG1_MONO : SIDEINFO_MPEG1_MULTI;
- }
- else
- {
- sideinfo = (h.mode & 0x2) ?
- SIDEINFO_MPEG2_MONO : SIDEINFO_MPEG2_MULTI;
- }
-
- if (fseek (file, sideinfo, SEEK_CUR) ||
- (fread (&buf[0], 1, 4, file) != 4))
- goto gp_fail;
-
- /* Is this really a Xing or Info Header?
- * FIXME: Apparently (according to madplay sources) there is a different
- * possible location for the Xing header ("due to an unfortunate
- * historical event"). I do not thing we need to care though since
- * ReplayGain information is only contained in recent files. */
- if (strncmp (buf, "Xing", 4) && strncmp (buf, "Info", 4))
- goto gp_fail;
-
- /* Determine the offset of the LAME tag based on contents of the Xing header */
- int flags;
- fread (&flags, 4, 1, file);
- int toskip = 0;
- if (flags | 0x1)
- { /* frames field is set */
- toskip += 4;
- }
- if (flags | 0x2)
- { /* bytes field is set */
- toskip += 4;
- }
- if (flags | 0x4)
- { /* TOC field is set */
- toskip += 100;
- }
- if (flags | 0x8)
- { /* quality field is set */
- toskip += 4;
- }
-
- /* Check for LAME Tag */
- if (fseek (file, toskip, SEEK_CUR) || (fread (&buf[0], 1, 4, file) != 4))
- goto gp_fail;
- if (strncmp (buf, "LAME", 4))
- goto gp_fail;
-
- /* Check LAME Version */
- if (fread (version, 1, 5, file) != 5)
- goto gp_fail;
-
- /* XXX skip old LAME versions, or just assume that pre/postgap
- * turn out zeros anyway, or check the CRC to vaidate the tag? */
-
- gboolean cbr = FALSE;
- if (fread (ubuf, 1, 1, file) != 1)
- goto gp_fail;
-
- if ((ubuf[0] & 0xf) == 0x1)
- cbr = TRUE;
-
- if (fseek (file, 0xB, SEEK_CUR) || (fread (ubuf, 1, 4, file) != 4))
- goto gp_fail;
-
- /* set pregap and postgap directly from LAME header */
- gd->pregap = (ubuf[0] << 4) + (ubuf[1] >> 4);
- gd->postgap = ((ubuf[1] & 0xf) << 8) + ubuf[2];
-
- /* jump the end of the frame with the xing header */
- if (fseek (file, xing_header_offset + frame_length (&h), SEEK_SET))
- goto gp_fail;
-
- /* counts bytes from the start of the 1st sync frame */
- int totaldatasize = frame_length (&h);
-
- /* keeps track of the last 8 frame sizes */
- int lastframes[8];
-
- /* counts number of music frames */
- int totalframes = 0;
-
- /* quickly parse the file, reading only frame headers */
- int l = 0;
- while ((l = get_header (file, &h)) != 0)
- {
- for (i = 7; i > 0; i--)
- {
- lastframes[i] = lastframes[i - 1];
- }
- lastframes[0] = l;
- totaldatasize += l;
- totalframes++;
-
- if (fseek (file, l - FRAME_HEADER_SIZE, SEEK_CUR))
- goto gp_fail;
-
- }
-
- int finaleight = 0;
- for (i = 0; i < 8; i++)
- {
- finaleight += lastframes[i];
- }
-
- if (cbr)
- totalframes++;
-
- /* all but last eight frames */
- gd->gapless_data = totaldatasize - finaleight;
- /* total samples minus pre/postgap */
- gd->samplecount = totalframes * mysamplesperframe - gd->pregap - gd->postgap;
- fclose(file);
-
- return TRUE;
-
-
- gp_fail:
- if (file)
- fclose (file);
- return FALSE;
-
-}
-
-
-
-/**
- * mp3_read_gapless:
- *
- * try to read the gapless values from the LAME Tag and set
- * the track's pregap, postgap, samplecount, and gapless_data fields
- * accordingly.
- *
- * @path: location of the file
- * @track: structure holding track information
- *
- * The function always rereads the data from the file.
- *
- * Returns TRUE if all four gapless fields could be
- * set. etrack->tchanged is set to TRUE if data has been changed,
- * FALSE otherwise.
- */
-gboolean mp3_read_gapless (char *path, Track *track)
-{
- GaplessData gd;
- ExtraTrackData *etr;
-
- g_return_val_if_fail (track, FALSE);
-
- etr = track->userdata;
-
- memset (&gd, 0, sizeof (GaplessData));
-
- gd.pregap = 0;
- gd.samplecount = 0;
- gd.postgap = 0;
- gd.gapless_data = 0;
-
- mp3_get_track_lame_gapless (path, &gd);
-
- etr->tchanged = FALSE;
-
- if ((gd.pregap) && (gd.samplecount) && (gd.postgap) && (gd.gapless_data))
- {
- if ((track->pregap != gd.pregap) ||
- (track->samplecount != gd.samplecount) ||
- (track->postgap != gd.postgap) ||
- (track->gapless_data != gd.gapless_data) ||
- (track->gapless_track_flag == FALSE))
- {
- etr->tchanged = TRUE;
- track->pregap = gd.pregap;
- track->samplecount = gd.samplecount;
- track->postgap = gd.postgap;
- track->gapless_data = gd.gapless_data;
- track->gapless_track_flag = TRUE;
- }
- }
- return FALSE;
-}
-
-
-
-/* ----------------------------------------------------------------------
-
- From here starts original gtkpod code
-
----------------------------------------------------------------------- */
-
-/* Return a Track structure with all information read from the mp3
- file filled in */
-Track *mp3_get_file_info (gchar *name)
-{
- Track *track = NULL;
- File_Tag filetag;
- MP3Info *mp3i=NULL;
- FILE *file;
- guchar *image_data = NULL;
- gsize image_data_len = 0;
-
- g_return_val_if_fail (name, NULL);
-
- /* Attempt to open the file */
- file = fopen (name, "r");
- if (file)
- {
- mp3i = g_malloc0 (sizeof (MP3Info));
- mp3i->filename = name;
- mp3i->file = file;
- get_mp3_info (mp3i);
- mp3i->file = NULL;
- fclose (file);
- }
- else
- {
- gchar *fbuf = charset_to_utf8 (name);
- gtkpod_warning(_("ERROR while opening file: '%s' (%s).\n"),
- fbuf, g_strerror(errno));
- g_free (fbuf);
- return NULL;
- }
-
- track = gp_track_new ();
- track->filetype = g_strdup ("MPEG audio file");
-
- if (prefs_get_int("readtags") && (id3_tag_read (name, &filetag) == TRUE))
- {
-
- if (filetag.album)
- {
- track->album = filetag.album;
- }
-
- if (filetag.artist)
- {
- track->artist = filetag.artist;
- }
-
- if (filetag.title)
- {
- track->title = filetag.title;
- }
-
- if (filetag.genre)
- {
- track->genre = filetag.genre;
- }
-
- if (filetag.composer)
- {
- track->composer = filetag.composer;
- }
-
- if (filetag.comment)
- {
- track->comment = filetag.comment;
- }
-
- if (filetag.podcasturl)
- {
- track->podcasturl = filetag.podcasturl;
- }
-
- if (filetag.podcastrss)
- {
- track->podcastrss = filetag.podcastrss;
- }
-
- if (filetag.subtitle)
- {
- track->subtitle = filetag.subtitle;
- }
-
- if (filetag.description)
- {
- track->description = filetag.description;
- }
-
- if (filetag.sort_artist)
- {
- track->sort_artist = filetag.sort_artist;
- }
-
- if (filetag.sort_title)
- {
- track->sort_title = filetag.sort_title;
- }
-
- if (filetag.sort_album)
- {
- track->sort_album = filetag.sort_album;
- }
-
- if (filetag.sort_albumartist)
- {
- track->sort_albumartist = filetag.sort_albumartist;
- }
-
- if (filetag.sort_composer)
- {
- track->sort_composer = filetag.sort_composer;
- }
-
- if (filetag.year == NULL)
- {
- track->year = 0;
- }
- else
- {
- track->year = atoi(filetag.year);
- g_free (filetag.year);
- }
-
- if (filetag.trackstring == NULL)
- {
- track->track_nr = 0;
- }
- else
- {
- track->track_nr = atoi(filetag.trackstring);
- g_free (filetag.trackstring);
- }
-
- if (filetag.track_total == NULL)
- {
- track->tracks = 0;
- }
- else
- {
- track->tracks = atoi(filetag.track_total);
- g_free (filetag.track_total);
- }
- /* CD/disc number handling */
- if (filetag.cdnostring == NULL)
- {
- track->cd_nr = 0;
- }
- else
- {
- track->cd_nr = atoi(filetag.cdnostring);
- g_free (filetag.cdnostring);
- }
-
- if (filetag.cdno_total == NULL)
- {
- track->cds = 0;
- }
- else
- {
- track->cds = atoi(filetag.cdno_total);
- g_free (filetag.cdno_total);
- }
-
- if (filetag.compilation == NULL)
- {
- track->compilation = 0;
- }
- else
- {
- track->compilation = atoi(filetag.compilation);
- g_free (filetag.compilation);
- }
-
- if (filetag.BPM == NULL)
- {
- track->BPM = 0;
- }
- else
- {
- track->BPM = atoi(filetag.BPM);
- g_free (filetag.BPM);
- }
-
- if (filetag.lyrics)
- {
- track->lyrics_flag = 0x01;
- g_free (filetag.lyrics);
- }
- else
- {
- track->lyrics_flag = 0x00;
- }
- }
-
- if (prefs_get_int("coverart_apic") &&
- (id3_apic_read (name, &image_data, &image_data_len) == TRUE))
- {
- if (image_data)
- {
- gp_track_set_thumbnails_from_data (track,
- image_data,
- image_data_len);
- g_free (image_data);
- }
- }
-
- mp3_read_soundcheck (name, track);
-
- mp3_read_gapless (name, track);
-
-#if LOCALDEBUG
- printf("%s\n", name);
- printf("\tpregap: %i\n", track->pregap);
- printf("\tpostgap: %i\n", track->postgap);
- printf("\tsamplecount: %li\n", track->samplecount);
- printf("\tgaplessdata: %i\n", track->gapless_data);
-#endif
-
-
- /* Get additional info (play time and bitrate */
- if (mp3i)
- {
- track->tracklen = mp3i->milliseconds;
- track->bitrate = (gint)(mp3i->vbr_average);
- track->samplerate = mp3file_header_frequency (&mp3i->header);
- g_free (mp3i);
- }
- /* Fall back to xmms code if tracklen is 0 */
- if (track->tracklen == 0)
- {
- track->tracklen = get_track_time (name);
- if (track->tracklen)
- track->bitrate = (float)track->size*8/track->tracklen;
- }
-
- if (track->tracklen == 0)
- {
- /* Tracks with zero play length are ignored by iPod... */
- gtkpod_warning (_("File \"%s\" has zero play length. Ignoring.\n"),
- name);
- gp_track_free (track);
- track = NULL;
- }
- return track;
-}
Copied: gtkpod/tags/0.99.10-5/src/mp3file.c (from rev 267, gtkpod/trunk/src/mp3file.c)
===================================================================
--- gtkpod/tags/0.99.10-5/src/mp3file.c (rev 0)
+++ gtkpod/tags/0.99.10-5/src/mp3file.c 2007-11-20 13:46:35 UTC (rev 280)
@@ -0,0 +1,2677 @@
+/* Time-stamp: <2007-06-26 00:39:11 jcs>
+|
+| Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
+| Part of the gtkpod project.
+|
+| URL: http://www.gtkpod.org/
+| URL: http://gtkpod.sourceforge.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
+|
+| iTunes and iPod are trademarks of Apple
+|
+| This product is not supported/written/published by Apple!
+|
+| $Id: mp3file.c 1591 2007-06-26 03:33:25Z tmzullinger $
+*/
+
+
+#define LOCALDEBUG 0
+
+
+/* The code in the first section of this file is taken from the
+ * mp3info (http://www.ibiblio.org/mp3info/) project. Only the code
+ * needed for the playlength calculation has been extracted. */
+
+/* The code in the second section of this file is taken from the
+ * mpg123 code used in xmms-1.2.7 (Input/mpg123). Only the code needed
+ * for the playlength calculation has been extracted. */
+
+/* The code in the last section of this file is original gtkpod
+ * code. */
+
+/****************
+ * Declarations *
+ ****************/
+
+#include <glib.h>
+#include <math.h>
+/*
+ * Description of each item of the TagList list
+ */
+typedef struct _File_Tag File_Tag;
+typedef struct _GainData GainData;
+typedef struct _GaplessData GaplessData;
+
+struct _File_Tag
+{
+ gchar *title; /* Title of track */
+ gchar *artist; /* Artist name */
+ gchar *album; /* Album name */
+ gchar *year; /* Year of track */
+ gchar *trackstring; /* Position of track in the album */
+ gchar *track_total; /* The number of tracks for the album (ex: 12/20) */
+ gchar *genre; /* Genre of song */
+ gchar *comment; /* Comment */
+ gchar *composer; /* Composer */
+ guint32 songlen; /* Length of file in ms */
+ gchar *cdnostring; /* Position of disc in the album */
+ gchar *cdno_total; /* The number of discs in the album (ex: 1/2) */
+ gchar *compilation; /* The track is a member of a compilation */
+ gchar *podcasturl; /* The following are mainly used for podcasts */
+ gchar *sort_artist;
+ gchar *sort_title;
+ gchar *sort_album;
+ gchar *sort_albumartist;
+ gchar *sort_composer;
+ gchar *description;
+ gchar *podcastrss;
+ gchar *time_released;
+ gchar *subtitle;
+ gchar *BPM; /* beats per minute */
+ gchar *lyrics; /* does not appear to be the full lyrics --
+ only used to set the flag 'lyrics_flag'
+ of the Track structure */
+};
+
+
+struct _GainData
+{
+ guint32 peak_signal; /* LAME Peak Signal * 0x800000 */
+ gdouble radio_gain; /* RadioGain in dB
+ (as defined by www.replaygain.org) */
+ gdouble audiophile_gain;/* AudiophileGain in dB
+ (as defined by www.replaygain.org) */
+ gboolean peak_signal_set; /* has the peak signal been set? */
+ gboolean radio_gain_set; /* has the radio gain been set? */
+ gboolean audiophile_gain_set;/* has the audiophile gain been set? */
+};
+
+struct _GaplessData
+{
+ guint32 pregap; /* number of pregap samples */
+ guint64 samplecount; /* number of actual music samples */
+ guint32 postgap; /* number of postgap samples */
+ guint32 gapless_data; /* number of bytes from the first sync frame to the 8th to last frame */
+};
+
+/* This code is taken from the mp3info code. Only the code needed for
+ * the playlength calculation has been extracted */
+
+/*
+ mp3tech.c - Functions for handling MP3 files and most MP3 data
+ structure manipulation.
+
+ Copyright (C) 2000-2001 Cedric Tefft <cedric at earthling.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ***************************************************************************
+
+ This file is based in part on:
+
+ * MP3Info 0.5 by Ricardo Cerqueira <rmc at rccn.net>
+ * MP3Stat 0.9 by Ed Sweetman <safemode at voicenet.com> and
+ Johannes Overmann <overmann at iname.com>
+
+*/
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "mp3file.h"
+#include "charset.h"
+#include "itdb.h"
+#include "file.h"
+#include "misc.h"
+
+
+/* MIN_CONSEC_GOOD_FRAMES defines how many consecutive valid MP3 frames
+ we need to see before we decide we are looking at a real MP3 file */
+#define MIN_CONSEC_GOOD_FRAMES 4
+#define FRAME_HEADER_SIZE 4
+#define MIN_FRAME_SIZE 21
+
+enum VBR_REPORT { VBR_VARIABLE, VBR_AVERAGE, VBR_MEDIAN };
+
+typedef struct {
+ gulong sync;
+ guint version;
+ guint layer;
+ guint crc;
+ guint bitrate;
+ guint freq;
+ guint padding;
+ guint extension;
+ guint mode;
+ guint mode_extension;
+ guint copyright;
+ guint original;
+ guint emphasis;
+} MP3Header;
+
+typedef struct {
+ gchar *filename;
+ FILE *file;
+ off_t datasize;
+ gint header_isvalid;
+ MP3Header header;
+ gint id3_isvalid;
+ gint vbr;
+ float vbr_average;
+ gint milliseconds;
+ gint frames;
+ gint badframes;
+} MP3Info;
+
+/* This is for xmms code */
+static guint get_track_time(gchar *path);
+
+
+
+/* ------------------------------------------------------------
+
+ start of first section
+
+ ------------------------------------------------------------ */
+void get_mp3_info(MP3Info *mp3);
+
+gint frequencies[3][4] = {
+ {22050,24000,16000,50000}, /* MPEG 2.0 */
+ {44100,48000,32000,50000}, /* MPEG 1.0 */
+ {11025,12000,8000,50000} /* MPEG 2.5 */
+};
+
+/* "0" added by JCS */
+gint bitrate[2][3][16] = {
+ { /* MPEG 2.0 */
+ {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,0},/* layer 1 */
+ {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0}, /* layer 2 */
+ {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0} /* layer 3 */
+ },
+
+ { /* MPEG 1.0 */
+ {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},/* layer 1 */
+ {0,32,48,56,64,80,96,112,128,160,192,224,256,320,384,0}, /* layer 2 */
+ {0,32,40,48,56,64,80,96,112,128,160,192,224,256,320,0} /* layer 3 */
+ }
+};
+
+gint frame_size_index[] = {24000, 72000, 72000};
+
+
+gchar *mode_text[] = {
+ "stereo", "joint stereo", "dual channel", "mono"
+};
+
+gchar *emphasis_text[] = {
+ "none", "50/15 microsecs", "reserved", "CCITT J 17"
+};
+
+
+static gint mp3file_header_bitrate(MP3Header *h) {
+ return bitrate[h->version & 1][3-h->layer][h->bitrate];
+}
+
+
+static gint mp3file_header_frequency(MP3Header *h) {
+ return frequencies[h->version][h->freq];
+}
+
+
+gint frame_length(MP3Header *header) {
+ return header->sync == 0xFFE ?
+ (frame_size_index[3-header->layer]*((header->version&1)+1)*
+ mp3file_header_bitrate(header)/(float)mp3file_header_frequency(header))+
+ header->padding : 1;
+}
+
+/* Get next MP3 frame header.
+ Return codes:
+ positive value = Frame Length of this header
+ 0 = No, we did not retrieve a valid frame header
+*/
+gint get_header(FILE *file,MP3Header *header)
+{
+ guchar buffer[FRAME_HEADER_SIZE];
+ gint fl;
+
+ if(fread(&buffer,FRAME_HEADER_SIZE,1,file)<1) {
+ header->sync=0;
+ return 0;
+ }
+ header->sync=(((gint)buffer[0]<<4) | ((gint)(buffer[1]&0xE0)>>4));
+ if(buffer[1] & 0x10) header->version=(buffer[1] >> 3) & 1;
+ else header->version=2;
+ header->layer=(buffer[1] >> 1) & 3;
+ if (header->layer == 0)
+ {
+ header->layer = 1; /* sanity added by JCS */
+ }
+ if((header->sync != 0xFFE) || (header->layer != 1)) {
+ header->sync=0;
+ return 0;
+ }
+ header->crc=buffer[1] & 1;
+ header->bitrate=(buffer[2] >> 4) & 0x0F;
+ header->freq=(buffer[2] >> 2) & 0x3;
+ header->padding=(buffer[2] >>1) & 0x1;
+ header->extension=(buffer[2]) & 0x1;
+ header->mode=(buffer[3] >> 6) & 0x3;
+ header->mode_extension=(buffer[3] >> 4) & 0x3;
+ header->copyright=(buffer[3] >> 3) & 0x1;
+ header->original=(buffer[3] >> 2) & 0x1;
+ header->emphasis=(buffer[3]) & 0x3;
+
+ return ((fl=frame_length(header)) >= MIN_FRAME_SIZE ? fl : 0);
+}
+
+gint sameConstant(MP3Header *h1, MP3Header *h2) {
+ if((*(guint*)h1) == (*(guint*)h2)) return 1;
+
+ if((h1->version == h2->version ) &&
+ (h1->layer == h2->layer ) &&
+ (h1->crc == h2->crc ) &&
+ (h1->freq == h2->freq ) &&
+ (h1->mode == h2->mode ) &&
+ (h1->copyright == h2->copyright ) &&
+ (h1->original == h2->original ) &&
+ (h1->emphasis == h2->emphasis ))
+ return 1;
+ else return 0;
+}
+
+
+gint get_first_header(MP3Info *mp3, long startpos)
+{
+ gint k, l=0,c;
+ MP3Header h, h2;
+ long valid_start=0;
+
+ fseek(mp3->file,startpos,SEEK_SET);
+ while (1) {
+ while((c=fgetc(mp3->file)) != 255 && (c != EOF));
+ if(c == 255) {
+ ungetc(c,mp3->file);
+ valid_start=ftell(mp3->file);
+ if((l=get_header(mp3->file,&h))) {
+ fseek(mp3->file,l-FRAME_HEADER_SIZE,SEEK_CUR);
+ for(k=1; (k < MIN_CONSEC_GOOD_FRAMES) && (mp3->datasize-ftell(mp3->file) >= FRAME_HEADER_SIZE); k++) {
+ if(!(l=get_header(mp3->file,&h2))) break;
+ if(!sameConstant(&h,&h2)) break;
+ fseek(mp3->file,l-FRAME_HEADER_SIZE,SEEK_CUR);
+ }
+ if(k == MIN_CONSEC_GOOD_FRAMES) {
+ fseek(mp3->file,valid_start,SEEK_SET);
+ memcpy(&(mp3->header),&h2,sizeof(MP3Header));
+ mp3->header_isvalid=1;
+ return 1;
+ }
+ }
+ } else {
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+
+/* get_next_header() - read header at current position or look for
+ the next valid header if there isn't one at the current position
+*/
+gint get_next_header(MP3Info *mp3)
+{
+ gint l=0,c,skip_bytes=0;
+ MP3Header h;
+
+ while(1) {
+ while((c=fgetc(mp3->file)) != 255 && (ftell(mp3->file) < mp3->datasize)) skip_bytes++;
+ if(c == 255) {
+ ungetc(c,mp3->file);
+ if((l=get_header(mp3->file,&h))) {
+ if(skip_bytes) mp3->badframes++;
+ fseek(mp3->file,l-FRAME_HEADER_SIZE,SEEK_CUR);
+ return 15-h.bitrate;
+ } else {
+ skip_bytes += FRAME_HEADER_SIZE;
+ }
+ } else {
+ if(skip_bytes) mp3->badframes++;
+ return 0;
+ }
+ }
+}
+
+
+void get_mp3_info(MP3Info *mp3)
+{
+ gint frame_type[15]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ float milliseconds=0,total_rate=0;
+ gint frames=0,frame_types=0,frames_so_far=0;
+ gint vbr_median=-1;
+ guint bitrate;
+ gint counter=0;
+ MP3Header header;
+ struct stat filestat;
+ off_t data_start=0;
+
+
+ stat(mp3->filename,&filestat);
+ mp3->datasize=filestat.st_size;
+
+ if(get_first_header(mp3,0L)) {
+ data_start=ftell(mp3->file);
+ while((bitrate=get_next_header(mp3))) {
+ if (bitrate < 15) /* sanity added by JCS */
+ frame_type[15-bitrate]++;
+ frames++;
+ }
+ memcpy(&header,&(mp3->header),sizeof(MP3Header));
+ for(counter=0;counter<15;counter++) {
+ if(frame_type[counter]) {
+ float header_bitrate; /* introduced by JCS to speed up */
+ frame_types++;
+ header.bitrate=counter;
+ frames_so_far += frame_type[counter];
+ header_bitrate = mp3file_header_bitrate(&header);
+ if (header_bitrate != 0)
+ milliseconds += (float)(8*frame_length(&header)*frame_type[counter])/header_bitrate;
+ total_rate += header_bitrate*frame_type[counter];
+ if((vbr_median == -1) && (frames_so_far >= frames/2))
+ vbr_median=counter;
+ }
+ }
+ mp3->milliseconds=(gint)(milliseconds+0.5);
+ mp3->header.bitrate=vbr_median;
+ mp3->vbr_average=total_rate/(float)frames;
+ mp3->frames=frames;
+ if(frame_types > 1) {
+ mp3->vbr=1;
+ }
+ }
+}
+
+
+
+
+/* ------------------------------------------------------------
+
+ xmms code
+
+
+ ------------------------------------------------------------ */
+
+/*
+| Changed by Jorg Schuler <jcsjcs at users.sourceforge.net> to
+| compile with the gtkpod project. 2003/04/01
+*/
+
+/* This code is taken from the mpg123 code used in xmms-1.2.7
+ * (Input/mpg123). Only the code needed for the playlength calculation
+ * has been extracted */
+
+#include "mp3file.h"
+#include <stdio.h>
+#include <string.h>
+
+#define FRAMES_FLAG 0x0001
+#define BYTES_FLAG 0x0002
+#define TOC_FLAG 0x0004
+#define VBR_SCALE_FLAG 0x0008
+
+#define SBLIMIT 32
+#define SCALE_BLOCK 12
+#define SSLIMIT 18
+
+#define MPG_MD_STEREO 0
+#define MPG_MD_JOINT_STEREO 1
+#define MPG_MD_DUAL_CHANNEL 2
+#define MPG_MD_MONO 3
+#define MAXFRAMESIZE 1792
+#define real float
+
+struct bitstream_info
+{
+ int bitindex;
+ unsigned char *wordpointer;
+};
+
+struct bitstream_info bsi;
+
+real mpg123_muls[27][64]; /* also used by layer 1 */
+
+int tabsel_123[2][3][16] =
+{
+ {
+ {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,},
+ {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384,},
+ {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,}},
+
+ {
+ {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,},
+ {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,},
+ {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}}
+};
+
+long mpg123_freqs[9] =
+{44100, 48000, 32000, 22050, 24000, 16000, 11025, 12000, 8000};
+
+/*
+ * structure to receive extracted header
+ */
+typedef struct
+{
+ int frames; /* total bit stream frames from Xing header data */
+ int bytes; /* total bit stream bytes from Xing header data */
+ unsigned char toc[100]; /* "table of contents" */
+} xing_header_t;
+
+struct al_table
+{
+ short bits;
+ short d;
+};
+
+struct frame
+{
+ struct al_table *alloc;
+ int (*synth) (real *, int, unsigned char *, int *);
+ int (*synth_mono) (real *, unsigned char *, int *);
+#ifdef USE_3DNOW
+ void (*dct36)(real *,real *,real *,real *,real *);
+#endif
+ int stereo;
+ int jsbound;
+ int single;
+ int II_sblimit;
+ int down_sample_sblimit;
+ int lsf;
+ int mpeg25;
+ int down_sample;
+ int header_change;
+ int lay;
+ int (*do_layer) (struct frame * fr);
+ int error_protection;
+ int bitrate_index;
+ int sampling_frequency;
+ int padding;
+ int extension;
+ int mode;
+ int mode_ext;
+ int copyright;
+ int original;
+ int emphasis;
+ int framesize; /* computed framesize */
+};
+
+static guint32 convert_to_header(guint8 * buf)
+{
+
+ return (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3];
+}
+
+static int mpg123_head_check(unsigned long head)
+{
+ if ((head & 0xffe00000) != 0xffe00000)
+ return FALSE;
+ if (!((head >> 17) & 3))
+ return FALSE;
+ if (((head >> 12) & 0xf) == 0xf)
+ return FALSE;
+ if (!((head >> 12) & 0xf))
+ return FALSE;
+ if (((head >> 10) & 0x3) == 0x3)
+ return FALSE;
+ if (((head >> 19) & 1) == 1 && ((head >> 17) & 3) == 3 && ((head >> 16) & 1) == 1)
+ return FALSE;
+ if ((head & 0xffff0000) == 0xfffe0000)
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/*
+ * the code a header and write the information
+ * into the frame structure
+ */
+static int mpg123_decode_header(struct frame *fr, unsigned long newhead)
+{
+ int ssize;
+
+ if (newhead & (1 << 20))
+ {
+ fr->lsf = (newhead & (1 << 19)) ? 0x0 : 0x1;
+ fr->mpeg25 = 0;
+ }
+ else
+ {
+ fr->lsf = 1;
+ fr->mpeg25 = 1;
+ }
+ fr->lay = 4 - ((newhead >> 17) & 3);
+ if (fr->mpeg25)
+ {
+ fr->sampling_frequency = 6 + ((newhead >> 10) & 0x3);
+ }
+ else
+ fr->sampling_frequency = ((newhead >> 10) & 0x3) + (fr->lsf * 3);
+ fr->error_protection = ((newhead >> 16) & 0x1) ^ 0x1;
+
+ fr->bitrate_index = ((newhead >> 12) & 0xf);
+ fr->padding = ((newhead >> 9) & 0x1);
+ fr->extension = ((newhead >> 8) & 0x1);
+ fr->mode = ((newhead >> 6) & 0x3);
+ fr->mode_ext = ((newhead >> 4) & 0x3);
+ fr->copyright = ((newhead >> 3) & 0x1);
+ fr->original = ((newhead >> 2) & 0x1);
+ fr->emphasis = newhead & 0x3;
+
+ fr->stereo = (fr->mode == MPG_MD_MONO) ? 1 : 2;
+
+ ssize = 0;
+
+ if (!fr->bitrate_index)
+ return (0);
+
+ switch (fr->lay)
+ {
+ case 1:
+/* fr->do_layer = mpg123_do_layer1; */
+/* mpg123_init_layer2(); /\* inits also shared tables with layer1 *\/ */
+ fr->framesize = (long) tabsel_123[fr->lsf][0][fr->bitrate_index] * 12000;
+ fr->framesize /= mpg123_freqs[fr->sampling_frequency];
+ fr->framesize = ((fr->framesize + fr->padding) << 2) - 4;
+ break;
+ case 2:
+/* fr->do_layer = mpg123_do_layer2; */
+/* mpg123_init_layer2(); /\* inits also shared tables with layer1 *\/ */
+ fr->framesize = (long) tabsel_123[fr->lsf][1][fr->bitrate_index] * 144000;
+ fr->framesize /= mpg123_freqs[fr->sampling_frequency];
+ fr->framesize += fr->padding - 4;
+ break;
+ case 3:
+/* fr->do_layer = mpg123_do_layer3; */
+ if (fr->lsf)
+ ssize = (fr->stereo == 1) ? 9 : 17;
+ else
+ ssize = (fr->stereo == 1) ? 17 : 32;
+ if (fr->error_protection)
+ ssize += 2;
+ fr->framesize = (long) tabsel_123[fr->lsf][2][fr->bitrate_index] * 144000;
+ fr->framesize /= mpg123_freqs[fr->sampling_frequency] << (fr->lsf);
+ fr->framesize = fr->framesize + fr->padding - 4;
+ break;
+ default:
+ return (0);
+ }
+ if(fr->framesize > MAXFRAMESIZE)
+ return 0;
+ return 1;
+}
+
+#define GET_INT32BE(b) \
+(i = (b[0] << 24) | (b[1] << 16) | b[2] << 8 | b[3], b += 4, i)
+
+static int mpg123_get_xing_header(xing_header_t * xing, unsigned char *buf)
+{
+ int i, head_flags;
+ int id, mode;
+
+ memset(xing, 0, sizeof(xing_header_t));
+
+ /* get selected MPEG header data */
+ id = (buf[1] >> 3) & 1;
+ mode = (buf[3] >> 6) & 3;
+ buf += 4;
+
+ /* Skip the sub band data */
+ if (id)
+ {
+ /* mpeg1 */
+ if (mode != 3)
+ buf += 32;
+ else
+ buf += 17;
+ }
+ else
+ {
+ /* mpeg2 */
+ if (mode != 3)
+ buf += 17;
+ else
+ buf += 9;
+ }
+
+ if (strncmp(buf, "Xing", 4))
+ return 0;
+ buf += 4;
+
+ head_flags = GET_INT32BE(buf);
+
+ if (head_flags & FRAMES_FLAG)
+ xing->frames = GET_INT32BE(buf);
+ if (xing->frames < 1)
+ xing->frames = 1;
+ if (head_flags & BYTES_FLAG)
+ xing->bytes = GET_INT32BE(buf);
+
+ if (head_flags & TOC_FLAG)
+ {
+ for (i = 0; i < 100; i++)
+ xing->toc[i] = buf[i];
+ buf += 100;
+ }
+
+#ifdef XING_DEBUG
+ for (i = 0; i < 100; i++)
+ {
+ if ((i % 10) == 0)
+ fprintf(stderr, "\n");
+ fprintf(stderr, " %3d", xing->toc[i]);
+ }
+#endif
+
+ return 1;
+}
+
+static double mpg123_compute_tpf(struct frame *fr)
+{
+ const int bs[4] = {0, 384, 1152, 1152};
+ double tpf;
+
+ tpf = bs[fr->lay];
+ tpf /= mpg123_freqs[fr->sampling_frequency] << (fr->lsf);
+ return tpf;
+}
+
+static double mpg123_compute_bpf(struct frame *fr)
+{
+ double bpf;
+
+ switch (fr->lay)
+ {
+ case 1:
+ bpf = tabsel_123[fr->lsf][0][fr->bitrate_index];
+ bpf *= 12000.0 * 4.0;
+ bpf /= mpg123_freqs[fr->sampling_frequency] << (fr->lsf);
+ break;
+ case 2:
+ case 3:
+ bpf = tabsel_123[fr->lsf][fr->lay - 1][fr->bitrate_index];
+ bpf *= 144000;
+ bpf /= mpg123_freqs[fr->sampling_frequency] << (fr->lsf);
+ break;
+ default:
+ bpf = 1.0;
+ }
+
+ return bpf;
+}
+
+
+unsigned int mpg123_getbits(int number_of_bits)
+{
+ unsigned long rval;
+
+#ifdef DEBUG_GETBITS
+ fprintf(stderr, "g%d", number_of_bits);
+#endif
+
+ if(!number_of_bits)
+ return 0;
+
+#if 0
+ check_buffer_range(number_of_bits + bsi.bitindex);
+#endif
+
+ {
+ rval = bsi.wordpointer[0];
+ rval <<= 8;
+ rval |= bsi.wordpointer[1];
+ rval <<= 8;
+ rval |= bsi.wordpointer[2];
+
+ rval <<= bsi.bitindex;
+ rval &= 0xffffff;
+
+ bsi.bitindex += number_of_bits;
+
+ rval >>= (24-number_of_bits);
+
+ bsi.wordpointer += (bsi.bitindex >> 3);
+ bsi.bitindex &= 7;
+ }
+
+#ifdef DEBUG_GETBITS
+ fprintf(stderr,":%x ",rval);
+#endif
+
+ return rval;
+}
+
+
+void I_step_one(unsigned int balloc[], unsigned int scale_index[2][SBLIMIT], struct frame *fr)
+{
+ unsigned int *ba = balloc;
+ unsigned int *sca = (unsigned int *) scale_index;
+
+ if (fr->stereo)
+ {
+ int i;
+ int jsbound = fr->jsbound;
+
+ for (i = 0; i < jsbound; i++)
+ {
+ *ba++ = mpg123_getbits(4);
+ *ba++ = mpg123_getbits(4);
+ }
+ for (i = jsbound; i < SBLIMIT; i++)
+ *ba++ = mpg123_getbits(4);
+
+ ba = balloc;
+
+ for (i = 0; i < jsbound; i++)
+ {
+ if ((*ba++))
+ *sca++ = mpg123_getbits(6);
+ if ((*ba++))
+ *sca++ = mpg123_getbits(6);
+ }
+ for (i = jsbound; i < SBLIMIT; i++)
+ if ((*ba++))
+ {
+ *sca++ = mpg123_getbits(6);
+ *sca++ = mpg123_getbits(6);
+ }
+ }
+ else
+ {
+ int i;
+
+ for (i = 0; i < SBLIMIT; i++)
+ *ba++ = mpg123_getbits(4);
+ ba = balloc;
+ for (i = 0; i < SBLIMIT; i++)
+ if ((*ba++))
+ *sca++ = mpg123_getbits(6);
+ }
+}
+
+void I_step_two(real fraction[2][SBLIMIT], unsigned int balloc[2 * SBLIMIT],
+ unsigned int scale_index[2][SBLIMIT], struct frame *fr)
+{
+ int i, n;
+ int smpb[2 * SBLIMIT]; /* values: 0-65535 */
+ int *sample;
+ register unsigned int *ba;
+ register unsigned int *sca = (unsigned int *) scale_index;
+
+ if (fr->stereo)
+ {
+ int jsbound = fr->jsbound;
+ register real *f0 = fraction[0];
+ register real *f1 = fraction[1];
+
+ ba = balloc;
+ for (sample = smpb, i = 0; i < jsbound; i++)
+ {
+ if ((n = *ba++))
+ *sample++ = mpg123_getbits(n + 1);
+ if ((n = *ba++))
+ *sample++ = mpg123_getbits(n + 1);
+ }
+ for (i = jsbound; i < SBLIMIT; i++)
+ if ((n = *ba++))
+ *sample++ = mpg123_getbits(n + 1);
+
+ ba = balloc;
+ for (sample = smpb, i = 0; i < jsbound; i++)
+ {
+ if ((n = *ba++))
+ *f0++ = (real) (((-1) << n) + (*sample++) + 1) * mpg123_muls[n + 1][*sca++];
+ else
+ *f0++ = 0.0;
+ if ((n = *ba++))
+ *f1++ = (real) (((-1) << n) + (*sample++) + 1) * mpg123_muls[n + 1][*sca++];
+ else
+ *f1++ = 0.0;
+ }
+ for (i = jsbound; i < SBLIMIT; i++)
+ {
+ if ((n = *ba++))
+ {
+ real samp = (((-1) << n) + (*sample++) + 1);
+
+ *f0++ = samp * mpg123_muls[n + 1][*sca++];
+ *f1++ = samp * mpg123_muls[n + 1][*sca++];
+ }
+ else
+ *f0++ = *f1++ = 0.0;
+ }
+ for (i = fr->down_sample_sblimit; i < 32; i++)
+ fraction[0][i] = fraction[1][i] = 0.0;
+ }
+ else
+ {
+ register real *f0 = fraction[0];
+
+ ba = balloc;
+ for (sample = smpb, i = 0; i < SBLIMIT; i++)
+ if ((n = *ba++))
+ *sample++ = mpg123_getbits(n + 1);
+ ba = balloc;
+ for (sample = smpb, i = 0; i < SBLIMIT; i++)
+ {
+ if ((n = *ba++))
+ *f0++ = (real) (((-1) << n) + (*sample++) + 1) * mpg123_muls[n + 1][*sca++];
+ else
+ *f0++ = 0.0;
+ }
+ for (i = fr->down_sample_sblimit; i < 32; i++)
+ fraction[0][i] = 0.0;
+ }
+}
+
+static guint get_track_time_file(FILE * file)
+{
+ guint32 head;
+ guchar tmp[4], *buf;
+ struct frame frm;
+ xing_header_t xing_header;
+ double tpf, bpf;
+ guint32 len;
+
+ if (!file)
+ return -1;
+
+ fseek(file, 0, SEEK_SET);
+ if (fread(tmp, 1, 4, file) != 4)
+ return 0;
+ head = convert_to_header(tmp);
+ while (!mpg123_head_check(head))
+ {
+ head <<= 8;
+ if (fread(tmp, 1, 1, file) != 1)
+ return 0;
+ head |= tmp[0];
+ }
+ if (mpg123_decode_header(&frm, head))
+ {
+ buf = g_malloc(frm.framesize + 4);
+ fseek(file, -4, SEEK_CUR);
+ fread(buf, 1, frm.framesize + 4, file);
+ tpf = mpg123_compute_tpf(&frm);
+ if (mpg123_get_xing_header(&xing_header, buf))
+ {
+ g_free(buf);
+ return ((guint) (tpf * xing_header.frames * 1000));
+ }
+ g_free(buf);
+ bpf = mpg123_compute_bpf(&frm);
+ fseek(file, 0, SEEK_END);
+ len = ftell(file);
+ fseek(file, -128, SEEK_END);
+ fread(tmp, 1, 3, file);
+ if (!strncmp(tmp, "TAG", 3))
+ len -= 128;
+ return ((guint) ((guint)(len / bpf) * tpf * 1000));
+ }
+ return 0;
+}
+
+static guint get_track_time (gchar *path)
+{
+ guint result = 0;
+
+ if (path)
+ {
+ FILE *file = fopen (path, "r");
+ result = get_track_time_file (file);
+ if (file) fclose (file);
+ }
+ return result;
+}
+
+
+/* libid3tag stuff */
+
+#include <id3tag.h>
+#include "prefs.h"
+
+#ifndef ID3_FRAME_GROUP
+#define ID3_FRAME_GROUP "TPE2"
+#endif
+
+
+
+static const gchar* id3_get_binary (struct id3_tag *tag,
+ char *frame_name,
+ id3_length_t *len,
+ int index)
+{
+ const id3_byte_t *binary = NULL;
+ struct id3_frame *frame;
+ union id3_field *field;
+
+ g_return_val_if_fail (len, NULL);
+
+ *len = 0;
+
+ frame = id3_tag_findframe (tag, frame_name, index);
+#if LOCALDEBUG
+ printf ("frame: %p\n", frame);
+#endif
+
+ if (!frame) return NULL;
+
+#if LOCALDEBUG
+ printf (" nfields: %d\n", frame->nfields);
+ if (strncmp (frame_name, "APIC", 4) == 0)
+ {
+ field = id3_frame_field (frame, 2);
+ printf (" picture type: %ld\n", field->number.value);
+ }
+#endif
+
+
+#if 0
+/*-----------------*/
+/* just to show that this field (before last) contains the d8 ff e0 ff
+ part of the start of a jpeg file when the coverart war embedded by iTunes */
+
+ const id3_ucs4_t *string = NULL;
+ gchar *raw = NULL;
+
+ /* The last field contains the data */
+ field = id3_frame_field (frame, frame->nfields-2);
+
+#if LOCALDEBUG
+ printf (" field: %p\n", field);
+#endif
+
+ if (!field) return NULL;
+
+#if LOCALDEBUG
+ printf (" type: %d\n", field->type);
+#endif
+
+ switch (field->type)
+ {
+ case ID3_FIELD_TYPE_STRING:
+ string = id3_field_getstring (field);
+ break;
+ default:
+ break;
+ }
+
+ /* ISO_8859_1 is just a "marker" -- most people just drop
+ whatever coding system they are using into it, so we use
+ charset_to_utf8() to convert to utf8 */
+
+ if (string)
+ {
+ raw = id3_ucs4_latin1duplicate (string);
+ }
+
+
+#if LOCALDEBUG
+ {
+ FILE *file;
+ printf (" string len: %d\n", raw?strlen(raw):0);
+ file = fopen ("/tmp/folder1.jpg", "w");
+ fwrite (raw, 1, raw?strlen(raw):0, file);
+ fclose (file);
+ }
+#endif
+ g_free (raw);
+
+/*-----------------*/
+#endif
+
+ /* The last field contains the data */
+ field = id3_frame_field (frame, frame->nfields-1);
+
+#if LOCALDEBUG
+ printf (" field: %p\n", field);
+#endif
+
+ if (!field) return NULL;
+
+#if LOCALDEBUG
+ printf (" type: %d\n", field->type);
+#endif
+
+ switch (field->type)
+ {
+ case ID3_FIELD_TYPE_BINARYDATA:
+ binary = id3_field_getbinarydata(field, len);
+ break;
+ default:
+ break;
+ }
+
+#if LOCALDEBUG
+ {
+ FILE *file;
+ printf (" binary len: %ld\n", *len);
+ file = fopen ("/tmp/folder2.jpg", "w");
+ fwrite (binary, 1, *len, file);
+ fclose (file);
+ }
+#endif
+
+
+
+ return binary;
+}
+
+
+
+static gchar* id3_get_string (struct id3_tag *tag, char *frame_name)
+{
+ const id3_ucs4_t *string = NULL;
+ const id3_byte_t *binary = NULL;
+ id3_length_t len = 0;
+ struct id3_frame *frame;
+ union id3_field *field;
+ gchar *utf8 = NULL;
+ enum id3_field_textencoding encoding = ID3_FIELD_TEXTENCODING_ISO_8859_1;
+
+ frame = id3_tag_findframe (tag, frame_name, 0);
+#if LOCALDEGUB
+ printf ("frame: %p\n", frame);
+#endif
+
+ if (!frame) return NULL;
+
+ /* Find the encoding used for the field */
+ field = id3_frame_field (frame, 0);
+#if LOCALDEBUG
+ printf ("field: %p\n", field);
+ printf ("type: %d\n", id3_field_type (field));
+#endif
+
+ if (field && (id3_field_type (field) == ID3_FIELD_TYPE_TEXTENCODING))
+ {
+ encoding = field->number.value;
+#if LOCALDEBUG
+ printf ("encoding: %d\n", encoding);
+#endif
+ }
+
+ /* The last field contains the data */
+ field = id3_frame_field (frame, frame->nfields-1);
+
+#if LOCALDEBUG
+ printf ("field: %p\n", field);
+#endif
+
+ if (!field) return NULL;
+
+#if LOCALDEBUG
+ printf ("type: %d\n", field->type);
+#endif
+
+
+ switch (field->type)
+ {
+ case ID3_FIELD_TYPE_STRINGLIST:
+ string = id3_field_getstrings (field, 0);
+ break;
+ case ID3_FIELD_TYPE_STRINGFULL:
+ string = id3_field_getfullstring (field);
+ break;
+ case ID3_FIELD_TYPE_BINARYDATA:
+ binary = id3_field_getbinarydata(field, &len);
+#if LOCALDEBUG
+ printf ("len: %ld\nbinary: %s\n", len, binary+1);
+#endif
+ if (len > 0)
+ return charset_to_utf8 (binary+1);
+ break;
+ default:
+ break;
+ }
+
+/* printf ("string: %p\n", string); */
+
+ if (!string) return NULL;
+
+ if (strcmp (frame_name, ID3_FRAME_GENRE) == 0)
+ string = id3_genre_name (string);
+
+ if (encoding == ID3_FIELD_TEXTENCODING_ISO_8859_1)
+ {
+ /* ISO_8859_1 is just a "marker" -- most people just drop
+ whatever coding system they are using into it, so we use
+ charset_to_utf8() to convert to utf8 */
+ id3_latin1_t *raw = id3_ucs4_latin1duplicate (string);
+ utf8 = charset_to_utf8 (raw);
+ g_free (raw);
+ }
+ else
+ {
+ /* Standard unicode is being used -- we won't have to worry
+ about charsets then. */
+ utf8 = id3_ucs4_utf8duplicate (string);
+ }
+ return utf8;
+}
+
+static void id3_set_string (struct id3_tag *tag,
+ const char *frame_name,
+ const char *data,
+ enum id3_field_textencoding encoding)
+{
+ int res;
+ struct id3_frame *frame;
+ union id3_field *field;
+ id3_ucs4_t *ucs4;
+
+ /* clear the frame, because of bug in libid3tag see
+ http://www.mars.org/mailman/public/mad-dev/2004-October/001113.html
+ */
+ while ((frame = id3_tag_findframe (tag, frame_name, 0)))
+ {
+ id3_tag_detachframe (tag, frame);
+ id3_frame_delete (frame);
+ }
+
+ if ((data == NULL) || (strlen(data) == 0))
+ return;
+
+ frame = id3_frame_new (frame_name);
+ id3_tag_attachframe (tag, frame);
+
+ /* Use the specified text encoding */
+ field = id3_frame_field (frame, 0);
+ id3_field_settextencoding(field, encoding);
+
+ if (strcmp (frame_name, ID3_FRAME_COMMENT) == 0)
+ {
+ field = id3_frame_field (frame, 3);
+ field->type = ID3_FIELD_TYPE_STRINGFULL;
+ }
+ else
+ {
+ field = id3_frame_field (frame, 1);
+ field->type = ID3_FIELD_TYPE_STRINGLIST;
+ }
+
+
+ /* maybe could be optimized see
+ http://www.mars.org/mailman/public/mad-dev/2002-October/000739.html
+ */
+ if (strcmp (frame_name, ID3_FRAME_GENRE) == 0)
+ {
+ id3_ucs4_t *tmp_ucs4 = id3_utf8_ucs4duplicate ((id3_utf8_t *)data);
+ int index = id3_genre_number (tmp_ucs4);
+ if (index != -1)
+ {
+ /* valid genre -- simply store the genre number */
+ gchar *tmp = g_strdup_printf("%d", index);
+ ucs4 = id3_latin1_ucs4duplicate (tmp);
+ g_free (tmp);
+ }
+ else
+ {
+ /* oups -- not a valid genre -- save the entire genre string */
+ if (encoding == ID3_FIELD_TEXTENCODING_ISO_8859_1)
+ {
+ /* we read 'ISO_8859_1' to stand for 'any locale
+ charset' -- most programs seem to work that way */
+ id3_latin1_t *raw = charset_from_utf8 (data);
+ ucs4 = id3_latin1_ucs4duplicate (raw);
+ g_free (raw);
+ }
+ else
+ {
+ /* Yeah! We use unicode encoding and won't have to
+ worry about charsets */
+ ucs4 = tmp_ucs4;
+ tmp_ucs4 = NULL;
+ }
+ }
+ g_free (tmp_ucs4);
+ }
+ else
+ {
+ if (encoding == ID3_FIELD_TEXTENCODING_ISO_8859_1)
+ {
+ /* we read 'ISO_8859_1' to stand for 'any locale charset'
+ -- most programs seem to work that way */
+ id3_latin1_t *raw = charset_from_utf8 (data);
+ ucs4 = id3_latin1_ucs4duplicate (raw);
+ g_free (raw);
+ }
+ else
+ {
+ /* Yeah! We use unicode encoding and won't have to
+ worry about charsets */
+ ucs4 = id3_utf8_ucs4duplicate ((id3_utf8_t *)data);
+ }
+ }
+
+ if (strcmp (frame_name, ID3_FRAME_COMMENT) == 0)
+ res = id3_field_setfullstring (field, ucs4);
+ else
+ res = id3_field_setstrings (field, 1, &ucs4);
+
+ g_free (ucs4);
+
+ if (res != 0)
+ g_print(_("Error setting ID3 field: %s\n"), frame_name);
+}
+
+
+/***
+ * Reads id3v1.x / id3v2 apic data
+ * @returns: TRUE on success, else FALSE.
+ */
+static gboolean id3_apic_read (gchar *filename,
+ guchar **image_data, gsize *image_data_len)
+{
+ struct id3_file *id3file;
+ struct id3_tag *id3tag;
+
+ g_return_val_if_fail (filename, FALSE);
+ g_return_val_if_fail (image_data, FALSE);
+ g_return_val_if_fail (image_data_len, FALSE);
+
+ *image_data = NULL;
+ *image_data_len = 0;
+
+ if (!(id3file = id3_file_open (filename, ID3_FILE_MODE_READONLY)))
+ {
+ gchar *fbuf = charset_to_utf8 (filename);
+ g_print(_("ERROR while opening file: '%s' (%s).\n"),
+ fbuf, g_strerror(errno));
+ g_free (fbuf);
+ return FALSE;
+ }
+
+ if ((id3tag = id3_file_tag(id3file)))
+ {
+ id3_length_t len;
+ const guchar *coverart = NULL;
+ int i;
+ struct id3_frame *frame;
+
+ /* Loop through APIC tags and set coverart. The picture type should be
+ * 3 -- Cover (front), but iTunes has been known to use 0 -- Other. */
+ for (i = 0; (frame = id3_tag_findframe(id3tag, "APIC", i)) != NULL; i++)
+ {
+ union id3_field *field = id3_frame_field (frame, 2);
+ int pictype = field->number.value;
+/* printf ("%s: found apic type %d\n", filename, pictype);*/
+
+ /* We'll prefer type 3 (cover) over type 0 (other) */
+ if (pictype == 3)
+ {
+ coverart = id3_get_binary (id3tag, "APIC", &len, i);
+ break;
+ }
+ if ((pictype == 0) && !coverart)
+ {
+ coverart = id3_get_binary (id3tag, "APIC", &len, i);
+ }
+ }
+
+ if (coverart)
+ { /* I guess iTunes is doing something wrong -- the
+ * beginning of the coverart data ends up in a different
+ field... We'll just add the missing data manually. */
+ const guchar itunes_broken_jfif_marker[] =
+ { 0x10, 'J', 'F', 'I', 'F'};
+ if (len >= 5)
+ {
+ if (strncmp (itunes_broken_jfif_marker, coverart, 5) == 0)
+ {
+ const guchar itunes_missing_header[] =
+ { 0xff, 0xd8, 0xff, 0xe0, 0x00 };
+ *image_data = g_malloc (len+5);
+ memcpy (*image_data, itunes_missing_header, 5);
+ memcpy ((*image_data)+5, coverart, len);
+ *image_data_len = len+5;
+ }
+ }
+ if (!*image_data)
+ {
+ *image_data = g_malloc (len);
+ memcpy (*image_data, coverart, len);
+ *image_data_len = len;
+ }
+#if LOCALDEBUG
+ if (*image_data)
+ {
+ FILE *file;
+ file = fopen ("/tmp/folder.jpg", "w");
+ fwrite (*image_data, 1, *image_data_len, file);
+ fclose (file);
+ }
+#endif
+ }
+ }
+ id3_file_close (id3file);
+ return TRUE;
+}
+
+/***
+ * Reads id3v1.x / id3v2 tag and load data into the Id3tag structure.
+ * If a tag entry exists (ex: title), we allocate memory, else value
+ * stays to NULL
+ * @returns: TRUE on success, else FALSE.
+ */
+gboolean id3_tag_read (gchar *filename, File_Tag *tag)
+{
+ struct id3_file *id3file;
+ struct id3_tag *id3tag;
+ gchar* string;
+ gchar* string2;
+
+ g_return_val_if_fail (filename, FALSE);
+ g_return_val_if_fail (tag, FALSE);
+
+ memset (tag, 0, sizeof (File_Tag));
+
+ if (!(id3file = id3_file_open (filename, ID3_FILE_MODE_READONLY)))
+ {
+ gchar *fbuf = charset_to_utf8 (filename);
+ g_print(_("ERROR while opening file: '%s' (%s).\n"),
+ fbuf, g_strerror(errno));
+ g_free (fbuf);
+ return FALSE;
+ }
+
+ if ((id3tag = id3_file_tag(id3file)))
+ {
+ tag->title = id3_get_string (id3tag, ID3_FRAME_TITLE);
+ tag->artist = id3_get_string (id3tag, ID3_FRAME_GROUP);
+ if (!tag->artist || !*tag->artist)
+ {
+ g_free (tag->artist);
+ tag->artist = id3_get_string (id3tag, ID3_FRAME_ARTIST);
+ }
+ tag->album = id3_get_string (id3tag, ID3_FRAME_ALBUM);
+ tag->year = id3_get_string (id3tag, ID3_FRAME_YEAR);
+ tag->composer = id3_get_string (id3tag, "TCOM");
+ tag->comment = id3_get_string (id3tag, ID3_FRAME_COMMENT);
+ tag->genre = id3_get_string (id3tag, ID3_FRAME_GENRE);
+ tag->compilation = id3_get_string (id3tag, "TCMP");
+ tag->subtitle = id3_get_string (id3tag, "TIT3");
+ tag->lyrics = id3_get_string (id3tag, "USLT");
+ tag->podcasturl = id3_get_string (id3tag, "YTID");
+ tag->podcastrss = id3_get_string (id3tag, "YWFD");
+ tag->description = id3_get_string (id3tag, "YTDS");
+ tag->time_released = id3_get_string (id3tag, "YTDR");
+ tag->BPM = id3_get_string (id3tag, "TBPM");
+ tag->sort_artist = id3_get_string (id3tag, "TSOP");
+ tag->sort_album = id3_get_string (id3tag, "TSOA");
+ tag->sort_title = id3_get_string (id3tag, "TSOT");
+ tag->sort_albumartist = id3_get_string (id3tag, "TSO2");
+ tag->sort_composer = id3_get_string (id3tag, "TSOC");
+
+ string = id3_get_string (id3tag, "TLEN");
+ if (string)
+ {
+ tag->songlen = (guint32) strtoul (string, 0, 10);
+ g_free (string);
+ }
+
+ string = id3_get_string (id3tag, ID3_FRAME_TRACK);
+ if (string)
+ {
+ string2 = strchr(string,'/');
+ if (string2)
+ {
+ tag->track_total = g_strdup_printf ("%.2d", atoi (string2+1));
+ *string2 = '\0';
+ }
+ tag->trackstring = g_strdup_printf ("%.2d", atoi (string));
+ g_free(string);
+ }
+
+ /* CD/disc number tag handling */
+ string = id3_get_string (id3tag, "TPOS");
+ if (string)
+ {
+ string2 = strchr(string,'/');
+ if (string2)
+ {
+ tag->cdno_total = g_strdup_printf ("%.2d", atoi (string2+1));
+ *string2 = '\0';
+ }
+ tag->cdnostring = g_strdup_printf ("%.2d", atoi (string));
+ g_free(string);
+ }
+ }
+
+ id3_file_close (id3file);
+ return TRUE;
+}
+
+
+
+static enum id3_field_textencoding get_encoding_of (struct id3_tag *tag, const char *frame_name)
+{
+ struct id3_frame *frame;
+ enum id3_field_textencoding encoding = -1;
+
+ frame = id3_tag_findframe (tag, frame_name, 0);
+ if (frame)
+ {
+ union id3_field *field = id3_frame_field (frame, 0);
+ if (field && (id3_field_type (field) == ID3_FIELD_TYPE_TEXTENCODING))
+ encoding = field->number.value;
+ }
+ return encoding;
+}
+
+/* Find out which encoding is being used. If in doubt, return
+ * latin1. This code assumes that the same encoding is used in all
+ * fields. */
+static enum id3_field_textencoding get_encoding (struct id3_tag *tag)
+{
+ enum id3_field_textencoding enc;
+
+ enc = get_encoding_of (tag, ID3_FRAME_TITLE);
+ if (enc != -1) return enc;
+ enc = get_encoding_of (tag, ID3_FRAME_ARTIST);
+ if (enc != -1) return enc;
+ enc = get_encoding_of (tag, ID3_FRAME_ALBUM);
+ if (enc != -1) return enc;
+ enc = get_encoding_of (tag, "TCOM");
+ if (enc != -1) return enc;
+ enc = get_encoding_of (tag, ID3_FRAME_COMMENT);
+ if (enc != -1) return enc;
+ enc = get_encoding_of (tag, ID3_FRAME_YEAR);
+ if (enc != -1) return enc;
+ return ID3_FIELD_TEXTENCODING_ISO_8859_1;
+}
+
+
+/* I'm not really sure about this: The original TAG identifier was
+ "TID", but no matter what I do I end up writing "YTID" */
+void set_uncommon_tag (struct id3_tag *id3tag,
+ const gchar *id,
+ const gchar *text,
+ enum id3_field_textencoding encoding)
+{
+#if 0
+ struct id3_frame *frame;
+
+ frame = id3_tag_findframe (id3tag, id, 0);
+ union id3_field *field;
+ frame->flags = 0;
+ field = id3_frame_field (frame, 0);
+ if (field)
+ {
+ string1 = g_strdup_printf ("%c%s", '\0',
+ track->podcasturl);
+ id3_field_setbinarydata (field, string1,
+ strlen(track->podcasturl)+1);
+ g_free (string1);
+ }
+
+#endif
+}
+
+
+
+/**
+ * Write the ID3 tags to the file.
+ * @returns: TRUE on success, else FALSE.
+ */
+gboolean mp3_write_file_info (gchar *filename, Track *track)
+{
+ struct id3_tag* id3tag;
+ struct id3_file* id3file;
+ gint error = 0;
+
+ id3file = id3_file_open (filename, ID3_FILE_MODE_READWRITE);
+ if (!id3file)
+ {
+ gchar *fbuf = charset_to_utf8 (filename);
+ g_print(_("ERROR while opening file: '%s' (%s).\n"),
+ fbuf, g_strerror(errno));
+ g_free (fbuf);
+ return FALSE;
+ }
+
+ if ((id3tag = id3_file_tag(id3file)))
+ {
+ char *string1;
+
+ enum id3_field_textencoding encoding;
+
+ /* use the same coding as before... */
+ encoding = get_encoding (id3tag);
+ /* ...unless it's ISO_8859_1 and prefs say we should use
+ unicode (i.e. ID3v2.4) */
+ if (prefs_get_int("id3_write_id3v24") &&
+ (encoding == ID3_FIELD_TEXTENCODING_ISO_8859_1))
+ encoding = ID3_FIELD_TEXTENCODING_UTF_8;
+
+ /* always render id3v1 to prevent dj studio from crashing */
+ id3_tag_options(id3tag, ID3_TAG_OPTION_ID3V1, ~0);
+
+ /* turn off frame compression and crc information to let
+ itunes read tags see
+ http://www.mars.org/mailman/public/mad-dev/2002-October/000742.html
+ */
+ id3_tag_options(id3tag, ID3_TAG_OPTION_COMPRESSION, 0);
+ id3_tag_options(id3tag, ID3_TAG_OPTION_CRC, 0);
+
+ id3_set_string (id3tag, ID3_FRAME_TITLE, track->title, encoding);
+ id3_set_string (id3tag, ID3_FRAME_ARTIST, track->artist, encoding);
+ id3_set_string (id3tag, ID3_FRAME_ALBUM, track->album, encoding);
+ id3_set_string (id3tag, ID3_FRAME_GENRE, track->genre, encoding);
+ id3_set_string (id3tag, ID3_FRAME_COMMENT, track->comment, encoding);
+ id3_set_string (id3tag, "TIT3", track->subtitle, encoding);
+ id3_set_string (id3tag, "TSOP", track->sort_artist, encoding);
+ id3_set_string (id3tag, "TSOA", track->sort_album, encoding);
+ id3_set_string (id3tag, "TSOT", track->sort_title, encoding);
+ id3_set_string (id3tag, "TSO2", track->sort_albumartist, encoding);
+ id3_set_string (id3tag, "TSOC", track->sort_composer, encoding);
+
+ set_uncommon_tag (id3tag, "YTID", track->podcasturl, encoding);
+ set_uncommon_tag (id3tag, "YTDS", track->description, encoding);
+ set_uncommon_tag (id3tag, "YWFD", track->podcastrss, encoding);
+
+ id3_set_string (id3tag, "TCOM", track->composer, encoding);
+
+ string1 = g_strdup_printf("%d", track->year);
+ id3_set_string(id3tag, ID3_FRAME_YEAR, string1, encoding);
+ g_free(string1);
+
+ string1 = g_strdup_printf("%d", track->BPM);
+ id3_set_string(id3tag, "TBPM", string1, encoding);
+ g_free(string1);
+
+ if (track->tracks)
+ string1 = g_strdup_printf ("%d/%d",
+ track->track_nr, track->tracks);
+ else
+ string1 = g_strdup_printf ("%d", track->track_nr);
+ id3_set_string (id3tag, ID3_FRAME_TRACK, string1, encoding);
+ g_free(string1);
+
+ if (track->cds)
+ string1 = g_strdup_printf ("%d/%d",
+ track->cd_nr, track->cds);
+ else
+ string1 = g_strdup_printf ("%d", track->cd_nr);
+ id3_set_string (id3tag, "TPOS", string1, encoding);
+ g_free(string1);
+
+ string1 = g_strdup_printf ("%d", track->compilation);
+ id3_set_string (id3tag, "TCMP", string1, encoding);
+ g_free(string1);
+ }
+
+ if (id3_file_update(id3file) != 0)
+ {
+ gchar *fbuf = charset_to_utf8 (filename);
+ g_print(_("ERROR while writing tag to file: '%s' (%s).\n"),
+ fbuf, g_strerror(errno));
+ g_free (fbuf);
+ return FALSE;
+ }
+
+ id3_file_close (id3file);
+
+ if (error) return FALSE;
+ else return TRUE;
+}
+
+
+/*
+ * Code to read the ReplayGain Values stored by LAME in its own tag.
+ *
+ * Most of the relevant information has been extracted from them LAME sources
+ * (http://lame.sourceforge.net/).
+ * The "Mp3 info Tag rev 1 specifications - draft 0"
+ * (http://gabriel.mp3-tech.org/mp3infotag.html) by Gabriel Bouvigne describes
+ * the actual Tag (except for small changes).
+ * Details on the actual ReplayGain fields have been obtained from
+ * http://www.replaygain.org .
+ *
+ * Apart from that, some information has been derived from phwip's LameTag
+ * (http://www.silisoftware.com/applets/?scriptname=LameTag)
+ *
+ *
+ * Code to read the ReplayGain Values stored in an Ape tag.
+ *
+ * Info on Lyrics3 V2.00 can be found at:
+ * http://www.id3.org/lyrics3200.html
+ * On the actual Ape Tag V2.0:
+ * http://www.personal.uni-jena.de/~pfk/mpp/sv8/apetag.html
+ *
+ * Copyright (C) 2004 Jens Taprogge <jens.taprogge at post.rwth-aachen.de>
+ *
+ * Provided under GPL according to Jens Taprogge. (JCS -- 12 March 2004)
+ */
+
+#define TAG_FOOTER 0x10
+#define LAME_OFFSET 0x74
+#define SIDEINFO_MPEG1_MONO 17
+#define SIDEINFO_MPEG1_MULTI 32
+#define SIDEINFO_MPEG2_MONO 9
+#define SIDEINFO_MPEG2_MULTI 17
+#define ID3V1_SIZE 0x80
+#define APE_FOOTER_SIZE 0x20
+#define LYRICS_FOOTER_SIZE 0x0f
+
+
+static gint lame_vcmp(gchar a[5], gchar b[5]) {
+ int r;
+
+ r = strncmp(a, b, 4);
+ if (r) return r;
+
+ if (a[4] == b[4]) return 0;
+
+ /* check for '.': indicates subminor version */
+ if (a[4] == '.') return 1;
+ if (b[4] == '.') return -1;
+
+ /* check for alpha or beta versions */
+ if (a[4] == ' ') return 1;
+ if (b[4] == ' ') return -1;
+
+ /* check for alpha, beta etc. indicated by a, b... */
+ return strncmp(&a[4], &b[4], 1);
+}
+
+
+/* buf[] must be declared unsigned -- otherwise the casts, shifts and
+ additions below produce funny results */
+static void read_lame_replaygain(unsigned char buf[],
+ GainData *gd, int gain_adjust) {
+ char oc, nc;
+ gint gain;
+
+ g_return_if_fail (gd);
+
+ /* buf[0] and buf[1] are a bit field:
+ 3 bits: name (mask: 0xe0 = 11100000)
+ 3 bits: originator (mask: 0x1c = 00011100)
+ 1 bit: negative if set (mask: 0x02 = 00000010)
+ 9 bits: value
+ */
+
+ /* check originator */
+ oc = (buf[0] & 0x1c) >> 2;
+ if ((oc <= 0) || (oc > 3)) return;
+
+ /* check name code */
+ nc = buf[0] & 0xe0;
+ if (!((nc == 0x20) || (nc == 0x40))) return;
+
+ gain = ((((guint)buf[0]) & 0x1) << 8) + buf[1];
+
+ /* This would be a value of -0.
+ * That value however is illegal by current standards and reserved for
+ * future use. */
+ if ((!gain) && (buf[0] & 0x02)) return;
+
+ if (buf[0] & 2) gain = -gain;
+
+ gain += gain_adjust;
+
+ switch (nc) {
+ case 0x20:
+ if (gd->radio_gain_set) return;
+ gd->radio_gain = (gdouble)gain / 10;
+ gd->radio_gain_set = TRUE;
+/* printf("radio_gain (lame): %i\n", gd->radio_gain); */
+ break;
+ case 0x40:
+ if (gd->audiophile_gain_set) return;
+ gd->audiophile_gain = (gdouble)gain / 10;
+ gd->audiophile_gain_set = TRUE;
+/* printf("audiophile_gain (lame): %i\n",
+ gd->audiophile_gain);*/
+ break;
+ }
+}
+
+
+static inline guint32 parse_ape_uint32(char *buf) {
+ return (buf[0] & 0xff) | (buf[1] & 0xff) << 8
+ | (buf[2] & 0xff) << 16 | (buf[3] & 0xff) << 24;
+}
+
+static inline guint32 parse_lame_uint32(char *buf) {
+ return (buf[0] & 0xff) << 24 | (buf[1] & 0xff) << 16
+ | (buf[2] & 0xff) << 8 | (buf[3] & 0xff);
+}
+
+
+/*
+ * mp3_get_track_lame_replaygain - read the specified file and scan for LAME Tag
+ * ReplayGain information.
+ *
+ * @path: localtion of the file
+ * @track: structure holding track information
+ *
+ * FIXME: Are there other encoders writing a LAME Tag using a different magic
+ * string?
+ * TODO: Check CRC.
+ */
+
+gboolean mp3_get_track_lame_replaygain (gchar *path, GainData *gd)
+{
+ struct {
+ /* All members are defined in terms of chars so padding does not
+ * occur. Is there a cleaner way to keep the compiler from
+ * padding? */
+
+ char id[3];
+ char version[2];
+ char flags;
+ char size[4];
+ } id3head;
+
+ FILE *file = NULL;
+ char buf[4], version[5];
+ int gain_adjust = 0;
+ int sideinfo;
+ guint32 ps;
+
+ g_return_val_if_fail (gd, FALSE);
+
+ gd->radio_gain = 0;
+ gd->audiophile_gain = 0;
+ gd->peak_signal = 0;
+ gd->radio_gain_set = FALSE;
+ gd->audiophile_gain_set = FALSE;
+ gd->peak_signal_set = FALSE;
+
+ if (!path)
+ goto rg_fail;
+
+ file = fopen (path, "r");
+
+ if (!file)
+ goto rg_fail;
+
+ /* Skip ID3 header if appropriate */
+ if (fread(&id3head, 1, sizeof(id3head), file) !=
+ sizeof(id3head))
+ goto rg_fail;
+
+ if (!strncmp(id3head.id, "ID3", 3)) {
+ int realsize = 0;
+
+ realsize = (id3head.size[0] & 0x7f) << 21
+ | (id3head.size[1] & 0x7f) << 14
+ | (id3head.size[2] & 0x7f) << 7
+ | (id3head.size[3] & 0x7f);
+
+ if (id3head.flags & TAG_FOOTER) {
+ /* footer is copy of header */
+ realsize += sizeof(id3head);
+ }
+
+ if (fseek(file, realsize-1, SEEK_CUR) ||
+ (!fread(&buf[0], 1, 1, file)))
+ goto rg_fail;
+ } else {
+ /* no ID3 Tag - go back */
+ fseek(file, -sizeof(id3head), SEEK_CUR);
+ }
+
+ /* Search Xing header. The location is dependant on the MPEG Layer and
+ * whether the stream is mono or not. */
+ if (fread(buf, 1, 4, file) != 4) goto rg_fail;
+
+ /* should start with 0xff 0xf? (synch) */
+ if (((buf[0] & 0xff) != 0xff)
+ || ((buf[1] & 0xf0) != 0xf0)) goto rg_fail;
+
+ /* determine the length of the sideinfo */
+ if (buf[1] & 0x08) {
+ sideinfo = ((buf[3] & 0xc0) == 0xc0) ?
+ SIDEINFO_MPEG1_MONO : SIDEINFO_MPEG1_MULTI;
+ } else {
+ sideinfo = ((buf[3] & 0xc0) == 0xc0) ?
+ SIDEINFO_MPEG2_MONO : SIDEINFO_MPEG2_MULTI;
+ }
+
+ if (fseek(file, sideinfo, SEEK_CUR) ||
+ (fread(&buf[0], 1, 4, file) != 4))
+ goto rg_fail;
+
+ /* Is this really a Xing or Info Header?
+ * FIXME: Apparently (according to madplay sources) there is a different
+ * possible location for the Xing header ("due to an unfortunate
+ * historical event"). I do not thing we need to care though since
+ * RaplayGain information is only conatined in recent files. */
+ if (strncmp(buf, "Xing", 4) && strncmp(buf, "Info", 4))
+ goto rg_fail;
+
+ /* Check for LAME Tag */
+ if (fseek(file, LAME_OFFSET, SEEK_CUR) ||
+ (fread(&buf[0], 1, 4, file) != 4))
+ goto rg_fail;
+ if (strncmp(buf, "LAME", 4))
+ goto rg_fail;
+
+ /* Check LAME Version */
+ if (fread(version, 1, 5, file) != 5)
+ goto rg_fail;
+
+ /* Skip really old versions altogether. I am not sure when radio_gain
+ * information was introduced. 3.89 does not seem to supprt it though.
+ * */
+ if (lame_vcmp(version, "3.90") < 0) {
+/* fprintf(stderr, "Old lame version (%c%c%c%c%c). Not used.\n",
+ version[0], version[1], version[2], version[3], version[4]); */
+ goto rg_fail;
+ }
+
+ if (fseek(file, 0x2, SEEK_CUR) || (fread(buf, 1, 4, file) != 4))
+ goto rg_fail;
+
+ /* get the peak signal. */
+ ps = parse_lame_uint32(buf);
+
+ /* Don't know when fixed-point PeakSingleAmplitude
+ * was introduced exactly. 3.94b will be used for now.) */
+ if ((lame_vcmp(version, "3.94b") >= 0)) {
+ if ((!gd->peak_signal_set) && ps) {
+ gd->peak_signal = ps;
+ gd->peak_signal_set = TRUE;
+/* printf("peak_signal (lame): %f\n", (double)
+ gd->peak_signal / 0x800000);*/
+ }
+ } else {
+ float f = *((float *) (void *) (&ps)) * 0x800000;
+ gd->peak_signal = (guint32) f;
+ /* I would like to see an example of that. */
+/* printf("peak_signal (lame floating point): %f. PLEASE report.\n",
+ (double) gd->peak_signal / 0x800000);*/
+ }
+
+ /*
+ * Versions prior to 3.95.1 used a reference volume of 83dB.
+ * (As compared to the currently used 89dB.)
+ */
+ if ((lame_vcmp(version, "3.95.") < 0)) {
+ gain_adjust = 60;
+/* fprintf(stderr, "Old lame version (%c%c%c%c%c). Adjusting gain.\n",
+ version[0], version[1], version[2], version[3], version[4]); */
+ }
+
+ if (fread(&buf[0], 1, 2, file) != 2)
+ goto rg_fail;
+
+ /* radio gain */
+ read_lame_replaygain (buf, gd, gain_adjust);
+
+ if (fread(&buf[0], 1, 2, file) != 2)
+ goto rg_fail;
+
+ /* audiophile gain */
+ read_lame_replaygain (buf, gd, gain_adjust);
+
+ fclose(file);
+ return TRUE;
+
+rg_fail:
+ if (file)
+ fclose(file);
+ return FALSE;
+}
+
+
+/*
+ * mp3_get_track_ape_replaygain - read the specified file and scan for Ape Tag
+ * ReplayGain information.
+ *
+ * @path: localtion of the file
+ * @track: structure holding track information
+ *
+ * The function only modifies the gains if they have not previously been set.
+ */
+
+gboolean mp3_get_track_ape_replaygain(gchar *path, GainData *gd)
+{
+ /* The Ape Tag is located a t the end of the file. Or at least that
+ * seems where it can most likely be found. Either it is at the very end
+ * or before a trailing ID3v1 Tag. Sometimes a Lyrics3 Tag is placed
+ * between the ID3v1 and the Ape Tag.
+ * If you find files that have the Tags located in different
+ * positions please let me know. */
+
+ FILE *file = NULL;
+ char buf[16];
+ char *dbuf = NULL, *ep;
+
+ int offset = 0;
+ int i;
+ int pos = 0, pos2 = 0;
+ guint32 version;
+ guint32 data_length;
+ guint32 entry_length = 0;
+ guint32 entries;
+ double d;
+
+ g_return_val_if_fail (gd, FALSE);
+ g_return_val_if_fail (path, FALSE);
+
+ file = fopen (path, "r");
+
+ if (!file)
+ goto rg_fail;
+
+ /* check for ID3v1 Tag */
+ if (fseek(file, -ID3V1_SIZE, SEEK_END) ||
+ fread(&buf, 1, 3, file) != 3)
+ goto rg_fail;
+ if (!strncmp(buf, "TAG", 3)) offset -= ID3V1_SIZE;
+
+ /* check for Lyrics3 Tag */
+ if (fseek(file, -9 + offset, SEEK_END) ||
+ fread(&buf, 1, 9, file) != 9)
+ goto rg_fail;
+ if (!strncmp(buf, "LYRICS200", 9)) {
+ if (fseek(file, -LYRICS_FOOTER_SIZE + offset, SEEK_END) ||
+ fread(&buf, 1, 9, file) != 9)
+ goto rg_fail;
+ data_length = buf[0] - '0';
+ for (i = 1; i < 6; i++) {
+ data_length *= 10;
+ data_length += buf[i] - '0';
+ }
+ if (fseek(file, -LYRICS_FOOTER_SIZE - data_length + offset,
+ SEEK_END) ||
+ fread(&buf, 1, 11, file) != 11)
+ goto rg_fail;
+ if (!strncmp(buf, "LYRICSBEGIN", 11))
+ offset -= LYRICS_FOOTER_SIZE + data_length;
+ }
+
+ /* check for APE Tag */
+ if (fseek(file, -APE_FOOTER_SIZE + offset, SEEK_END) ||
+ fread(&buf, 1, 8, file) != 8)
+ goto rg_fail;
+ if (strncmp(buf, "APETAGEX", 8)) goto rg_fail;
+
+ /* Check the version of the tag. 1000 and 2000 (v1.0 and 2.0) are the
+ * only ones I know about. Make suer things do not break in the future.
+ * */
+ if (fread(&buf, 1, 4, file) != 4)
+ goto rg_fail;
+ version = parse_ape_uint32(buf);
+ if (version != 1000 && version != 2000)
+ goto rg_fail;
+
+ /* determine data length */
+ if (fread(&buf, 1, 4, file) != 4)
+ goto rg_fail;
+ data_length = parse_ape_uint32(buf) - APE_FOOTER_SIZE;
+
+ /* determine number of entries */
+ if (fread(&buf, 1, 4, file) != 4)
+ goto rg_fail;
+ entries = parse_ape_uint32(buf);
+
+ /* seek to first entry and read the whole buffer*/
+ if (fseek(file, -APE_FOOTER_SIZE + offset - data_length, SEEK_END))
+ goto rg_fail;
+ if (!(dbuf = malloc(data_length)))
+ goto rg_fail;
+ if (fread(dbuf, 1, data_length, file) != data_length)
+ goto rg_fail;
+
+ for (i = 0; i < entries; i++) {
+ if (gd->radio_gain_set && gd->peak_signal_set) break;
+ pos = pos2 + entry_length;
+ if (pos > data_length - 10) break;
+
+ entry_length = parse_ape_uint32(&dbuf[pos]); pos += 4;
+ pos += 4;
+
+ pos2 = pos;
+ while (dbuf[pos2] && pos2 < data_length) pos2++;
+ if (pos2 == data_length) break;
+ pos2++;
+
+ if (entry_length + 1 > sizeof(buf))
+ continue;
+/* printf ("%s:%d:%d\n",&dbuf[pos], pos2, pos); */
+ if (!gd->radio_gain_set && !strcasecmp(&dbuf[pos],
+ "REPLAYGAIN_TRACK_GAIN")) {
+ memcpy(buf, &dbuf[pos2], entry_length);
+ buf[entry_length] = '\0';
+
+ d = g_ascii_strtod(buf, &ep);
+/* printf("%f\n", d); */
+ if ((ep == buf + entry_length - 3)
+ && (!strncasecmp(ep, " dB", 3))) {
+ gd->radio_gain = d;
+ gd->radio_gain_set = TRUE;
+/* printf("radio_gain (ape): %i\n", gd->radio_gain);*/
+ }
+
+ continue;
+ }
+ if (!gd->peak_signal_set && !strcasecmp(&dbuf[pos],
+ "REPLAYGAIN_TRACK_PEAK")) {
+ memcpy(buf, &dbuf[pos2], entry_length);
+ buf[entry_length] = '\0';
+
+ d = g_ascii_strtod(buf, &ep);
+ if (ep == buf + entry_length) {
+ d *= 0x800000;
+ gd->peak_signal = (guint32) floor(d + 0.5);
+ gd->peak_signal_set = TRUE;
+/* printf("peak_signal (ape): %f\n", (double) gd->peak_signal / 0x800000);*/
+ }
+
+ continue;
+ }
+ }
+
+ free(dbuf);
+ fclose(file);
+ return TRUE;
+
+rg_fail:
+ if (dbuf)
+ free(dbuf);
+ if (file)
+ fclose(file);
+ return FALSE;
+}
+
+
+/* ----------------------------------------------------------------------
+
+ mp3gain code
+
+---------------------------------------------------------------------- */
+
+#include <sys/wait.h>
+#include <fcntl.h>
+
+
+
+
+
+
+/**
+ * mp3_read_soundcheck:
+ *
+ * try to read the ReplayGain values from the LAME or Ape Tags and set
+ * the track's soundcheck field accordingly.
+ *
+ * @path: localtion of the file
+ * @track: structure holding track information
+ *
+ * The function always rereads the gain from the file.
+ *
+ * Returns TRUE if the soundcheck field could be set.
+ */
+gboolean mp3_read_soundcheck (gchar *path, Track *track)
+{
+ GainData gd;
+
+ g_return_val_if_fail (track, FALSE);
+
+ memset (&gd, 0, sizeof (GainData));
+
+ gd.radio_gain_set = FALSE;
+ gd.audiophile_gain_set = FALSE;
+ gd.peak_signal_set = FALSE;
+
+ mp3_get_track_lame_replaygain (path, &gd);
+ if (gd.radio_gain_set)
+ {
+ track->soundcheck = replaygain_to_soundcheck (gd.radio_gain);
+ return TRUE;
+ }
+
+ mp3_get_track_ape_replaygain (path, &gd);
+ if (gd.radio_gain_set)
+ {
+ track->soundcheck = replaygain_to_soundcheck (gd.radio_gain);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+
+
+
+/* mp3 slot size in bytes */
+int slotsize[3] = {4,1,1}; /* layer 1, layer 2, layer 3 */
+
+int samplesperframe[2][3] = {
+ { /* MPEG 2.0 */
+ 384,1152,576 /* layer 1, layer 2, layer 3 */
+ },
+
+ { /* MPEG 1.0 */
+ 384,1152,1152 /* layer 1, layer 2, layer 3 */
+ }
+};
+
+
+/*
+ * mp3_get_track_lame_gapless - read the specified file and scan for LAME Tag
+ * gapless information.
+ *
+ * @path: localtion of the file
+ * @track: structure holding track information
+ *
+ * TODO: Split off non-LAME stuff (samplecount, gapless_data) to a separate function since it's generic
+ */
+gboolean mp3_get_track_lame_gapless (gchar *path, GaplessData *gd)
+{
+ FILE *file = NULL;
+ char buf[4], version[5];
+ unsigned char ubuf[4];
+ int sideinfo;
+ int i;
+
+ g_return_val_if_fail (gd, FALSE);
+
+ if (!path)
+ goto gp_fail;
+
+ file = fopen (path, "rb");
+
+ if (!file)
+ goto gp_fail;
+
+ /* use get_first_header() to seek to the first mp3 header */
+ MP3Info *mp3i = NULL;
+ mp3i = g_malloc0 (sizeof (MP3Info));
+ mp3i->filename = path;
+ mp3i->file = file;
+ get_mp3_info (mp3i);
+ get_first_header (mp3i, 0);
+
+ int xing_header_offset = ftell (file);
+
+ MP3Header h;
+ if (!get_header (file, &h))
+ goto gp_fail;
+
+ int mysamplesperframe = samplesperframe[h.version & 1][3 - h.layer];
+
+ /* Determine offset of Xing header based on sideinfo size */
+ if (h.version & 0x1)
+ {
+ sideinfo = (h.mode & 0x2) ?
+ SIDEINFO_MPEG1_MONO : SIDEINFO_MPEG1_MULTI;
+ }
+ else
+ {
+ sideinfo = (h.mode & 0x2) ?
+ SIDEINFO_MPEG2_MONO : SIDEINFO_MPEG2_MULTI;
+ }
+
+ if (fseek (file, sideinfo, SEEK_CUR) ||
+ (fread (&buf[0], 1, 4, file) != 4))
+ goto gp_fail;
+
+ /* Is this really a Xing or Info Header?
+ * FIXME: Apparently (according to madplay sources) there is a different
+ * possible location for the Xing header ("due to an unfortunate
+ * historical event"). I do not thing we need to care though since
+ * ReplayGain information is only contained in recent files. */
+ if (strncmp (buf, "Xing", 4) && strncmp (buf, "Info", 4))
+ goto gp_fail;
+
+ /* Determine the offset of the LAME tag based on contents of the Xing header */
+ int flags;
+ fread (&flags, 4, 1, file);
+ int toskip = 0;
+ if (flags | 0x1)
+ { /* frames field is set */
+ toskip += 4;
+ }
+ if (flags | 0x2)
+ { /* bytes field is set */
+ toskip += 4;
+ }
+ if (flags | 0x4)
+ { /* TOC field is set */
+ toskip += 100;
+ }
+ if (flags | 0x8)
+ { /* quality field is set */
+ toskip += 4;
+ }
+
+ /* Check for LAME Tag */
+ if (fseek (file, toskip, SEEK_CUR) || (fread (&buf[0], 1, 4, file) != 4))
+ goto gp_fail;
+ if (strncmp (buf, "LAME", 4))
+ goto gp_fail;
+
+ /* Check LAME Version */
+ if (fread (version, 1, 5, file) != 5)
+ goto gp_fail;
+
+ /* XXX skip old LAME versions, or just assume that pre/postgap
+ * turn out zeros anyway, or check the CRC to vaidate the tag? */
+
+ gboolean cbr = FALSE;
+ if (fread (ubuf, 1, 1, file) != 1)
+ goto gp_fail;
+
+ if ((ubuf[0] & 0xf) == 0x1)
+ cbr = TRUE;
+
+ if (fseek (file, 0xB, SEEK_CUR) || (fread (ubuf, 1, 4, file) != 4))
+ goto gp_fail;
+
+ /* set pregap and postgap directly from LAME header */
+ gd->pregap = (ubuf[0] << 4) + (ubuf[1] >> 4);
+ gd->postgap = ((ubuf[1] & 0xf) << 8) + ubuf[2];
+
+ /* jump the end of the frame with the xing header */
+ if (fseek (file, xing_header_offset + frame_length (&h), SEEK_SET))
+ goto gp_fail;
+
+ /* counts bytes from the start of the 1st sync frame */
+ int totaldatasize = frame_length (&h);
+
+ /* keeps track of the last 8 frame sizes */
+ int lastframes[8];
+
+ /* counts number of music frames */
+ int totalframes = 0;
+
+ /* quickly parse the file, reading only frame headers */
+ int l = 0;
+ while ((l = get_header (file, &h)) != 0)
+ {
+ for (i = 7; i > 0; i--)
+ {
+ lastframes[i] = lastframes[i - 1];
+ }
+ lastframes[0] = l;
+ totaldatasize += l;
+ totalframes++;
+
+ if (fseek (file, l - FRAME_HEADER_SIZE, SEEK_CUR))
+ goto gp_fail;
+
+ }
+
+ int finaleight = 0;
+ for (i = 0; i < 8; i++)
+ {
+ finaleight += lastframes[i];
+ }
+
+ if (cbr)
+ totalframes++;
+
+ /* all but last eight frames */
+ gd->gapless_data = totaldatasize - finaleight;
+ /* total samples minus pre/postgap */
+ gd->samplecount = totalframes * mysamplesperframe - gd->pregap - gd->postgap;
+
+ return TRUE;
+
+
+ gp_fail:
+ if (file)
+ fclose (file);
+ return FALSE;
+
+}
+
+
+
+/**
+ * mp3_read_gapless:
+ *
+ * try to read the gapless values from the LAME Tag and set
+ * the track's pregap, postgap, samplecount, and gapless_data fields
+ * accordingly.
+ *
+ * @path: location of the file
+ * @track: structure holding track information
+ *
+ * The function always rereads the data from the file.
+ *
+ * Returns TRUE if all four gapless fields could be
+ * set. etrack->tchanged is set to TRUE if data has been changed,
+ * FALSE otherwise.
+ */
+gboolean mp3_read_gapless (char *path, Track *track)
+{
+ GaplessData gd;
+ ExtraTrackData *etr;
+
+ g_return_val_if_fail (track, FALSE);
+
+ etr = track->userdata;
+
+ memset (&gd, 0, sizeof (GaplessData));
+
+ gd.pregap = 0;
+ gd.samplecount = 0;
+ gd.postgap = 0;
+ gd.gapless_data = 0;
+
+ mp3_get_track_lame_gapless (path, &gd);
+
+ etr->tchanged = FALSE;
+
+ if ((gd.pregap) && (gd.samplecount) && (gd.postgap) && (gd.gapless_data))
+ {
+ if ((track->pregap != gd.pregap) ||
+ (track->samplecount != gd.samplecount) ||
+ (track->postgap != gd.postgap) ||
+ (track->gapless_data != gd.gapless_data) ||
+ (track->gapless_track_flag == FALSE))
+ {
+ etr->tchanged = TRUE;
+ track->pregap = gd.pregap;
+ track->samplecount = gd.samplecount;
+ track->postgap = gd.postgap;
+ track->gapless_data = gd.gapless_data;
+ track->gapless_track_flag = TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+
+/* ----------------------------------------------------------------------
+
+ From here starts original gtkpod code
+
+---------------------------------------------------------------------- */
+
+/* Return a Track structure with all information read from the mp3
+ file filled in */
+Track *mp3_get_file_info (gchar *name)
+{
+ Track *track = NULL;
+ File_Tag filetag;
+ MP3Info *mp3i=NULL;
+ FILE *file;
+ guchar *image_data = NULL;
+ gsize image_data_len = 0;
+
+ g_return_val_if_fail (name, NULL);
+
+ /* Attempt to open the file */
+ file = fopen (name, "r");
+ if (file)
+ {
+ mp3i = g_malloc0 (sizeof (MP3Info));
+ mp3i->filename = name;
+ mp3i->file = file;
+ get_mp3_info (mp3i);
+ mp3i->file = NULL;
+ fclose (file);
+ }
+ else
+ {
+ gchar *fbuf = charset_to_utf8 (name);
+ gtkpod_warning(_("ERROR while opening file: '%s' (%s).\n"),
+ fbuf, g_strerror(errno));
+ g_free (fbuf);
+ return NULL;
+ }
+
+ track = gp_track_new ();
+ track->filetype = g_strdup ("MPEG audio file");
+
+ if (prefs_get_int("readtags") && (id3_tag_read (name, &filetag) == TRUE))
+ {
+
+ if (filetag.album)
+ {
+ track->album = filetag.album;
+ }
+
+ if (filetag.artist)
+ {
+ track->artist = filetag.artist;
+ }
+
+ if (filetag.title)
+ {
+ track->title = filetag.title;
+ }
+
+ if (filetag.genre)
+ {
+ track->genre = filetag.genre;
+ }
+
+ if (filetag.composer)
+ {
+ track->composer = filetag.composer;
+ }
+
+ if (filetag.comment)
+ {
+ track->comment = filetag.comment;
+ }
+
+ if (filetag.podcasturl)
+ {
+ track->podcasturl = filetag.podcasturl;
+ }
+
+ if (filetag.podcastrss)
+ {
+ track->podcastrss = filetag.podcastrss;
+ }
+
+ if (filetag.subtitle)
+ {
+ track->subtitle = filetag.subtitle;
+ }
+
+ if (filetag.description)
+ {
+ track->description = filetag.description;
+ }
+
+ if (filetag.sort_artist)
+ {
+ track->sort_artist = filetag.sort_artist;
+ }
+
+ if (filetag.sort_title)
+ {
+ track->sort_title = filetag.sort_title;
+ }
+
+ if (filetag.sort_album)
+ {
+ track->sort_album = filetag.sort_album;
+ }
+
+ if (filetag.sort_albumartist)
+ {
+ track->sort_albumartist = filetag.sort_albumartist;
+ }
+
+ if (filetag.sort_composer)
+ {
+ track->sort_composer = filetag.sort_composer;
+ }
+
+ if (filetag.year == NULL)
+ {
+ track->year = 0;
+ }
+ else
+ {
+ track->year = atoi(filetag.year);
+ g_free (filetag.year);
+ }
+
+ if (filetag.trackstring == NULL)
+ {
+ track->track_nr = 0;
+ }
+ else
+ {
+ track->track_nr = atoi(filetag.trackstring);
+ g_free (filetag.trackstring);
+ }
+
+ if (filetag.track_total == NULL)
+ {
+ track->tracks = 0;
+ }
+ else
+ {
+ track->tracks = atoi(filetag.track_total);
+ g_free (filetag.track_total);
+ }
+ /* CD/disc number handling */
+ if (filetag.cdnostring == NULL)
+ {
+ track->cd_nr = 0;
+ }
+ else
+ {
+ track->cd_nr = atoi(filetag.cdnostring);
+ g_free (filetag.cdnostring);
+ }
+
+ if (filetag.cdno_total == NULL)
+ {
+ track->cds = 0;
+ }
+ else
+ {
+ track->cds = atoi(filetag.cdno_total);
+ g_free (filetag.cdno_total);
+ }
+
+ if (filetag.compilation == NULL)
+ {
+ track->compilation = 0;
+ }
+ else
+ {
+ track->compilation = atoi(filetag.compilation);
+ g_free (filetag.compilation);
+ }
+
+ if (filetag.BPM == NULL)
+ {
+ track->BPM = 0;
+ }
+ else
+ {
+ track->BPM = atoi(filetag.BPM);
+ g_free (filetag.BPM);
+ }
+
+ if (filetag.lyrics)
+ {
+ track->lyrics_flag = 0x01;
+ g_free (filetag.lyrics);
+ }
+ else
+ {
+ track->lyrics_flag = 0x00;
+ }
+ }
+
+ if (prefs_get_int("coverart_apic") &&
+ (id3_apic_read (name, &image_data, &image_data_len) == TRUE))
+ {
+ if (image_data)
+ {
+ gp_track_set_thumbnails_from_data (track,
+ image_data,
+ image_data_len);
+ g_free (image_data);
+ }
+ }
+
+ mp3_read_soundcheck (name, track);
+
+ mp3_read_gapless (name, track);
+
+#if LOCALDEBUG
+ printf("%s\n", name);
+ printf("\tpregap: %i\n", track->pregap);
+ printf("\tpostgap: %i\n", track->postgap);
+ printf("\tsamplecount: %li\n", track->samplecount);
+ printf("\tgaplessdata: %i\n", track->gapless_data);
+#endif
+
+
+ /* Get additional info (play time and bitrate */
+ if (mp3i)
+ {
+ track->tracklen = mp3i->milliseconds;
+ track->bitrate = (gint)(mp3i->vbr_average);
+ track->samplerate = mp3file_header_frequency (&mp3i->header);
+ g_free (mp3i);
+ }
+ /* Fall back to xmms code if tracklen is 0 */
+ if (track->tracklen == 0)
+ {
+ track->tracklen = get_track_time (name);
+ if (track->tracklen)
+ track->bitrate = (float)track->size*8/track->tracklen;
+ }
+
+ if (track->tracklen == 0)
+ {
+ /* Tracks with zero play length are ignored by iPod... */
+ gtkpod_warning (_("File \"%s\" has zero play length. Ignoring.\n"),
+ name);
+ gp_track_free (track);
+ track = NULL;
+ }
+ return track;
+}
Deleted: gtkpod/tags/0.99.10-5/src/prefs.c
===================================================================
--- gtkpod/trunk/src/prefs.c 2007-11-13 14:54:03 UTC (rev 259)
+++ gtkpod/tags/0.99.10-5/src/prefs.c 2007-11-20 13:46:35 UTC (rev 280)
@@ -1,2281 +0,0 @@
-/*
-| Copyright (C) 2002-2007 Jorg Schuler <jcsjcs at users sourceforge net>
-| Copyright (C) 2006 James Liggett <jrliggett at cox.net>
-| Part of the gtkpod project.
-|
-| URL: http://www.gtkpod.org/
-| URL: http://gtkpod.sourceforge.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
-|
-| iTunes and iPod are trademarks of Apple
-|
-| This product is not supported/written/published by Apple!
-|
-| $Id: prefs.c 1597 2007-06-26 14:35:18Z dforsi $
-*/
-
-/* -------------------------------------------------------------------
- *
- * HOWTO add a new_option to the prefs dialog
- *
- * - add the desired option to the prefs window using glade-2
- *
- * - set the default value of new_option in set_default_preferences() in prefs.c
- *
- * - add a callback on_new_option_*() to prefs_windows.c to set the
- * new value.
- * The value is applied to the actual prefs when pressing the "OK"
- * or "Apply" button in the prefs window.
- *
- * - add code to prefs_window_create() in prefs_window.c to set the
- * correct state of the option in the prefs window.
- *
- * - if you want new_option to be a command line option as well, add
- * code to usage() and read_commandline().
- *
- * - for environment variables, add code to read_environment().
- *
- * ---------------------------------------------------------------- */
-
-/* ----------------------------------------------------------------
- *
- * The prefs module should be thread safe. The hash table is locked
- * before each read or write access.
- *
- * The temp_prefs module is not thread-safe. If necessary a locking
- * mechanism can be implemented.
- *
- * ---------------------------------------------------------------- */
-
-
-
-
-/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
- Ditto for AIX 3.2 and <stdlib.h>. */
-#ifndef _NO_PROTO
-# define _NO_PROTO
-#endif
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <glib/gstdio.h>
-#ifdef HAVE_GETOPT_LONG_ONLY
-# include <getopt.h>
-#else
-# include "getopt.h"
-#endif
-
-#include "clientserver.h"
-#include "misc.h"
-#include "prefs.h"
-
-/*
- * Data global to this module only
- */
-
-/* End-of-list marker for variable-length lists */
-#define LIST_END_MARKER "----++++----"
-
-struct temp_prefs_save
-{
- GIOChannel *gio;
- GError **error;
- gboolean success;
-};
-
-struct sub_data
-{
- TempPrefs *temp_prefs;
- TempPrefs *temp_prefs_orig;
- const gchar *subkey;
- const gchar *subkey2;
- gboolean exists;
-};
-
-/* Pointer to preferences hash table */
-static GHashTable *prefs_table = NULL;
-static GMutex *prefs_table_mutex = NULL;
-
-/*
- * Functions used by this module only
- */
-void discard_prefs (void);
-
-/* Different paths that can be set in the prefs window */
-typedef enum
-{
- PATH_PLAY_NOW = 0,
- PATH_PLAY_ENQUEUE,
- PATH_MP3GAIN,
- PATH_SYNC_CONTACTS,
- PATH_SYNC_CALENDAR,
- PATH_MSERV_MUSIC_ROOT,
- PATH_MSERV_TRACKINFO_ROOT,
- PATH_SYNC_NOTES,
- PATH_AACGAIN,
- PATH_NUM
-} PathType;
-
-/* enum for reading of options */
-enum {
- GP_HELP,
- GP_PLAYCOUNT,
- GP_MOUNT,
- GP_PRINT_HASH,
-};
-
-
-/* Lock the prefs table. If the table is already locked the calling
- * thread will remain blocked until the lock is released by the other thread. */
-static void lock_prefs_table ()
-{
- g_return_if_fail (prefs_table_mutex);
- g_mutex_lock (prefs_table_mutex);
-}
-
-/* Unlock the prefs table again. */
-static void unlock_prefs_table ()
-{
- g_return_if_fail (prefs_table_mutex);
- g_mutex_unlock (prefs_table_mutex);
-}
-
-
-/* Set default preferences */
-static void set_default_preferences()
-{
- int i;
- gchar *str;
-
- prefs_set_int("update_existing", FALSE);
- prefs_set_int("id3_write", FALSE);
- prefs_set_int("id3_write_id3v24", FALSE);
- prefs_set_int(KEY_SYNC_DELETE_TRACKS, TRUE);
- prefs_set_int(KEY_SYNC_CONFIRM_DELETE, TRUE);
- prefs_set_int(KEY_SYNC_SHOW_SUMMARY, TRUE);
- prefs_set_int("show_duplicates", TRUE);
- prefs_set_int("show_non_updated", TRUE);
- prefs_set_int("show_updated", TRUE);
- prefs_set_int("mserv_report_probs", TRUE);
- prefs_set_int("delete_ipod", TRUE);
- prefs_set_int("delete_file", TRUE);
- prefs_set_int("delete_local_file", TRUE);
- prefs_set_int("delete_database", TRUE);
- prefs_set_string("initial_mountpoint", "/media/ipod");
- prefs_set_string ("path_play_now", "xmms %s");
- prefs_set_string ("path_play_enqueue", "xmms -e %s");
- prefs_set_string ("path_mserv_trackinfo_root", "/var/lib/mserv/trackinfo/");
-
- str = g_build_filename (SCRIPTDIR, "convert-ogg2mp3.sh", NULL);
- prefs_set_string ("path_conv_ogg", str);
- g_free (str);
- prefs_set_int ("convert_ogg", TRUE);
-
- str = g_build_filename (SCRIPTDIR, "convert-flac2mp3.sh", NULL);
- prefs_set_string ("path_conv_flac", str);
- g_free (str);
- prefs_set_int ("convert_flac", TRUE);
-
- str = g_build_filename (SCRIPTDIR, "convert-wav2mp3.sh", NULL);
- prefs_set_string ("path_conv_wav", str);
- g_free (str);
- prefs_set_int ("convert_wav", FALSE);
-
-
- /* Set sorting tab defaults */
- for (i = 0; i < SORT_TAB_MAX; i++)
- {
- prefs_set_int_index("st_autoselect", i, TRUE);
- prefs_set_int_index("st_category", i, (i < ST_CAT_NUM ? i : 0));
- prefs_set_int_index("sp_or", i, FALSE);
- prefs_set_int_index("sp_rating_cond", i, FALSE);
- prefs_set_int_index("sp_playcount_cond", i, FALSE);
- prefs_set_int_index("sp_played_cond", i, FALSE);
- prefs_set_int_index("sp_modified_cond", i, FALSE);
- prefs_set_int_index("sp_added_cond", i, FALSE);
- prefs_set_int_index("sp_rating_state", i, 0);
- prefs_set_string_index("sp_played_state", i, ">4w");
- prefs_set_string_index("sp_modified_state", i, "<1d");
- prefs_set_string_index("sp_added_state", i, "<1d");
- prefs_set_int_index("sp_playcount_low", i, 0);
- prefs_set_int_index("sp_playcount_high", i, -1);
- prefs_set_int_index("sp_autodisplay", i, FALSE);
- }
-
- prefs_set_int("sort_tab_num", 2);
-
- /* Set colum preferences */
- for (i = 0; i < TM_NUM_COLUMNS; i++)
- {
- prefs_set_int_index("tm_col_width", i, 80);
- prefs_set_int_index("col_visible", i, FALSE);
- prefs_set_int_index("col_order", i, i);
- }
-
- for (i = 0; i < TM_NUM_TAGS_PREFS; i++)
- prefs_set_int_index("tag_autoset", i, FALSE);
-
- prefs_set_int_index("tag_autoset", TM_COLUMN_TITLE, TRUE);
-
- prefs_set_int_index("col_visible", TM_COLUMN_ARTIST, TRUE);
- prefs_set_int_index("col_visible", TM_COLUMN_ALBUM, TRUE);
- prefs_set_int_index("col_visible", TM_COLUMN_TITLE, TRUE);
- prefs_set_int_index("col_visible", TM_COLUMN_GENRE, TRUE);
- prefs_set_int_index("col_visible", TM_COLUMN_PLAYCOUNT, TRUE);
- prefs_set_int_index("col_visible", TM_COLUMN_RATING, TRUE);
-
- /* Set pane positions--Let gtk worry about position */
- for (i = 0; i < PANED_NUM; i++)
- prefs_set_int_index("paned_pos_", i, -1);
-
- prefs_set_int("mpl_autoselect", TRUE);
-
- /* Set window sizes */
- prefs_set_int("size_gtkpod.x", 600);
- prefs_set_int("size_gtkpod.y", 500);
- prefs_set_int("size_cal.x", 500);
- prefs_set_int("size_cal.y", 300);
- prefs_set_int("size_conf_sw.x", 300);
- prefs_set_int("size_conf_sw.y", 300);
- prefs_set_int("size_conf.x", 300);
- prefs_set_int("size_conf.y", -1);
- prefs_set_int("size_dirbr.x", 300);
- prefs_set_int("size_dirbr.y", 400);
- prefs_set_int("size_prefs.x", -1);
- prefs_set_int("size_prefs.y", 480);
- prefs_set_int("size_info.x", 510);
- prefs_set_int("size_info.y", 300);
-
- /* size of file dialog if there is not a details textview */
- prefs_set_int("size_file_dialog.x", 320);
- prefs_set_int("size_file_dialog.y", 140);
-
- /* size of file dialog if there is a details textview */
- prefs_set_int("size_file_dialog_details.x", 320);
- prefs_set_int("size_file_dialog_details.y", 140);
-
- prefs_set_int("readtags", TRUE);
- prefs_set_int("write_extended_info", TRUE);
- prefs_set_int("parsetags", FALSE);
- prefs_set_int("parsetags_overwrite", FALSE);
- prefs_set_string("parsetags_template", "%a - %A/%T %t.mp3;%t.wav");
- prefs_set_int("coverart_apic", TRUE);
- prefs_set_int("coverart_file", TRUE);
- prefs_set_string("coverart_template", "%A;folder.jpg");
- prefs_set_int("mserv_use", FALSE);
- prefs_set_string("mserv_username", "");
- prefs_set_int("startup_messages", TRUE);
- prefs_set_int("add_recursively", TRUE);
- prefs_set_int("info_window", FALSE);
- prefs_set_int("last_prefs_page", 0);
- prefs_set_int("multi_edit_title", TRUE);
- prefs_set_int("multi_edit", FALSE);
- prefs_set_int("not_played_track", TRUE);
- prefs_set_int("misc_track_nr", 25);
- prefs_set_int("update_charset", FALSE);
- prefs_set_int("display_tooltips_main", TRUE);
- prefs_set_int("display_tooltips_prefs", TRUE);
- prefs_set_int("display_toolbar", TRUE);
- prefs_set_int("toolbar_style", GTK_TOOLBAR_BOTH);
- prefs_set_int("sha1", TRUE);
- prefs_set_string("export_template", "%o;%a - %t.mp3;%t.wav");
- prefs_set_int("file_dialog_details_expanded", FALSE);
-
- /* Set last browsed directory */
- str = g_get_current_dir();
-
- if (str)
- {
- prefs_set_string("last_dir_browsed", str);
- g_free(str);
- }
- else
- prefs_set_string("last_dir_browsed", g_get_home_dir());
-
- /* Set sorting prefs */
- prefs_set_int("case_sensitive", FALSE);
- prefs_set_int("tm_autostore", FALSE);
- prefs_set_int("st_sort", SORT_NONE);
- prefs_set_int("pm_sort", SORT_NONE);
- prefs_set_int("tm_sortcol", TM_COLUMN_TITLE);
- prefs_set_int("tm_sort", SORT_NONE);
-}
-
-/* Initialize default variable-length list entries */
-static void set_default_list_entries()
-{
- if (!prefs_get_string_value_index("sort_ign_string_", 0, NULL))
- {
- prefs_set_string_index("sort_ign_string_", 0, "a ");
- prefs_set_string_index("sort_ign_string_", 1, "an ");
- prefs_set_string_index("sort_ign_string_", 2, LIST_END_MARKER);
- }
-}
-
-/* A printf-like function that outputs in the system locale */
-static void locale_fprintf(FILE *fp, const gchar *format, ...)
-{
- gchar *utf8_string; /* Raw UTF-8 string */
- gchar *locale_string; /* String in system locale format */
- va_list format_list; /* Printf-like formatting arguments */
-
- /* Create the locale format string based on the given format */
- va_start(format_list, format);
- utf8_string = g_strdup_vprintf(format, format_list);
- va_end(format_list);
-
- locale_string = g_locale_from_utf8 (utf8_string, -1, NULL, NULL, NULL);
-
- if (fp)
- fprintf(fp, "%s", locale_string);
-
- g_free(utf8_string);
- g_free(locale_string);
-}
-
-/* Print commandline usage information */
-static void usage(FILE *fp)
-{
- locale_fprintf(fp, _("gtkpod version %s usage:\n"), VERSION);
- locale_fprintf(fp, _(" -h, --help: display this message\n"));
- locale_fprintf(fp, _(" -p <file>: increment playcount for file by one\n"));
- locale_fprintf(fp, _(" --hash <file>:print gtkpod hash for file\n"));
- locale_fprintf(fp, _(" -m path: define the mountpoint of your iPod\n"));
- locale_fprintf(fp, _(" --mountpoint: same as '-m'.\n"));
- locale_fprintf(fp, _(" -a: import database automatically after start.\n"));
- locale_fprintf(fp, _(" --auto: same as '-a'.\n"));
-}
-
-/* Parse commandline based options */
-static void read_commandline(int argc, char *argv[])
-{
- int option; /* Code returned by getopt */
-
- /* The options data structure. The format is standard getopt. */
- struct option const options[] =
- {
- { "h", no_argument, NULL, GP_HELP },
- { "help", no_argument, NULL, GP_HELP },
- { "p", required_argument, NULL, GP_PLAYCOUNT },
- { "hash", required_argument, NULL, GP_PRINT_HASH },
- { "m", required_argument, NULL, GP_MOUNT },
- { "mountpoint", required_argument, NULL, GP_MOUNT },
- { 0, 0, 0, 0 }
- };
-
- /* Handle commandline options */
- while ((option = getopt_long_only(argc, argv, "", options, NULL)) != -1)
- {
- switch (option)
- {
- case GP_HELP:
- usage(stdout);
- exit(0);
- break;
- case GP_PLAYCOUNT:
- client_playcount(optarg);
- exit(0);
- break;
- case GP_PRINT_HASH:
- print_sha1_hash (optarg);
- exit(0);
- break;
- case GP_MOUNT:
- prefs_set_string("initial_mountpoint", optarg);
- break;
- default:
- locale_fprintf(stderr, "Unknown option: %s\n", argv[optind]);
- usage(stderr);
- exit(1);
- break;
- };
- }
-}
-
-/* Read options from environment variables */
-static void read_environment()
-{
- gchar *buf;
-
- buf = convert_filename(getenv("IPOD_MOUNTPOINT"));
- if (buf)
- prefs_set_string("initial_mountpoint", buf);
- g_free(buf);
-}
-
-/* Create a full numbered key from a base key string and a number.
- * Free returned string. */
-static gchar *create_full_key(const gchar *base_key, gint index)
-{
- if (base_key)
- return g_strdup_printf("%s%i", base_key, index);
- else
- return NULL;
-}
-
-/* Remove key present in the temp prefs tree from the hash table */
-static gboolean flush_key (gpointer key, gpointer value, gpointer user_data)
-{
- g_return_val_if_fail (prefs_table, FALSE);
-
- g_hash_table_remove (prefs_table, key);
-
- return FALSE;
-}
-
-
-/* Copy key data from the temp prefs tree to the hash table (or to
- * sub_data->temp_prefs_orig if non-NULL). The old key is removed. */
-static gboolean subst_key (gpointer key, gpointer value, gpointer user_data)
-{
- struct sub_data *sub_data = user_data;
- gint len;
-
- g_return_val_if_fail (key && value && user_data, FALSE);
- g_return_val_if_fail (sub_data->subkey && sub_data->subkey2, FALSE);
- if (!sub_data->temp_prefs_orig)
- g_return_val_if_fail (prefs_table, FALSE);
- if (sub_data->temp_prefs_orig)
- g_return_val_if_fail (sub_data->temp_prefs_orig->tree, FALSE);
-
- len = strlen (sub_data->subkey);
-
- if (strncmp (key, sub_data->subkey, len) == 0)
- {
- gchar *new_key = g_strdup_printf ("%s%s",
- sub_data->subkey2,
- ((gchar *)key)+len);
- if (sub_data->temp_prefs_orig)
- {
- g_tree_remove (sub_data->temp_prefs_orig->tree, key);
- g_tree_insert (sub_data->temp_prefs_orig->tree,
- new_key, g_strdup(value));
- }
- else
- {
- g_hash_table_remove (prefs_table, key);
- g_hash_table_insert (prefs_table, new_key, g_strdup(value));
- }
- }
- return FALSE;
-}
-
-/* return TRUE if @key starts with @subkey */
-static gboolean match_subkey (gpointer key, gpointer value, gpointer subkey)
-{
- g_return_val_if_fail (key && subkey, FALSE);
-
- if (strncmp (key, subkey, strlen (subkey)) == 0) return TRUE;
- return FALSE;
-}
-
-
-/* return TRUE and set sub_data->exists to TRUE if @key starts with
- * @subkey */
-static gboolean check_subkey (gpointer key, gpointer value, gpointer user_data)
-{
- struct sub_data *sub_data = user_data;
-
- g_return_val_if_fail (key && user_data, TRUE);
- g_return_val_if_fail (sub_data->subkey, TRUE);
-
- if (strncmp (key, sub_data->subkey, strlen (sub_data->subkey)) == 0)
- {
- sub_data->exists = TRUE;
- return TRUE;
- }
- return FALSE;
-}
-
-
-
-/* Add key/value to temp_prefs if it matches subkey -- called by
- * prefs_create_subset() and temp_prefs_create_subset() */
-static gboolean get_subset (gpointer key, gpointer value, gpointer user_data)
-{
- struct sub_data *sub_data = user_data;
-
- g_return_val_if_fail (key && value && user_data, TRUE);
- g_return_val_if_fail (sub_data->subkey && sub_data->temp_prefs, TRUE);
-
- if (strncmp (key, sub_data->subkey,
- strlen (sub_data->subkey)) == 0)
- { /* match */
- temp_prefs_set_string (sub_data->temp_prefs, key, value);
- }
- return FALSE; /* continue traversal (g_tree), ignored for g_hash */
-}
-
-
-/* Copy a variable-length list to the prefs table */
-static gboolean copy_list(gpointer key, gpointer value, gpointer user_data)
-{
- prefs_apply_list((gchar*)key, (GList*)value);
- return FALSE;
-}
-
-/* Callback that writes pref table data to a file */
-static void write_key(gpointer key, gpointer value, gpointer user_data)
-{
- FILE *fp; /* file pointer passed in through user_data */
-
- /* Write out each key and value to the given file */
- fp = (FILE*)user_data;
-
- if (fp)
- fprintf(fp, "%s=%s\n", (gchar*)key, (gchar*)value);
-}
-
-/* Gets a string that contains ~/.gtkpod/ If the folder doesn't exist,
- * create it. Free the string when you are done with it.
- * If the folder wasn't found, and couldn't be created, return NULL */
-gchar *prefs_get_cfgdir()
-{
- gchar *folder; /* Folder path */
-
- /* Create the folder path. If the folder doesn't exist, create it. */
- folder = g_build_filename(g_get_home_dir(), ".gtkpod", NULL);
-
- if (!g_file_test(folder, G_FILE_TEST_IS_DIR))
- {
- if ((g_mkdir(folder, 0777)) == -1)
- {
- printf(_("Couldn't create ~/.gtkpod\n"));
- return NULL;
- }
- }
-
- return folder;
-}
-
-
-/* get @key and @value from a string like "key=value" */
-static gboolean read_prefs_get_key_value (const gchar *buf,
- gchar **key, gchar **value)
-{
- size_t len; /* string length */
- const gchar *buf_start; /* Pointer to where actual useful data starts in line */
-
- g_return_val_if_fail (buf && key && value, FALSE);
-
- /* Strip out any comments (lines that begin with ; or #) */
- if ((buf[0] == ';') || (buf[0] == '#'))
- return FALSE;
-
- /* Find the key and value, and look for malformed lines */
- buf_start = strchr (buf, '=');
-
- if ((!buf_start) || (buf_start == buf))
- {
- printf("Parse error reading prefs: %s", buf);
- return FALSE;
- }
-
- /* Find the key name */
- *key = g_strndup (buf, (buf_start - buf));
-
- /* Strip whitespace */
- g_strstrip (*key);
-
- /* Find the value string */
- *value = strdup (buf_start+1);
-
- /* remove newline */
- len = strlen (*value);
- if ((len > 0) && ((*value)[len - 1] == 0x0a))
- (*value)[len - 1] = 0;
-
- /* Don't strip whitespace! If there is any, there's a reason for it. */
- /* g_strstrip (*value); */
-
- return TRUE;
-}
-
-
-/* Read preferences from a file */
-static void read_prefs_from_file(FILE *fp)
-{
- gchar buf[PATH_MAX]; /* Buffer that contains one line */
- gchar *key; /* Pref value key */
- gchar *value; /* Pref value */
-
-
- g_return_if_fail (prefs_table && fp);
-
- while (fgets(buf, PATH_MAX, fp))
- {
- if (read_prefs_get_key_value (buf, &key, &value))
- {
- g_hash_table_insert (prefs_table, key, value);
- }
- }
-}
-
-/* Write prefs to file */
-static void write_prefs_to_file(FILE *fp)
-{
- lock_prefs_table ();
-
- if (!prefs_table)
- {
- unlock_prefs_table ();
- g_return_if_reached ();
- }
-
- g_hash_table_foreach(prefs_table, write_key, (gpointer)fp);
-
- unlock_prefs_table ();
-}
-
-/* Load preferences, first loading the defaults, and then overwrite that with
- * preferences in the user home folder. */
-static void load_prefs()
-{
- gchar *filename; /* Config path to open */
- gchar *config_dir; /* Directory where config is (usually ~/.gtkpod) */
- FILE *fp;
-
- /* Start by initializing the prefs to their default values */
- set_default_preferences();
-
- /* and then override those values with those found in the home folder. */
- config_dir = prefs_get_cfgdir();
-
- if (config_dir)
- {
- filename = g_build_filename(config_dir, "prefs", NULL);
-
- if (filename)
- {
- fp = fopen(filename, "r");
-
- if (fp)
- {
- read_prefs_from_file(fp);
- fclose(fp);
- }
-
- g_free(filename);
- }
-
- g_free(config_dir);
- }
-
- /* Finally, initialize variable-length lists. Do this after everything else
- * so that list defaults don't hang out in the table after prefs have been
- * read from the file. */
- set_default_list_entries();
-}
-
-/* Save preferences to user home folder (~/.gtkpod/prefs) */
-void prefs_save ()
-{
- gchar *filename; /* Path of file to write to */
- gchar *config_dir; /* Folder where prefs file is */
- FILE *fp; /* File pointer */
-
- /* Open $HOME/.gtkpod/prefs, and write prefs */
- config_dir = prefs_get_cfgdir();
-
- if (config_dir)
- {
- filename = g_build_filename(config_dir, "prefs", NULL);
-
- if (filename)
- {
- fp = fopen(filename, "w");
-
- if (fp)
- {
- write_prefs_to_file(fp);
- fclose(fp);
- }
-
- g_free(filename);
- }
-
- g_free(config_dir);
- }
-}
-
-
-static gboolean temp_prefs_save_fe (gchar *key, gchar *value,
- struct temp_prefs_save *tps)
-{
- gchar *buf;
- GIOStatus status;
-
- buf=g_strdup_printf ("%s=%s\n", key, value);
- status = g_io_channel_write_chars (tps->gio, buf, -1, NULL, tps->error);
- g_free (buf);
- if (status != G_IO_STATUS_NORMAL)
- {
- tps->success = FALSE;
- return TRUE; /* stop traversal */
- }
- return FALSE;
-}
-
-
-/* Save @temp_prefs to @filename in the same manner as prefs_save is
- * saving to ~/.gtkpod/prefs. @error: location where to store
- * information about errors or NULL.
- *
- * Return value: TRUE on success, FALSE if an error occured, in which
- * case @error will be set accordingly.
- */
-gboolean temp_prefs_save (TempPrefs *temp_prefs,
- const gchar *filename,
- GError **error)
-{
- GIOChannel *gio;
- struct temp_prefs_save tps;
-
- g_return_val_if_fail (temp_prefs && filename, FALSE);
-
- gio = g_io_channel_new_file (filename, "w", error);
- tps.gio = gio;
- tps.error = error;
- tps.success = TRUE;
- if (gio)
- {
- g_tree_foreach (temp_prefs->tree, (GTraverseFunc)temp_prefs_save_fe, &tps);
- g_io_channel_unref (gio);
- }
-
- return tps.success;
-}
-
-
-TempPrefs *temp_prefs_load (const gchar *filename, GError **error)
-{
- GIOChannel *gio;
- TempPrefs *temp_prefs = NULL;
-
- g_return_val_if_fail (filename, NULL);
-
- gio = g_io_channel_new_file (filename, "r", error);
- if (gio)
- {
- GIOStatus status;
-
- temp_prefs = temp_prefs_create ();
-
- do
- {
- gchar *line;
-
- status = g_io_channel_read_line (gio, &line, NULL, NULL, error);
- if (status == G_IO_STATUS_NORMAL)
- {
- gchar *key, *value;
- if (read_prefs_get_key_value (line, &key, &value))
- {
- temp_prefs_set_string (temp_prefs, key, value);
- }
- g_free (line);
- }
- } while (status == G_IO_STATUS_NORMAL);
-
- g_io_channel_unref (gio);
-
- if (status != G_IO_STATUS_EOF)
- {
- temp_prefs_destroy (temp_prefs);
- temp_prefs = NULL;
- }
- }
-
- return temp_prefs;
-}
-
-
-/* Removes already existing list keys from the prefs table */
-static void wipe_list(const gchar *key)
-{
- gchar *full_key; /* Complete key, with its number suffix */
- guint i; /* Loop counter */
-
- /* Go through the prefs table, starting at key<number>, delete it and go
- * through key<number+1>... until there are no keys left */
-
- for (i = 0;;i++)
- {
- full_key = create_full_key(key, i);
-
- if (g_hash_table_remove(prefs_table, full_key))
- {
- g_free(full_key);
- continue;
- }
- else /* We got all the unneeded keys, leave the loop... */
- {
- g_free(full_key);
- break;
- }
- }
-}
-
-/* Delete and rename keys */
-static void cleanup_keys()
-{
- gchar *buf;
- gchar *sp = NULL;
- gint int_buf;
- gint i;
- gint x, y, p; /* Window position */
- float version=0;
-
- /* Get version */
- version = prefs_get_double("version");
-
- /* rename mountpoint to initial_mountpoint */
- if (prefs_get_string_value(KEY_MOUNTPOINT, &buf))
- {
- prefs_set_string("initial_mountpoint", buf);
- g_free(buf);
- prefs_set_string(KEY_MOUNTPOINT, NULL);
- }
-
- /* rename coverart to coverart_file */
- if (prefs_get_string_value("coverart", &buf))
- {
- prefs_set_string("coverart_file", buf);
- g_free(buf);
- prefs_set_string("coverart", NULL);
- }
-
- /* rename tm_sort_ to tm_sort */
- if (prefs_get_string_value("tm_sort_", &buf))
- {
- prefs_set_string("tm_sort", buf);
- g_free(buf);
- prefs_set_string("tm_sort_", NULL);
- }
-
- /* rename md5 to sha1 */
- if (prefs_get_string_value("md5", &buf))
- {
- prefs_set_string("sha1", buf);
- g_free(buf);
- prefs_set_string("md5", NULL);
- }
-
- /* Convert old path numbered keys to named ones */
-
- /* Play Now */
- if (prefs_get_string_value_index("path", PATH_PLAY_NOW, &buf))
- {
- prefs_set_string("path_play_now", buf);
- prefs_set_string_index("path", PATH_PLAY_NOW, NULL);
- if (version < 0.87)
- { /* default changed from "xmms -p %s" to "xmms
- %s" which avoids xmms from hanging --
- thanks to Chris Vine */
- if (strcmp (buf, "xmms -p %s") == 0)
- {
- prefs_set_string ("path_play_now", "xmms %s");
- }
- }
- g_free(buf);
- }
-
- if (prefs_get_string_value_index("toolpath", PATH_PLAY_NOW, &buf))
- {
- prefs_set_string("path_play_now", buf);
- g_free(buf);
- prefs_set_string_index("toolpath", PATH_PLAY_NOW, NULL);
- }
-
- /* Enqueue */
- if (prefs_get_string_value_index("path", PATH_PLAY_ENQUEUE, &buf))
- {
- prefs_set_string("path_play_enqueue", buf);
- g_free(buf);
- prefs_set_string_index("path", PATH_PLAY_ENQUEUE, NULL);
- }
-
- if (prefs_get_string_value_index("toolpath", PATH_PLAY_ENQUEUE, &buf))
- {
- prefs_set_string("path_play_enqueue", buf);
- g_free(buf);
- prefs_set_string_index("toolpath", PATH_PLAY_ENQUEUE, NULL);
- }
-
- /* MP3 Gain */
- if (prefs_get_string_value_index("path", PATH_MP3GAIN, &buf))
- {
- prefs_set_string("path_mp3gain", buf);
- g_free(buf);
- prefs_set_string_index("path", PATH_MP3GAIN, NULL);
- }
-
- if (prefs_get_string_value_index("toolpath", PATH_MP3GAIN, &buf))
- {
- prefs_set_string("path_mp3gain", buf);
- g_free(buf);
- prefs_set_string_index("toolpath", PATH_MP3GAIN, NULL);
- }
-
- /* Sync contacts */
- if (prefs_get_string_value_index("path", PATH_SYNC_CONTACTS, &buf))
- {
- prefs_set_string("itdb_0_path_sync_contacts", buf);
- g_free(buf);
- prefs_set_string_index("path", PATH_SYNC_CONTACTS, NULL);
- }
-
- if (prefs_get_string_value_index("toolpath", PATH_SYNC_CONTACTS, &buf))
- {
- prefs_set_string("itdb_0_path_sync_contacts", buf);
- g_free(buf);
- prefs_set_string_index("toolpath", PATH_SYNC_CONTACTS, NULL);
- }
-
- /* Sync calendar */
- if (prefs_get_string_value_index("path", PATH_SYNC_CALENDAR, &buf))
- {
- prefs_set_string("itdb_0_path_sync_calendar", buf);
- g_free(buf);
- prefs_set_string_index("path", PATH_SYNC_CALENDAR, NULL);
- }
-
- if (prefs_get_string_value_index("toolpath", PATH_SYNC_CALENDAR, &buf))
- {
- prefs_set_string("itdb_0_path_sync_calendar", buf);
- g_free(buf);
- prefs_set_string_index("toolpath", PATH_SYNC_CALENDAR, NULL);
- }
-
- /* Sync notes */
- if (prefs_get_string_value_index("path", PATH_SYNC_NOTES, &buf))
- {
- prefs_set_string("itdb_0_path_sync_notes", buf);
- g_free(buf);
- prefs_set_string_index("path", PATH_SYNC_NOTES, NULL);
- }
-
- if (prefs_get_string_value_index("toolpath", PATH_SYNC_NOTES, &buf))
- {
- prefs_set_string("itdb_0_path_sync_notes", buf);
- g_free(buf);
- prefs_set_string_index("toolpath", PATH_SYNC_NOTES, NULL);
- }
-
- /* MSERV music root */
- if (prefs_get_string_value_index("path", PATH_MSERV_MUSIC_ROOT, &buf))
- {
- prefs_set_string("path_mserv_music_root", buf);
- g_free(buf);
- prefs_set_string_index("path", PATH_MSERV_MUSIC_ROOT, NULL);
- }
-
- if (prefs_get_string_value_index("toolpath", PATH_MSERV_MUSIC_ROOT, &buf))
- {
- prefs_set_string("path_mserv_music_root", buf);
- g_free(buf);
- prefs_set_string_index("toolpath", PATH_MSERV_MUSIC_ROOT, NULL);
- }
-
- /* MSERV track info root */
- if (prefs_get_string_value_index("path", PATH_MSERV_TRACKINFO_ROOT, &buf))
- {
- prefs_set_string("path_mserv_trackinfo_root", buf);
- g_free(buf);
- prefs_set_string_index("path", PATH_MSERV_TRACKINFO_ROOT, NULL);
- }
-
- if (prefs_get_string_value_index("toolpath", PATH_MSERV_TRACKINFO_ROOT, &buf))
- {
- prefs_set_string("path_mserv_trackinfo_root", buf);
- g_free(buf);
- prefs_set_string_index("toolpath", PATH_MSERV_TRACKINFO_ROOT, NULL);
- }
-
- /* If there's an extra (PATH_NUM) key, delete it */
- prefs_set_string_index("path", PATH_NUM, NULL);
- prefs_set_string_index("toolpath", PATH_NUM, NULL);
-
- /* Ignore/remove some keys */
- prefs_set_string("play_now_path", NULL);
- prefs_set_string("sync_remove", NULL);
- prefs_set_string("sync_remove_confirm", NULL);
- prefs_set_string("show_sync_dirs", NULL);
- prefs_set_string("play_enqueue_path", NULL);
- prefs_set_string("mp3gain_path", NULL);
- prefs_set_string("statusbar_timeout", NULL);
- prefs_set_string("offline", NULL);
- prefs_set_string("time_format", NULL);
- prefs_set_string("id3_all", NULL);
- prefs_set_string("pm_autostore", NULL);
- prefs_set_string("backups", NULL);
- prefs_set_string("save_sorted_order", NULL);
- prefs_set_string("fix_path", NULL);
- prefs_set_string("write_gaintag", NULL);
- prefs_set_string("automount", NULL);
- prefs_set_string("display_artcovers", NULL);
- prefs_set_string("block_display", NULL);
- prefs_set_string("tmp_disable_sort", NULL);
- prefs_set_string("size_file_dialog.x", NULL);
- prefs_set_string("size_file_dialog.y", NULL);
- prefs_set_string("size_file_dialog_details.x", NULL);
- prefs_set_string("size_file_dialog_details.y", NULL);
- prefs_set_string("autoimport", NULL);
- prefs_set_string("auto_import", NULL);
-
- /* sp_created_cond renamed to sp_added_cond */
- for (i = 0; i < SORT_TAB_MAX; i++)
- {
- if (prefs_get_int_value_index("sp_created_cond", i, &int_buf))
- {
- prefs_set_int_index("sp_added_cond", i, int_buf);
- prefs_set_string("sp_created_cond", NULL);
- }
- }
-
- /* sp_created_state renamed to sp_added_state */
- for (i = 0; i < SORT_TAB_MAX; i++)
- {
- if (prefs_get_int_value_index("sp_created_state", i, &int_buf))
- {
- prefs_set_int_index("sp_added_state", i, int_buf);
- prefs_set_string("sp_created_state", NULL);
- }
- }
-
- /* sm_col_width renamed to tm_col_width */
- for (i = 0; i < TM_NUM_COLUMNS; i++)
- {
- if (prefs_get_int_value_index("sm_col_width", i, &int_buf))
- {
- prefs_set_int_index("tm_col_width", i, int_buf);
- prefs_set_string_index("sm_col_width", i, NULL);
- }
- }
-
- /* handle version changes in prefs */
- if (version == 0.0)
- {
- /* most likely prefs file written by V0.50 */
- /* I added two new PANED elements since V0.50 --> shift */
- for (i=PANED_NUM_ST-1; i>=0; --i)
- {
- prefs_set_int_index("paned_pos_", PANED_NUM_GLADE + i,
- prefs_get_int_index("paned_pos_", PANED_NUM_GLADE + i - 2));
- }
- prefs_set_int_index("paned_pos_", PANED_STATUS1, -1);
- prefs_set_int_index("paned_pos_", PANED_STATUS2, -1);
- }
-
- /* set statusbar paned to a decent value if unset */
- if (prefs_get_int_index("paned_pos_", PANED_STATUS1) == -1)
- {
- x = prefs_get_int("size_gtkpod.x");
- /* set to about 2/3 of the window width */
- if (x>0)
- prefs_set_int_index("paned_pos_", PANED_STATUS1, 20*x/30);
- }
-
- if (prefs_get_int_index("paned_pos_", PANED_STATUS2) == -1)
- {
- x = prefs_get_int("size_gtkpod.x");
- y = prefs_get_int("size_gtkpod.y");
- p = prefs_get_int_index("paned_pos_", PANED_STATUS1);
- /* set to about half of the remaining window */
- if (x>0)
- prefs_set_int_index("paned_pos_", PANED_STATUS2, (x-p)/2 );
- }
-
- /* Changed layout of info window between 0.72 and 0.73 */
- if (version < 0.73)
- {
- prefs_set_string("size_info.x", NULL);
- prefs_set_string("size_info.y", NULL);
- }
-
- /* not_played_song renamed to not_played_track */
- if (prefs_get_int_value("not_played_song", &int_buf))
- {
- prefs_set_int("not_played_track", int_buf);
- prefs_set_string("not_played_song", NULL);
- }
-
- /* misc_song_nr renamed to misc_track_nr */
- if (prefs_get_int_value("misc_song_nr", &int_buf))
- {
- prefs_set_int("misc_track_nr", int_buf);
- prefs_set_string("misc_song_nr", NULL);
- }
-
- /* sm_autostore renamed to tm_autostore */
- if (prefs_get_int_value("sm_autostore", &int_buf))
- {
- prefs_set_int("tm_autostore", int_buf);
- prefs_set_string("sm_autostore", NULL);
- }
-
- /* sm_sortcol renamed to tm_sortcol */
- if (prefs_get_int_value("sm_sortcol", &int_buf))
- {
- prefs_set_int("tm_sortcol", int_buf);
- prefs_set_string("sm_sortcol", NULL);
- }
-
- /* sm_sort_ renamed to tm_sort */
- if (prefs_get_int_value("sm_sort_", &int_buf))
- {
- prefs_set_int("tm_sort", int_buf);
- prefs_set_string("sm_sort_", NULL);
- }
-
- /* filename_format renamed to export_template */
- if (prefs_get_string_value("filename_format", &buf))
- {
- prefs_set_string("export_template", buf);
- g_free(buf);
- prefs_set_string("filename_format", NULL);
- }
-
- /* This string was a wrong autoconvert--just ignore it */
- buf = prefs_get_string("export_template");
-
- if (buf && strcmp(buf, "%a - %a/%T - %T.mp3") == 0)
- prefs_set_string("export_template", NULL);
-
- g_free (buf);
-
- /* We changed the meaning of the %x in export_template */
- if (version < 0.72)
- {
- /* changed the meaning of the %x in export_template */
- if (sp) while (*sp)
- {
- if (sp[0] == '%')
- {
- switch (sp[1]) {
- case 'A':
- sp[1] = 'a';
- break;
- case 'd':
- sp[1] = 'A';
- break;
- case 'n':
- sp[1] = 't';
- break;
- case 't':
- sp[1] = 'T';
- break;
- default:
- break;
- }
- }
- }
- }
-
- /* For versions < 0.91, remove all itdb keys */
- if (version < 0.91)
- prefs_flush_subkey("itdb_");
-
- prefs_set_string ("version", VERSION);
-}
-
-/* Initialize the prefs table and read configuration */
-void prefs_init (int argc, char *argv[])
-{
- if (!prefs_table_mutex)
- prefs_table_mutex = g_mutex_new ();
-
- lock_prefs_table ();
-
- /* Create the prefs hash table */
- prefs_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
- g_free);
-
- unlock_prefs_table ();
-
- /* Load preferences */
- load_prefs();
-
- /* Clean up old prefs keys */
- cleanup_keys();
-
- /* Read environment variables */
- read_environment();
-
- /* Read commandline arguments */
- read_commandline(argc, argv);
-}
-
-/* Delete the hash table */
-void prefs_shutdown ()
-{
- lock_prefs_table ();
-
- if (!prefs_table)
- {
- unlock_prefs_table ();
- g_return_if_reached ();
- }
-
- /* Delete the prefs hash table */
- g_hash_table_destroy(prefs_table);
- prefs_table = NULL;
-
- unlock_prefs_table ();
-
- /* We can't free the prefs_table_mutex in a thread-safe way */
-}
-
-/* Create the temp prefs tree */
-/* Free the returned structure with delete_temp_prefs() */
-TempPrefs *temp_prefs_create ()
-{
- TempPrefs *temp_prefs; /* Returned temp prefs structure */
-
- temp_prefs = (TempPrefs*)g_malloc(sizeof(TempPrefs));
-
- temp_prefs->tree = g_tree_new_full((GCompareDataFunc)strcmp, NULL,
- g_free, g_free);
-
- return temp_prefs;
-}
-
-/* Delete temp prefs */
-void temp_prefs_destroy (TempPrefs *temp_prefs)
-{
- g_return_if_fail (temp_prefs);
- g_return_if_fail (temp_prefs->tree);
-
- g_tree_destroy(temp_prefs->tree);
- g_free(temp_prefs);
-}
-
-/* Copy key data from the temp prefs tree to the hash table */
-static gboolean copy_key (gpointer key, gpointer value, gpointer user_data)
-{
- prefs_set_string(key, value);
-
- return FALSE;
-}
-
-/* Copy the data from the temp prefs tree to the permanent prefs table */
-void temp_prefs_apply (TempPrefs *temp_prefs)
-{
- g_return_if_fail (temp_prefs);
- g_return_if_fail (temp_prefs->tree);
-
- g_tree_foreach (temp_prefs->tree, copy_key, NULL);
-}
-
-
-/* Create a temp_prefs tree containing a subset of keys in the
- permanent prefs table (those starting with @subkey */
-static TempPrefs *prefs_create_subset_unlocked (const gchar *subkey)
-{
- struct sub_data sub_data;
-
- g_return_val_if_fail (prefs_table, NULL);
-
- sub_data.temp_prefs = temp_prefs_create ();
- sub_data.subkey = subkey;
-
- g_hash_table_foreach (prefs_table, (GHFunc)get_subset, &sub_data);
-
- return sub_data.temp_prefs;
-}
-
-/* Create a temp_prefs tree containing a subset of keys in the
- permanent prefs table (those starting with @subkey */
-TempPrefs *prefs_create_subset (const gchar *subkey)
-{
- TempPrefs *temp_prefs;
-
- lock_prefs_table ();
-
- temp_prefs = prefs_create_subset_unlocked (subkey);
-
- unlock_prefs_table ();
-
- return temp_prefs;
-}
-
-
-/* Create a temp_prefs tree containing a subset of keys in the
- permanent prefs table (those starting with @subkey */
-TempPrefs *temp_prefs_create_subset (TempPrefs *temp_prefs,
- const gchar *subkey)
-{
- struct sub_data sub_data;
-
- g_return_val_if_fail (temp_prefs, NULL);
- g_return_val_if_fail (temp_prefs->tree, NULL);
-
- sub_data.temp_prefs = temp_prefs_create ();
- sub_data.subkey = subkey;
-
- g_tree_foreach (temp_prefs->tree, get_subset, &sub_data);
-
- return sub_data.temp_prefs;
-}
-
-
-/* Remove all keys in the temp prefs tree from the permanent prefs
- table */
-void temp_prefs_flush (TempPrefs *temp_prefs)
-{
- g_return_if_fail (temp_prefs);
- g_return_if_fail (temp_prefs->tree);
-
- lock_prefs_table ();
-
- g_tree_foreach (temp_prefs->tree, flush_key, NULL);
-
- unlock_prefs_table ();
-}
-
-/* Return the number of keys stored in @temp_prefs */
-gint temp_prefs_size (TempPrefs *temp_prefs)
-{
- g_return_val_if_fail (temp_prefs, 0);
- g_return_val_if_fail (temp_prefs->tree, 0);
-
- return g_tree_nnodes (temp_prefs->tree);
-}
-
-
-/* Returns TRUE if at least one key starting with @subkey exists */
-gboolean temp_prefs_subkey_exists (TempPrefs *temp_prefs,
- const gchar *subkey)
-{
- struct sub_data sub_data;
-
- g_return_val_if_fail (temp_prefs && subkey, FALSE);
-
- sub_data.temp_prefs = NULL;
- sub_data.subkey = subkey;
- sub_data.exists = FALSE;
-
- g_tree_foreach (temp_prefs->tree, check_subkey, &sub_data);
-
- return sub_data.exists;
-}
-
-
-/* Special functions */
-
-/* Remove all keys that start with @subkey */
-void prefs_flush_subkey (const gchar *subkey)
-{
- lock_prefs_table ();
-
- if (!prefs_table)
- {
- unlock_prefs_table ();
- g_return_if_reached ();
- }
-
- g_hash_table_foreach_remove (prefs_table, match_subkey, (gchar *)subkey);
-
- unlock_prefs_table ();
-}
-
-
-/* Rename all keys that start with @subkey_old in such a way that they
- start with @subkey_new */
-void prefs_rename_subkey (const gchar *subkey_old, const gchar *subkey_new){
- struct sub_data sub_data;
-
- g_return_if_fail (subkey_old);
- g_return_if_fail (subkey_new);
-
- lock_prefs_table ();
-
- if (!prefs_table)
- {
- unlock_prefs_table ();
- g_return_if_reached ();
- }
-
- sub_data.temp_prefs = prefs_create_subset_unlocked (subkey_old);
- sub_data.temp_prefs_orig = NULL;
-
- if (temp_prefs_size (sub_data.temp_prefs) > 0)
- {
- sub_data.subkey = subkey_old;
- sub_data.subkey2 = subkey_new;
- g_tree_foreach (sub_data.temp_prefs->tree, subst_key, &sub_data);
- }
-
- temp_prefs_destroy (sub_data.temp_prefs);
-
- unlock_prefs_table ();
-}
-
-
-/* Rename all keys that start with @subkey_old in such a way that they
- start with @subkey_new */
-void temp_prefs_rename_subkey (TempPrefs *temp_prefs,
- const gchar *subkey_old,
- const gchar *subkey_new)
-{
- struct sub_data sub_data;
-
- g_return_if_fail (temp_prefs);
- g_return_if_fail (subkey_old);
- g_return_if_fail (subkey_new);
-
- sub_data.temp_prefs_orig = temp_prefs;
- sub_data.temp_prefs = temp_prefs_create_subset (temp_prefs,
- subkey_old);
-
- if (temp_prefs_size (sub_data.temp_prefs) > 0)
- {
- sub_data.subkey = subkey_old;
- sub_data.subkey2 = subkey_new;
- g_tree_foreach (sub_data.temp_prefs->tree, subst_key, &sub_data);
- }
-
- temp_prefs_destroy (sub_data.temp_prefs);
-}
-
-/* Functions for non-numbered pref keys */
-
-/* Set a string value with the given key, or remove key if @value is
- NULL */
-void prefs_set_string(const gchar *key, const gchar *value)
-{
- g_return_if_fail (key);
-
- lock_prefs_table ();
-
- if (!prefs_table)
- {
- unlock_prefs_table ();
- g_return_if_reached ();
- }
-
- if (value)
- g_hash_table_insert (prefs_table,
- g_strdup(key), g_strdup(value));
- else
- g_hash_table_remove (prefs_table, key);
-
- unlock_prefs_table ();
-}
-
-/* Set a key value to a given integer */
-void prefs_set_int(const gchar *key, const gint value)
-{
- gchar *strvalue; /* String value converted from integer */
-
- lock_prefs_table ();
-
- if (!prefs_table)
- {
- unlock_prefs_table ();
- g_return_if_reached ();
- }
-
- strvalue = g_strdup_printf("%i", value);
- g_hash_table_insert(prefs_table, g_strdup(key), strvalue);
-
- unlock_prefs_table ();
-}
-
-/* Set a key to an int64 value */
-void prefs_set_int64(const gchar *key, const gint64 value)
-{
- gchar *strvalue; /* String value converted from int64 */
-
- lock_prefs_table ();
-
- if (!prefs_table)
- {
- unlock_prefs_table ();
- g_return_if_reached ();
- }
-
- strvalue = g_strdup_printf("%" G_GINT64_FORMAT, value);
- g_hash_table_insert(prefs_table, g_strdup(key), strvalue);
-
- unlock_prefs_table ();
-}
-
-void prefs_set_double(const gchar *key, gdouble value)
-{
- gchar *strvalue; /* String value converted from integer */
-
- lock_prefs_table ();
-
- if (!prefs_table)
- {
- unlock_prefs_table ();
- g_return_if_reached ();
- }
-
- strvalue = g_strdup_printf("%f", value);
- g_hash_table_insert(prefs_table, g_strdup(key), strvalue);
-
- unlock_prefs_table ();
-}
-
-/* Get a string value associated with a key. Free returned string. */
-gchar *prefs_get_string(const gchar *key)
-{
- gchar *string = NULL;
-
- lock_prefs_table ();
-
- g_return_val_if_fail (prefs_table, (unlock_prefs_table(), NULL));
-
- string = g_strdup(g_hash_table_lookup(prefs_table, key));
-
- unlock_prefs_table ();
-
- return string;
-}
-
-/* Use this if you need to know if the given key actually exists */
-/* The value parameter can be NULL if you don't need the value itself. */
-gboolean prefs_get_string_value(const gchar *key, gchar **value)
-{
- const gchar *string; /* String value from prefs table */
- gboolean valid = FALSE;
-
- lock_prefs_table ();
-
- g_return_val_if_fail (prefs_table, (unlock_prefs_table(), FALSE));
-
- string = g_hash_table_lookup(prefs_table, key);
-
- if (value)
- *value = g_strdup (string);
- if (string)
- valid = TRUE;
-
- unlock_prefs_table ();
-
- return valid;
-}
-
-/* Get an integer value from a key */
-gint prefs_get_int(const gchar *key)
-{
- gchar *string; /* Hash value string */
- gint value; /* Returned value */
-
- value = 0;
-
- lock_prefs_table ();
-
- g_return_val_if_fail (prefs_table, (unlock_prefs_table(), value));
-
- string = g_hash_table_lookup(prefs_table, key);
-
- if (string)
- value = atoi(string);
-
- unlock_prefs_table ();
-
- return value;
-}
-
-/* Use this if you need to know if the given key actually exists */
-/* The value parameter can be NULL if you don't need the value itself. */
-gboolean prefs_get_int_value(const gchar *key, gint *value)
-{
- gchar *string; /* String value from prefs table */
- gboolean valid = FALSE;
-
- lock_prefs_table ();
-
- g_return_val_if_fail (prefs_table, (unlock_prefs_table(), FALSE));
-
- string = g_hash_table_lookup(prefs_table, key);
-
- if (value)
- {
- if (string)
- *value = atoi(string);
- else
- *value = 0;
- }
-
- if (string)
- valid = TRUE;
-
- unlock_prefs_table ();
-
- return valid;
-}
-
-/* Get a 64 bit integer value from a key */
-gint64 prefs_get_int64(const gchar *key)
-{
- gchar *string; /* Key value string */
- gint64 value; /* Returned value */
-
- value = 0;
-
- lock_prefs_table ();
-
- g_return_val_if_fail (prefs_table, (unlock_prefs_table(), value));
-
- string = g_hash_table_lookup(prefs_table, key);
-
- if (string)
- value = g_ascii_strtoull(string, NULL, 10);
-
- unlock_prefs_table ();
-
- return value;
-}
-
-/* Get a 64 bit integer value from a key */
-/* Use this if you need to know if the given key actually exists */
-/* The value parameter can be NULL if you don't need the value itself. */
-gboolean prefs_get_int64_value(const gchar *key, gint64 *value)
-{
- gchar *string; /* String value from prefs table */
- gboolean valid = FALSE;
-
- lock_prefs_table ();
-
- g_return_val_if_fail (prefs_table, (unlock_prefs_table(), FALSE));
-
- string = g_hash_table_lookup(prefs_table, key);
-
- if (value)
- {
- if (string)
- *value = g_ascii_strtoull(string, NULL, 10);
- else
- *value = 0;
- }
-
- if (string)
- valid = TRUE;
-
- unlock_prefs_table ();
-
- return valid;
-}
-
-gdouble prefs_get_double(const gchar *key)
-{
- gchar *string; /* Key value string */
- gdouble value; /* Returned value */
-
- value = 0;
-
- lock_prefs_table ();
-
- g_return_val_if_fail (prefs_table, (unlock_prefs_table(), value));
-
- string = g_hash_table_lookup(prefs_table, key);
-
- if (string)
- value = g_ascii_strtod(string, NULL);
-
- unlock_prefs_table ();
-
- return value;
-}
-
-gboolean prefs_get_double_value(const gchar *key, gdouble *value)
-{
- gchar *string; /* String value from prefs table */
- gboolean valid = FALSE;
-
- lock_prefs_table ();
-
- g_return_val_if_fail (prefs_table, (unlock_prefs_table(), FALSE));
-
- string = g_hash_table_lookup(prefs_table, key);
-
- if (value)
- {
- if (string)
- *value = g_ascii_strtod(string, NULL);
- else
- *value = 0;
- }
-
- if (string)
- valid = TRUE;
-
- unlock_prefs_table ();
-
- return valid;
-}
-
-/* Functions for numbered pref keys */
-
-/* Set a string value with the given key */
-void prefs_set_string_index(const gchar *key, const guint index,
- const gchar *value)
-{
- gchar *full_key; /* Complete numbered key */
-
- full_key = create_full_key(key, index);
- prefs_set_string(full_key, value);
-
- g_free(full_key);
-}
-
-/* Set a key value to a given integer */
-void prefs_set_int_index(const gchar *key, const guint index,
- const gint value)
-{
- gchar *full_key; /* Complete numbered key */
-
- full_key = create_full_key(key, index);
- prefs_set_int(full_key, value);
-
- g_free(full_key);
-}
-
-/* Set a key to an int64 value */
-void prefs_set_int64_index(const gchar *key, const guint index,
- const gint64 value)
-{
- gchar *full_key; /* Complete numbered key */
-
- full_key = create_full_key(key, index);
- prefs_set_int64(full_key, value);
-
- g_free(full_key);
-}
-
-/* Set a key to a gdouble value */
-void prefs_set_double_index(const gchar *key, guint index,
- gdouble value)
-{
- gchar *full_key; /* Complete numbered key */
-
- full_key = create_full_key(key, index);
- prefs_set_double(full_key, value);
-
- g_free(full_key);
-}
-
-/* Get a string value associated with a key. Free returned string. */
-gchar *prefs_get_string_index(const gchar *key, const guint index)
-{
- gchar *full_key; /* Complete numbered key */
- gchar *string; /* Return string */
-
- full_key = create_full_key(key, index);
- string = prefs_get_string(full_key);
-
- g_free(full_key);
- return string;
-}
-
-/* Get a string value associated with a key. Free returned string. */
-/* Use this if you need to know if the given key actually exists */
-gboolean prefs_get_string_value_index(const gchar *key, const guint index,
- gchar **value)
-{
- gchar *full_key; /* Complete numbered key */
- gboolean ret; /* Return value */
-
- full_key = create_full_key(key, index);
- ret = prefs_get_string_value(full_key, value);
-
- g_free(full_key);
- return ret;
-}
-
-/* Get an integer value from a key */
-gint prefs_get_int_index(const gchar *key, const guint index)
-{
- gchar *full_key; /* Complete numbered key */
- gint value; /* Returned integer value */
-
- full_key = create_full_key(key, index);
- value = prefs_get_int(full_key);
-
- g_free(full_key);
- return value;
-}
-
-/* Get an integer value from a key */
-/* Use this if you need to know if the given key actually exists */
-gboolean prefs_get_int_value_index(const gchar *key, const guint index,
- gint *value)
-{
- gchar *full_key; /* Complete numbered key */
- gboolean ret; /* Return value */
-
- full_key = create_full_key(key, index);
- ret = prefs_get_int_value(full_key, value);
-
- g_free(full_key);
- return ret;
-}
-
-/* Get a 64 bit integer value from a key */
-gint64 prefs_get_int64_index(const gchar *key, const guint index)
-{
- gchar *full_key; /* Complete numbered key */
- gint64 value; /* Return value */
-
- full_key = create_full_key(key, index);
- value = prefs_get_int64(full_key);
-
- g_free(full_key);
- return value;
-}
-
-/* Get a 64 bit integer value from a key */
-/* Use this if you need to know if the given key actually exists */
-gboolean prefs_get_int64_value_index(const gchar *key, const guint index,
- gint64 *value)
-{
- gchar *full_key; /* Complete numbered key */
- gboolean ret; /* Return value */
-
- full_key = create_full_key(key, index);
- ret = prefs_get_int64_value(full_key, value);
-
- g_free(full_key);
- return ret;
-}
-
-gdouble prefs_get_double_index(const gchar *key, guint index)
-{
- gchar *full_key; /* Complete numbered key */
- gdouble value; /* Return value */
-
- full_key = create_full_key(key, index);
- value = prefs_get_double(full_key);
-
- g_free(full_key);
- return value;
-}
-
-gboolean prefs_get_double_value_index(const gchar *key, guint index,
- gdouble *value)
-{
- gchar *full_key; /* Complete numbered key */
- gboolean ret; /* Return value */
-
- full_key = create_full_key(key, index);
- ret = prefs_get_double_value(full_key, value);
-
- g_free(full_key);
- return ret;
-}
-
-/* Add string value with the given key to temp prefs. Note: use
- * temp_prefs_remove_key() to remove key from the temp prefs. Setting
- * it to NULL will not remove the key. It will instead remove the key
- * in the main prefs table when you call temp_prefs_apply(). */
-void temp_prefs_set_string (TempPrefs *temp_prefs, const gchar *key,
- const gchar *value)
-{
- g_return_if_fail (temp_prefs && temp_prefs->tree);
- g_return_if_fail (key);
-
- g_tree_insert (temp_prefs->tree, g_strdup(key), g_strdup(value));
-}
-
-/* Add string value with the given key to temp prefs. Remove the key
- * if @value is NULL. */
-void temp_prefs_remove_key (TempPrefs *temp_prefs, const gchar *key)
-{
- g_return_if_fail (temp_prefs && temp_prefs->tree);
- g_return_if_fail (key);
-
- g_tree_remove (temp_prefs->tree, key);
-}
-
-/* Add an integer value to temp prefs */
-void temp_prefs_set_int(TempPrefs *temp_prefs, const gchar *key,
- const gint value)
-{
- gchar *strvalue; /* String value converted from integer */
-
- g_return_if_fail (temp_prefs && temp_prefs->tree);
- g_return_if_fail (key);
-
- strvalue = g_strdup_printf("%i", value);
- g_tree_insert(temp_prefs->tree, g_strdup(key), strvalue);
-}
-
-/* Add an int64 to temp prefs */
-void temp_prefs_set_int64(TempPrefs *temp_prefs, const gchar *key,
- const gint64 value)
-{
- gchar *strvalue; /* String value converted from int64 */
-
- g_return_if_fail (temp_prefs && temp_prefs->tree);
- g_return_if_fail (key);
-
- strvalue = g_strdup_printf("%" G_GINT64_FORMAT, value);
- g_tree_insert(temp_prefs->tree, g_strdup(key), strvalue);
-}
-
-void temp_prefs_set_double(TempPrefs *temp_prefs, const gchar *key,
- gdouble value)
-{
- gchar *strvalue; /* String value converted from int64 */
-
- g_return_if_fail (temp_prefs && temp_prefs->tree);
- g_return_if_fail (key);
-
- strvalue = g_strdup_printf("%fu", value);
- g_tree_insert(temp_prefs->tree, g_strdup(key), strvalue);
-}
-
-/* Get a string value associated with a key. Free returned string. */
-gchar *temp_prefs_get_string(TempPrefs *temp_prefs, const gchar *key)
-{
- g_return_val_if_fail (temp_prefs && temp_prefs->tree, NULL);
- g_return_val_if_fail (key, NULL);
-
- return g_strdup (g_tree_lookup (temp_prefs->tree, key));
-}
-
-/* Use this if you need to know if the given key actually exists */
-/* The value parameter can be NULL if you don't need the value itself. */
-gboolean temp_prefs_get_string_value(TempPrefs *temp_prefs,
- const gchar *key, gchar **value)
-{
- gchar *string; /* String value from prefs table */
-
- g_return_val_if_fail (temp_prefs && temp_prefs->tree, FALSE);
- g_return_val_if_fail (key, FALSE);
-
- string = g_tree_lookup (temp_prefs->tree, key);
-
- if (value)
- *value = g_strdup (string);
-
- if (string)
- return TRUE;
- else
- return FALSE;
-}
-
-/* Get an integer value from a key */
-gint temp_prefs_get_int(TempPrefs *temp_prefs, const gchar *key)
-{
- gchar *string; /* Hash value string */
- gint value; /* Returned value */
-
- g_return_val_if_fail (temp_prefs && temp_prefs->tree, 0);
- g_return_val_if_fail (key, 0);
-
- value = 0;
-
- string = g_tree_lookup (temp_prefs->tree, key);
-
- if (string)
- value = atoi(string);
-
- return value;
-}
-
-/* Use this if you need to know if the given key actually exists */
-/* The value parameter can be NULL if you don't need the value itself. */
-gboolean temp_prefs_get_int_value(TempPrefs *temp_prefs,
- const gchar *key, gint *value)
-{
- gchar *string; /* String value from prefs table */
-
- g_return_val_if_fail (temp_prefs && temp_prefs->tree, FALSE);
- g_return_val_if_fail (key, FALSE);
-
- string = g_tree_lookup (temp_prefs->tree, key);
-
- if (value)
- {
- if (string)
- *value = atoi(string);
- else
- *value = 0;
- }
-
- if (string)
- return TRUE;
- else
- return FALSE;
-}
-
-gdouble temp_prefs_get_double(TempPrefs *temp_prefs,
- const gchar *key)
-{
- gchar *string; /* Hash value string */
- gdouble value; /* Returned value */
-
- g_return_val_if_fail (temp_prefs && temp_prefs->tree, 0);
- g_return_val_if_fail (key, 0);
-
- value = 0.0f;
-
- string = g_tree_lookup (temp_prefs->tree, key);
-
- if (string)
- value = g_ascii_strtod(string, NULL);
-
- return value;
-}
-
-gboolean temp_prefs_get_double_value(TempPrefs *temp_prefs,
- const gchar *key, gdouble *value)
-{
- gchar *string; /* String value from prefs table */
-
- g_return_val_if_fail (temp_prefs && temp_prefs->tree, FALSE);
- g_return_val_if_fail (key, FALSE);
-
- string = g_tree_lookup (temp_prefs->tree, key);
-
- if (value)
- {
- if (string)
- *value = g_ascii_strtod(string, NULL);
- else
- *value = 0;
- }
-
- if (string)
- return TRUE;
- else
- return FALSE;
-}
-
-/* Functions for numbered pref keys */
-
-/* Set a string value with the given key */
-void temp_prefs_set_string_index(TempPrefs *temp_prefs, const gchar *key,
- const guint index, const gchar *value)
-{
- gchar *full_key; /* Complete numbered key */
-
- g_return_if_fail (temp_prefs && temp_prefs->tree);
- g_return_if_fail (key);
-
- full_key = create_full_key(key, index);
- temp_prefs_set_string(temp_prefs, full_key, value);
-
- g_free(full_key);
-}
-
-/* Set a key value to a given integer */
-void temp_prefs_set_int_index(TempPrefs *temp_prefs, const gchar *key,
- const guint index, const gint value)
-{
- gchar *full_key; /* Complete numbered key */
-
- g_return_if_fail (temp_prefs && temp_prefs->tree);
- g_return_if_fail (key);
-
- full_key = create_full_key(key, index);
- temp_prefs_set_int(temp_prefs, full_key, value);
-
- g_free(full_key);
-}
-
-/* Set a key to an int64 value */
-void temp_prefs_set_int64_index(TempPrefs *temp_prefs, const gchar *key,
- const guint index, const gint64 value)
-{
- gchar *full_key; /* Complete numbered key */
-
- g_return_if_fail (temp_prefs && temp_prefs->tree);
- g_return_if_fail (key);
-
- full_key = create_full_key(key, index);
- temp_prefs_set_int64(temp_prefs, full_key, value);
-
- g_free(full_key);
-}
-
-/* Functions for variable-length lists */
-
-/* Create a tree that contains lists that need to be rebuilt */
-/* Free the returned structure with destroy_temp_lists */
-TempLists *temp_lists_create()
-{
- TempLists *temp_lists; /* Allocated temp list structure */
-
- temp_lists = (TempLists*)g_malloc(sizeof(TempLists));
-
-
- temp_lists->tree = g_tree_new_full((GCompareDataFunc)strcmp, NULL,
- g_free,
- (GDestroyNotify)prefs_free_list);
- return temp_lists;
-}
-
-/* Destroys the list tree */
-void temp_lists_destroy(TempLists *temp_lists)
-{
- if (temp_lists)
- {
- if (temp_lists->tree)
- g_tree_destroy(temp_lists->tree);
-
- g_free(temp_lists);
- }
-}
-
-/* Add a list with the given key prefix to a temp list tree */
-void temp_list_add(TempLists *temp_lists, const gchar *key, GList *list)
-{
- if (temp_lists)
- {
- if (temp_lists->tree)
- g_tree_insert(temp_lists->tree, g_strdup(key), list);
- }
-}
-
-/* Copy the items of the lists in the given tree to the prefs table */
-void temp_lists_apply(TempLists *temp_lists)
-{
- if (temp_lists)
- {
- if (temp_lists->tree)
- g_tree_foreach(temp_lists->tree, copy_list, NULL);
- }
-}
-
-/* Copy one list to the prefs table. Useful for lists not changed by a window */
-void prefs_apply_list(gchar *key, GList *list)
-{
- GList *node; /* Current list node */
- guint i; /* Counter */
-
- i = 0;
-
- if (prefs_table)
- {
- /* Clean the existing list */
- wipe_list(key);
-
- node = list;
-
- /* Add the new list items to the table */
- while (node)
- {
- g_hash_table_insert(prefs_table, create_full_key(key, i),
- g_strdup(node->data));
-
- node = g_list_next(node);
- i++;
- }
-
- /* Add the end marker */
- g_hash_table_insert(prefs_table, create_full_key(key, i),
- g_strdup(LIST_END_MARKER));
- }
-}
-
-/* Get the items in a variable-length list from the prefs table */
-GList *prefs_get_list(const gchar *key)
-{
- guint end_marker_hash; /* Hash value of the list end marker */
- guint item_hash; /* Hash value of current list string */
- gchar *item_string; /* List item string */
- guint i; /* Counter */
- GList *list; /* List that contains items */
-
- /* Go through each key in the table until we find the end marker */
- end_marker_hash = g_str_hash(LIST_END_MARKER);
- list = NULL;
-
- for (i = 0;;i++)
- {
- item_string = prefs_get_string_index(key, i);
-
- if (item_string)
- {
- item_hash = g_str_hash(item_string);
-
- if (item_hash != end_marker_hash)
- {
- list = g_list_append(list, item_string);
- continue;
- }
- else
- {
- g_free(item_string);
- break;
- }
- }
- }
-
- return list;
-}
-
-/* Free a list and its strings */
-void prefs_free_list(GList *list)
-{
- GList *node; /* Current list node */
-
- node = list;
-
- /* Go through the list, freeing the strings */
-
- while (node)
- {
- if (node->data)
- g_free(node->data);
-
- node = g_list_next(node);
- }
-
- g_list_free(list);
-}
-
-/* Creates a list from lines in a GtkTextBuffer. Free the list when done. */
-GList *get_list_from_buffer(GtkTextBuffer *buffer)
-{
- GtkTextIter start_iter; /* Start of buffer text */
- GtkTextIter end_iter; /* End of buffer text */
- gchar *text_buffer; /* Raw text buffer */
- gchar **string_array; /* Contains each line of the buffer */
- gchar **string_iter; /* Pointer for iterating through the string vector */
- GList *list; /* List that contains each string */
-
- list = NULL;
-
- /* Grab the text from the buffer, and then split it up by lines */
- gtk_text_buffer_get_start_iter(buffer, &start_iter);
- gtk_text_buffer_get_end_iter(buffer, &end_iter);
-
- text_buffer = gtk_text_buffer_get_text(buffer, &start_iter, &end_iter, FALSE);
- string_array = g_strsplit(text_buffer, "\n", -1);
- string_iter = string_array;
-
- /* Go through each string and put it in the list */
- while (*string_iter)
- {
- if (strlen(*string_iter) != 0)
- list = g_list_append(list, g_strdup(*string_iter));
-
- string_iter++;
- }
-
- return list;
-}
Copied: gtkpod/tags/0.99.10-5/src/prefs.c (from rev 268, gtkpod/trunk/src/prefs.c)
===================================================================
--- gtkpod/tags/0.99.10-5/src/prefs.c (rev 0)
+++ gtkpod/tags/0.99.10-5/src/prefs.c 2007-11-20 13:46:35 UTC (rev 280)
@@ -0,0 +1,2281 @@
+/*
+| Copyright (C) 2002-2007 Jorg Schuler <jcsjcs at users sourceforge net>
+| Copyright (C) 2006 James Liggett <jrliggett at cox.net>
+| Part of the gtkpod project.
+|
+| URL: http://www.gtkpod.org/
+| URL: http://gtkpod.sourceforge.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
+|
+| iTunes and iPod are trademarks of Apple
+|
+| This product is not supported/written/published by Apple!
+|
+| $Id: prefs.c 1597 2007-06-26 14:35:18Z dforsi $
+*/
+
+/* -------------------------------------------------------------------
+ *
+ * HOWTO add a new_option to the prefs dialog
+ *
+ * - add the desired option to the prefs window using glade-2
+ *
+ * - set the default value of new_option in set_default_preferences() in prefs.c
+ *
+ * - add a callback on_new_option_*() to prefs_windows.c to set the
+ * new value.
+ * The value is applied to the actual prefs when pressing the "OK"
+ * or "Apply" button in the prefs window.
+ *
+ * - add code to prefs_window_create() in prefs_window.c to set the
+ * correct state of the option in the prefs window.
+ *
+ * - if you want new_option to be a command line option as well, add
+ * code to usage() and read_commandline().
+ *
+ * - for environment variables, add code to read_environment().
+ *
+ * ---------------------------------------------------------------- */
+
+/* ----------------------------------------------------------------
+ *
+ * The prefs module should be thread safe. The hash table is locked
+ * before each read or write access.
+ *
+ * The temp_prefs module is not thread-safe. If necessary a locking
+ * mechanism can be implemented.
+ *
+ * ---------------------------------------------------------------- */
+
+
+
+
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
+ Ditto for AIX 3.2 and <stdlib.h>. */
+#ifndef _NO_PROTO
+# define _NO_PROTO
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <glib/gstdio.h>
+#ifdef HAVE_GETOPT_LONG_ONLY
+# include <getopt.h>
+#else
+# include "getopt.h"
+#endif
+
+#include "clientserver.h"
+#include "misc.h"
+#include "prefs.h"
+
+/*
+ * Data global to this module only
+ */
+
+/* End-of-list marker for variable-length lists */
+#define LIST_END_MARKER "----++++----"
+
+struct temp_prefs_save
+{
+ GIOChannel *gio;
+ GError **error;
+ gboolean success;
+};
+
+struct sub_data
+{
+ TempPrefs *temp_prefs;
+ TempPrefs *temp_prefs_orig;
+ const gchar *subkey;
+ const gchar *subkey2;
+ gboolean exists;
+};
+
+/* Pointer to preferences hash table */
+static GHashTable *prefs_table = NULL;
+static GMutex *prefs_table_mutex = NULL;
+
+/*
+ * Functions used by this module only
+ */
+void discard_prefs (void);
+
+/* Different paths that can be set in the prefs window */
+typedef enum
+{
+ PATH_PLAY_NOW = 0,
+ PATH_PLAY_ENQUEUE,
+ PATH_MP3GAIN,
+ PATH_SYNC_CONTACTS,
+ PATH_SYNC_CALENDAR,
+ PATH_MSERV_MUSIC_ROOT,
+ PATH_MSERV_TRACKINFO_ROOT,
+ PATH_SYNC_NOTES,
+ PATH_AACGAIN,
+ PATH_NUM
+} PathType;
+
+/* enum for reading of options */
+enum {
+ GP_HELP,
+ GP_PLAYCOUNT,
+ GP_MOUNT,
+ GP_PRINT_HASH,
+};
+
+
+/* Lock the prefs table. If the table is already locked the calling
+ * thread will remain blocked until the lock is released by the other thread. */
+static void lock_prefs_table ()
+{
+ g_return_if_fail (prefs_table_mutex);
+ g_mutex_lock (prefs_table_mutex);
+}
+
+/* Unlock the prefs table again. */
+static void unlock_prefs_table ()
+{
+ g_return_if_fail (prefs_table_mutex);
+ g_mutex_unlock (prefs_table_mutex);
+}
+
+
+/* Set default preferences */
+static void set_default_preferences()
+{
+ int i;
+ gchar *str;
+
+ prefs_set_int("update_existing", FALSE);
+ prefs_set_int("id3_write", FALSE);
+ prefs_set_int("id3_write_id3v24", FALSE);
+ prefs_set_int(KEY_SYNC_DELETE_TRACKS, TRUE);
+ prefs_set_int(KEY_SYNC_CONFIRM_DELETE, TRUE);
+ prefs_set_int(KEY_SYNC_SHOW_SUMMARY, TRUE);
+ prefs_set_int("show_duplicates", TRUE);
+ prefs_set_int("show_non_updated", TRUE);
+ prefs_set_int("show_updated", TRUE);
+ prefs_set_int("mserv_report_probs", TRUE);
+ prefs_set_int("delete_ipod", TRUE);
+ prefs_set_int("delete_file", TRUE);
+ prefs_set_int("delete_local_file", TRUE);
+ prefs_set_int("delete_database", TRUE);
+ prefs_set_string("initial_mountpoint", "/mnt/ipod");
+ prefs_set_string ("path_play_now", "xmms %s");
+ prefs_set_string ("path_play_enqueue", "xmms -e %s");
+ prefs_set_string ("path_mserv_trackinfo_root", "/var/lib/mserv/trackinfo/");
+
+ str = g_build_filename (SCRIPTDIR, "convert-ogg2mp3.sh", NULL);
+ prefs_set_string ("path_conv_ogg", str);
+ g_free (str);
+ prefs_set_int ("convert_ogg", TRUE);
+
+ str = g_build_filename (SCRIPTDIR, "convert-flac2mp3.sh", NULL);
+ prefs_set_string ("path_conv_flac", str);
+ g_free (str);
+ prefs_set_int ("convert_flac", TRUE);
+
+ str = g_build_filename (SCRIPTDIR, "convert-wav2mp3.sh", NULL);
+ prefs_set_string ("path_conv_wav", str);
+ g_free (str);
+ prefs_set_int ("convert_wav", FALSE);
+
+
+ /* Set sorting tab defaults */
+ for (i = 0; i < SORT_TAB_MAX; i++)
+ {
+ prefs_set_int_index("st_autoselect", i, TRUE);
+ prefs_set_int_index("st_category", i, (i < ST_CAT_NUM ? i : 0));
+ prefs_set_int_index("sp_or", i, FALSE);
+ prefs_set_int_index("sp_rating_cond", i, FALSE);
+ prefs_set_int_index("sp_playcount_cond", i, FALSE);
+ prefs_set_int_index("sp_played_cond", i, FALSE);
+ prefs_set_int_index("sp_modified_cond", i, FALSE);
+ prefs_set_int_index("sp_added_cond", i, FALSE);
+ prefs_set_int_index("sp_rating_state", i, 0);
+ prefs_set_string_index("sp_played_state", i, ">4w");
+ prefs_set_string_index("sp_modified_state", i, "<1d");
+ prefs_set_string_index("sp_added_state", i, "<1d");
+ prefs_set_int_index("sp_playcount_low", i, 0);
+ prefs_set_int_index("sp_playcount_high", i, -1);
+ prefs_set_int_index("sp_autodisplay", i, FALSE);
+ }
+
+ prefs_set_int("sort_tab_num", 2);
+
+ /* Set colum preferences */
+ for (i = 0; i < TM_NUM_COLUMNS; i++)
+ {
+ prefs_set_int_index("tm_col_width", i, 80);
+ prefs_set_int_index("col_visible", i, FALSE);
+ prefs_set_int_index("col_order", i, i);
+ }
+
+ for (i = 0; i < TM_NUM_TAGS_PREFS; i++)
+ prefs_set_int_index("tag_autoset", i, FALSE);
+
+ prefs_set_int_index("tag_autoset", TM_COLUMN_TITLE, TRUE);
+
+ prefs_set_int_index("col_visible", TM_COLUMN_ARTIST, TRUE);
+ prefs_set_int_index("col_visible", TM_COLUMN_ALBUM, TRUE);
+ prefs_set_int_index("col_visible", TM_COLUMN_TITLE, TRUE);
+ prefs_set_int_index("col_visible", TM_COLUMN_GENRE, TRUE);
+ prefs_set_int_index("col_visible", TM_COLUMN_PLAYCOUNT, TRUE);
+ prefs_set_int_index("col_visible", TM_COLUMN_RATING, TRUE);
+
+ /* Set pane positions--Let gtk worry about position */
+ for (i = 0; i < PANED_NUM; i++)
+ prefs_set_int_index("paned_pos_", i, -1);
+
+ prefs_set_int("mpl_autoselect", TRUE);
+
+ /* Set window sizes */
+ prefs_set_int("size_gtkpod.x", 600);
+ prefs_set_int("size_gtkpod.y", 500);
+ prefs_set_int("size_cal.x", 500);
+ prefs_set_int("size_cal.y", 300);
+ prefs_set_int("size_conf_sw.x", 300);
+ prefs_set_int("size_conf_sw.y", 300);
+ prefs_set_int("size_conf.x", 300);
+ prefs_set_int("size_conf.y", -1);
+ prefs_set_int("size_dirbr.x", 300);
+ prefs_set_int("size_dirbr.y", 400);
+ prefs_set_int("size_prefs.x", -1);
+ prefs_set_int("size_prefs.y", 480);
+ prefs_set_int("size_info.x", 510);
+ prefs_set_int("size_info.y", 300);
+
+ /* size of file dialog if there is not a details textview */
+ prefs_set_int("size_file_dialog.x", 320);
+ prefs_set_int("size_file_dialog.y", 140);
+
+ /* size of file dialog if there is a details textview */
+ prefs_set_int("size_file_dialog_details.x", 320);
+ prefs_set_int("size_file_dialog_details.y", 140);
+
+ prefs_set_int("readtags", TRUE);
+ prefs_set_int("write_extended_info", TRUE);
+ prefs_set_int("parsetags", FALSE);
+ prefs_set_int("parsetags_overwrite", FALSE);
+ prefs_set_string("parsetags_template", "%a - %A/%T %t.mp3;%t.wav");
+ prefs_set_int("coverart_apic", TRUE);
+ prefs_set_int("coverart_file", TRUE);
+ prefs_set_string("coverart_template", "%A;folder.jpg");
+ prefs_set_int("mserv_use", FALSE);
+ prefs_set_string("mserv_username", "");
+ prefs_set_int("startup_messages", TRUE);
+ prefs_set_int("add_recursively", TRUE);
+ prefs_set_int("info_window", FALSE);
+ prefs_set_int("last_prefs_page", 0);
+ prefs_set_int("multi_edit_title", TRUE);
+ prefs_set_int("multi_edit", FALSE);
+ prefs_set_int("not_played_track", TRUE);
+ prefs_set_int("misc_track_nr", 25);
+ prefs_set_int("update_charset", FALSE);
+ prefs_set_int("display_tooltips_main", TRUE);
+ prefs_set_int("display_tooltips_prefs", TRUE);
+ prefs_set_int("display_toolbar", TRUE);
+ prefs_set_int("toolbar_style", GTK_TOOLBAR_BOTH);
+ prefs_set_int("sha1", TRUE);
+ prefs_set_string("export_template", "%o;%a - %t.mp3;%t.wav");
+ prefs_set_int("file_dialog_details_expanded", FALSE);
+
+ /* Set last browsed directory */
+ str = g_get_current_dir();
+
+ if (str)
+ {
+ prefs_set_string("last_dir_browsed", str);
+ g_free(str);
+ }
+ else
+ prefs_set_string("last_dir_browsed", g_get_home_dir());
+
+ /* Set sorting prefs */
+ prefs_set_int("case_sensitive", FALSE);
+ prefs_set_int("tm_autostore", FALSE);
+ prefs_set_int("st_sort", SORT_NONE);
+ prefs_set_int("pm_sort", SORT_NONE);
+ prefs_set_int("tm_sortcol", TM_COLUMN_TITLE);
+ prefs_set_int("tm_sort", SORT_NONE);
+}
+
+/* Initialize default variable-length list entries */
+static void set_default_list_entries()
+{
+ if (!prefs_get_string_value_index("sort_ign_string_", 0, NULL))
+ {
+ prefs_set_string_index("sort_ign_string_", 0, "a ");
+ prefs_set_string_index("sort_ign_string_", 1, "an ");
+ prefs_set_string_index("sort_ign_string_", 2, LIST_END_MARKER);
+ }
+}
+
+/* A printf-like function that outputs in the system locale */
+static void locale_fprintf(FILE *fp, const gchar *format, ...)
+{
+ gchar *utf8_string; /* Raw UTF-8 string */
+ gchar *locale_string; /* String in system locale format */
+ va_list format_list; /* Printf-like formatting arguments */
+
+ /* Create the locale format string based on the given format */
+ va_start(format_list, format);
+ utf8_string = g_strdup_vprintf(format, format_list);
+ va_end(format_list);
+
+ locale_string = g_locale_from_utf8 (utf8_string, -1, NULL, NULL, NULL);
+
+ if (fp)
+ fprintf(fp, "%s", locale_string);
+
+ g_free(utf8_string);
+ g_free(locale_string);
+}
+
+/* Print commandline usage information */
+static void usage(FILE *fp)
+{
+ locale_fprintf(fp, _("gtkpod version %s usage:\n"), VERSION);
+ locale_fprintf(fp, _(" -h, --help: display this message\n"));
+ locale_fprintf(fp, _(" -p <file>: increment playcount for file by one\n"));
+ locale_fprintf(fp, _(" --hash <file>:print gtkpod hash for file\n"));
+ locale_fprintf(fp, _(" -m path: define the mountpoint of your iPod\n"));
+ locale_fprintf(fp, _(" --mountpoint: same as '-m'.\n"));
+ locale_fprintf(fp, _(" -a: import database automatically after start.\n"));
+ locale_fprintf(fp, _(" --auto: same as '-a'.\n"));
+}
+
+/* Parse commandline based options */
+static void read_commandline(int argc, char *argv[])
+{
+ int option; /* Code returned by getopt */
+
+ /* The options data structure. The format is standard getopt. */
+ struct option const options[] =
+ {
+ { "h", no_argument, NULL, GP_HELP },
+ { "help", no_argument, NULL, GP_HELP },
+ { "p", required_argument, NULL, GP_PLAYCOUNT },
+ { "hash", required_argument, NULL, GP_PRINT_HASH },
+ { "m", required_argument, NULL, GP_MOUNT },
+ { "mountpoint", required_argument, NULL, GP_MOUNT },
+ { 0, 0, 0, 0 }
+ };
+
+ /* Handle commandline options */
+ while ((option = getopt_long_only(argc, argv, "", options, NULL)) != -1)
+ {
+ switch (option)
+ {
+ case GP_HELP:
+ usage(stdout);
+ exit(0);
+ break;
+ case GP_PLAYCOUNT:
+ client_playcount(optarg);
+ exit(0);
+ break;
+ case GP_PRINT_HASH:
+ print_sha1_hash (optarg);
+ exit(0);
+ break;
+ case GP_MOUNT:
+ prefs_set_string("initial_mountpoint", optarg);
+ break;
+ default:
+ locale_fprintf(stderr, "Unknown option: %s\n", argv[optind]);
+ usage(stderr);
+ exit(1);
+ break;
+ };
+ }
+}
+
+/* Read options from environment variables */
+static void read_environment()
+{
+ gchar *buf;
+
+ buf = convert_filename(getenv("IPOD_MOUNTPOINT"));
+ if (buf)
+ prefs_set_string("initial_mountpoint", buf);
+ g_free(buf);
+}
+
+/* Create a full numbered key from a base key string and a number.
+ * Free returned string. */
+static gchar *create_full_key(const gchar *base_key, gint index)
+{
+ if (base_key)
+ return g_strdup_printf("%s%i", base_key, index);
+ else
+ return NULL;
+}
+
+/* Remove key present in the temp prefs tree from the hash table */
+static gboolean flush_key (gpointer key, gpointer value, gpointer user_data)
+{
+ g_return_val_if_fail (prefs_table, FALSE);
+
+ g_hash_table_remove (prefs_table, key);
+
+ return FALSE;
+}
+
+
+/* Copy key data from the temp prefs tree to the hash table (or to
+ * sub_data->temp_prefs_orig if non-NULL). The old key is removed. */
+static gboolean subst_key (gpointer key, gpointer value, gpointer user_data)
+{
+ struct sub_data *sub_data = user_data;
+ gint len;
+
+ g_return_val_if_fail (key && value && user_data, FALSE);
+ g_return_val_if_fail (sub_data->subkey && sub_data->subkey2, FALSE);
+ if (!sub_data->temp_prefs_orig)
+ g_return_val_if_fail (prefs_table, FALSE);
+ if (sub_data->temp_prefs_orig)
+ g_return_val_if_fail (sub_data->temp_prefs_orig->tree, FALSE);
+
+ len = strlen (sub_data->subkey);
+
+ if (strncmp (key, sub_data->subkey, len) == 0)
+ {
+ gchar *new_key = g_strdup_printf ("%s%s",
+ sub_data->subkey2,
+ ((gchar *)key)+len);
+ if (sub_data->temp_prefs_orig)
+ {
+ g_tree_remove (sub_data->temp_prefs_orig->tree, key);
+ g_tree_insert (sub_data->temp_prefs_orig->tree,
+ new_key, g_strdup(value));
+ }
+ else
+ {
+ g_hash_table_remove (prefs_table, key);
+ g_hash_table_insert (prefs_table, new_key, g_strdup(value));
+ }
+ }
+ return FALSE;
+}
+
+/* return TRUE if @key starts with @subkey */
+static gboolean match_subkey (gpointer key, gpointer value, gpointer subkey)
+{
+ g_return_val_if_fail (key && subkey, FALSE);
+
+ if (strncmp (key, subkey, strlen (subkey)) == 0) return TRUE;
+ return FALSE;
+}
+
+
+/* return TRUE and set sub_data->exists to TRUE if @key starts with
+ * @subkey */
+static gboolean check_subkey (gpointer key, gpointer value, gpointer user_data)
+{
+ struct sub_data *sub_data = user_data;
+
+ g_return_val_if_fail (key && user_data, TRUE);
+ g_return_val_if_fail (sub_data->subkey, TRUE);
+
+ if (strncmp (key, sub_data->subkey, strlen (sub_data->subkey)) == 0)
+ {
+ sub_data->exists = TRUE;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+
+/* Add key/value to temp_prefs if it matches subkey -- called by
+ * prefs_create_subset() and temp_prefs_create_subset() */
+static gboolean get_subset (gpointer key, gpointer value, gpointer user_data)
+{
+ struct sub_data *sub_data = user_data;
+
+ g_return_val_if_fail (key && value && user_data, TRUE);
+ g_return_val_if_fail (sub_data->subkey && sub_data->temp_prefs, TRUE);
+
+ if (strncmp (key, sub_data->subkey,
+ strlen (sub_data->subkey)) == 0)
+ { /* match */
+ temp_prefs_set_string (sub_data->temp_prefs, key, value);
+ }
+ return FALSE; /* continue traversal (g_tree), ignored for g_hash */
+}
+
+
+/* Copy a variable-length list to the prefs table */
+static gboolean copy_list(gpointer key, gpointer value, gpointer user_data)
+{
+ prefs_apply_list((gchar*)key, (GList*)value);
+ return FALSE;
+}
+
+/* Callback that writes pref table data to a file */
+static void write_key(gpointer key, gpointer value, gpointer user_data)
+{
+ FILE *fp; /* file pointer passed in through user_data */
+
+ /* Write out each key and value to the given file */
+ fp = (FILE*)user_data;
+
+ if (fp)
+ fprintf(fp, "%s=%s\n", (gchar*)key, (gchar*)value);
+}
+
+/* Gets a string that contains ~/.gtkpod/ If the folder doesn't exist,
+ * create it. Free the string when you are done with it.
+ * If the folder wasn't found, and couldn't be created, return NULL */
+gchar *prefs_get_cfgdir()
+{
+ gchar *folder; /* Folder path */
+
+ /* Create the folder path. If the folder doesn't exist, create it. */
+ folder = g_build_filename(g_get_home_dir(), ".gtkpod", NULL);
+
+ if (!g_file_test(folder, G_FILE_TEST_IS_DIR))
+ {
+ if ((g_mkdir(folder, 0777)) == -1)
+ {
+ printf(_("Couldn't create ~/.gtkpod\n"));
+ return NULL;
+ }
+ }
+
+ return folder;
+}
+
+
+/* get @key and @value from a string like "key=value" */
+static gboolean read_prefs_get_key_value (const gchar *buf,
+ gchar **key, gchar **value)
+{
+ size_t len; /* string length */
+ const gchar *buf_start; /* Pointer to where actual useful data starts in line */
+
+ g_return_val_if_fail (buf && key && value, FALSE);
+
+ /* Strip out any comments (lines that begin with ; or #) */
+ if ((buf[0] == ';') || (buf[0] == '#'))
+ return FALSE;
+
+ /* Find the key and value, and look for malformed lines */
+ buf_start = strchr (buf, '=');
+
+ if ((!buf_start) || (buf_start == buf))
+ {
+ printf("Parse error reading prefs: %s", buf);
+ return FALSE;
+ }
+
+ /* Find the key name */
+ *key = g_strndup (buf, (buf_start - buf));
+
+ /* Strip whitespace */
+ g_strstrip (*key);
+
+ /* Find the value string */
+ *value = strdup (buf_start+1);
+
+ /* remove newline */
+ len = strlen (*value);
+ if ((len > 0) && ((*value)[len - 1] == 0x0a))
+ (*value)[len - 1] = 0;
+
+ /* Don't strip whitespace! If there is any, there's a reason for it. */
+ /* g_strstrip (*value); */
+
+ return TRUE;
+}
+
+
+/* Read preferences from a file */
+static void read_prefs_from_file(FILE *fp)
+{
+ gchar buf[PATH_MAX]; /* Buffer that contains one line */
+ gchar *key; /* Pref value key */
+ gchar *value; /* Pref value */
+
+
+ g_return_if_fail (prefs_table && fp);
+
+ while (fgets(buf, PATH_MAX, fp))
+ {
+ if (read_prefs_get_key_value (buf, &key, &value))
+ {
+ g_hash_table_insert (prefs_table, key, value);
+ }
+ }
+}
+
+/* Write prefs to file */
+static void write_prefs_to_file(FILE *fp)
+{
+ lock_prefs_table ();
+
+ if (!prefs_table)
+ {
+ unlock_prefs_table ();
+ g_return_if_reached ();
+ }
+
+ g_hash_table_foreach(prefs_table, write_key, (gpointer)fp);
+
+ unlock_prefs_table ();
+}
+
+/* Load preferences, first loading the defaults, and then overwrite that with
+ * preferences in the user home folder. */
+static void load_prefs()
+{
+ gchar *filename; /* Config path to open */
+ gchar *config_dir; /* Directory where config is (usually ~/.gtkpod) */
+ FILE *fp;
+
+ /* Start by initializing the prefs to their default values */
+ set_default_preferences();
+
+ /* and then override those values with those found in the home folder. */
+ config_dir = prefs_get_cfgdir();
+
+ if (config_dir)
+ {
+ filename = g_build_filename(config_dir, "prefs", NULL);
+
+ if (filename)
+ {
+ fp = fopen(filename, "r");
+
+ if (fp)
+ {
+ read_prefs_from_file(fp);
+ fclose(fp);
+ }
+
+ g_free(filename);
+ }
+
+ g_free(config_dir);
+ }
+
+ /* Finally, initialize variable-length lists. Do this after everything else
+ * so that list defaults don't hang out in the table after prefs have been
+ * read from the file. */
+ set_default_list_entries();
+}
+
+/* Save preferences to user home folder (~/.gtkpod/prefs) */
+void prefs_save ()
+{
+ gchar *filename; /* Path of file to write to */
+ gchar *config_dir; /* Folder where prefs file is */
+ FILE *fp; /* File pointer */
+
+ /* Open $HOME/.gtkpod/prefs, and write prefs */
+ config_dir = prefs_get_cfgdir();
+
+ if (config_dir)
+ {
+ filename = g_build_filename(config_dir, "prefs", NULL);
+
+ if (filename)
+ {
+ fp = fopen(filename, "w");
+
+ if (fp)
+ {
+ write_prefs_to_file(fp);
+ fclose(fp);
+ }
+
+ g_free(filename);
+ }
+
+ g_free(config_dir);
+ }
+}
+
+
+static gboolean temp_prefs_save_fe (gchar *key, gchar *value,
+ struct temp_prefs_save *tps)
+{
+ gchar *buf;
+ GIOStatus status;
+
+ buf=g_strdup_printf ("%s=%s\n", key, value);
+ status = g_io_channel_write_chars (tps->gio, buf, -1, NULL, tps->error);
+ g_free (buf);
+ if (status != G_IO_STATUS_NORMAL)
+ {
+ tps->success = FALSE;
+ return TRUE; /* stop traversal */
+ }
+ return FALSE;
+}
+
+
+/* Save @temp_prefs to @filename in the same manner as prefs_save is
+ * saving to ~/.gtkpod/prefs. @error: location where to store
+ * information about errors or NULL.
+ *
+ * Return value: TRUE on success, FALSE if an error occured, in which
+ * case @error will be set accordingly.
+ */
+gboolean temp_prefs_save (TempPrefs *temp_prefs,
+ const gchar *filename,
+ GError **error)
+{
+ GIOChannel *gio;
+ struct temp_prefs_save tps;
+
+ g_return_val_if_fail (temp_prefs && filename, FALSE);
+
+ gio = g_io_channel_new_file (filename, "w", error);
+ tps.gio = gio;
+ tps.error = error;
+ tps.success = TRUE;
+ if (gio)
+ {
+ g_tree_foreach (temp_prefs->tree, (GTraverseFunc)temp_prefs_save_fe, &tps);
+ g_io_channel_unref (gio);
+ }
+
+ return tps.success;
+}
+
+
+TempPrefs *temp_prefs_load (const gchar *filename, GError **error)
+{
+ GIOChannel *gio;
+ TempPrefs *temp_prefs = NULL;
+
+ g_return_val_if_fail (filename, NULL);
+
+ gio = g_io_channel_new_file (filename, "r", error);
+ if (gio)
+ {
+ GIOStatus status;
+
+ temp_prefs = temp_prefs_create ();
+
+ do
+ {
+ gchar *line;
+
+ status = g_io_channel_read_line (gio, &line, NULL, NULL, error);
+ if (status == G_IO_STATUS_NORMAL)
+ {
+ gchar *key, *value;
+ if (read_prefs_get_key_value (line, &key, &value))
+ {
+ temp_prefs_set_string (temp_prefs, key, value);
+ }
+ g_free (line);
+ }
+ } while (status == G_IO_STATUS_NORMAL);
+
+ g_io_channel_unref (gio);
+
+ if (status != G_IO_STATUS_EOF)
+ {
+ temp_prefs_destroy (temp_prefs);
+ temp_prefs = NULL;
+ }
+ }
+
+ return temp_prefs;
+}
+
+
+/* Removes already existing list keys from the prefs table */
+static void wipe_list(const gchar *key)
+{
+ gchar *full_key; /* Complete key, with its number suffix */
+ guint i; /* Loop counter */
+
+ /* Go through the prefs table, starting at key<number>, delete it and go
+ * through key<number+1>... until there are no keys left */
+
+ for (i = 0;;i++)
+ {
+ full_key = create_full_key(key, i);
+
+ if (g_hash_table_remove(prefs_table, full_key))
+ {
+ g_free(full_key);
+ continue;
+ }
+ else /* We got all the unneeded keys, leave the loop... */
+ {
+ g_free(full_key);
+ break;
+ }
+ }
+}
+
+/* Delete and rename keys */
+static void cleanup_keys()
+{
+ gchar *buf;
+ gchar *sp = NULL;
+ gint int_buf;
+ gint i;
+ gint x, y, p; /* Window position */
+ float version=0;
+
+ /* Get version */
+ version = prefs_get_double("version");
+
+ /* rename mountpoint to initial_mountpoint */
+ if (prefs_get_string_value(KEY_MOUNTPOINT, &buf))
+ {
+ prefs_set_string("initial_mountpoint", buf);
+ g_free(buf);
+ prefs_set_string(KEY_MOUNTPOINT, NULL);
+ }
+
+ /* rename coverart to coverart_file */
+ if (prefs_get_string_value("coverart", &buf))
+ {
+ prefs_set_string("coverart_file", buf);
+ g_free(buf);
+ prefs_set_string("coverart", NULL);
+ }
+
+ /* rename tm_sort_ to tm_sort */
+ if (prefs_get_string_value("tm_sort_", &buf))
+ {
+ prefs_set_string("tm_sort", buf);
+ g_free(buf);
+ prefs_set_string("tm_sort_", NULL);
+ }
+
+ /* rename md5 to sha1 */
+ if (prefs_get_string_value("md5", &buf))
+ {
+ prefs_set_string("sha1", buf);
+ g_free(buf);
+ prefs_set_string("md5", NULL);
+ }
+
+ /* Convert old path numbered keys to named ones */
+
+ /* Play Now */
+ if (prefs_get_string_value_index("path", PATH_PLAY_NOW, &buf))
+ {
+ prefs_set_string("path_play_now", buf);
+ prefs_set_string_index("path", PATH_PLAY_NOW, NULL);
+ if (version < 0.87)
+ { /* default changed from "xmms -p %s" to "xmms
+ %s" which avoids xmms from hanging --
+ thanks to Chris Vine */
+ if (strcmp (buf, "xmms -p %s") == 0)
+ {
+ prefs_set_string ("path_play_now", "xmms %s");
+ }
+ }
+ g_free(buf);
+ }
+
+ if (prefs_get_string_value_index("toolpath", PATH_PLAY_NOW, &buf))
+ {
+ prefs_set_string("path_play_now", buf);
+ g_free(buf);
+ prefs_set_string_index("toolpath", PATH_PLAY_NOW, NULL);
+ }
+
+ /* Enqueue */
+ if (prefs_get_string_value_index("path", PATH_PLAY_ENQUEUE, &buf))
+ {
+ prefs_set_string("path_play_enqueue", buf);
+ g_free(buf);
+ prefs_set_string_index("path", PATH_PLAY_ENQUEUE, NULL);
+ }
+
+ if (prefs_get_string_value_index("toolpath", PATH_PLAY_ENQUEUE, &buf))
+ {
+ prefs_set_string("path_play_enqueue", buf);
+ g_free(buf);
+ prefs_set_string_index("toolpath", PATH_PLAY_ENQUEUE, NULL);
+ }
+
+ /* MP3 Gain */
+ if (prefs_get_string_value_index("path", PATH_MP3GAIN, &buf))
+ {
+ prefs_set_string("path_mp3gain", buf);
+ g_free(buf);
+ prefs_set_string_index("path", PATH_MP3GAIN, NULL);
+ }
+
+ if (prefs_get_string_value_index("toolpath", PATH_MP3GAIN, &buf))
+ {
+ prefs_set_string("path_mp3gain", buf);
+ g_free(buf);
+ prefs_set_string_index("toolpath", PATH_MP3GAIN, NULL);
+ }
+
+ /* Sync contacts */
+ if (prefs_get_string_value_index("path", PATH_SYNC_CONTACTS, &buf))
+ {
+ prefs_set_string("itdb_0_path_sync_contacts", buf);
+ g_free(buf);
+ prefs_set_string_index("path", PATH_SYNC_CONTACTS, NULL);
+ }
+
+ if (prefs_get_string_value_index("toolpath", PATH_SYNC_CONTACTS, &buf))
+ {
+ prefs_set_string("itdb_0_path_sync_contacts", buf);
+ g_free(buf);
+ prefs_set_string_index("toolpath", PATH_SYNC_CONTACTS, NULL);
+ }
+
+ /* Sync calendar */
+ if (prefs_get_string_value_index("path", PATH_SYNC_CALENDAR, &buf))
+ {
+ prefs_set_string("itdb_0_path_sync_calendar", buf);
+ g_free(buf);
+ prefs_set_string_index("path", PATH_SYNC_CALENDAR, NULL);
+ }
+
+ if (prefs_get_string_value_index("toolpath", PATH_SYNC_CALENDAR, &buf))
+ {
+ prefs_set_string("itdb_0_path_sync_calendar", buf);
+ g_free(buf);
+ prefs_set_string_index("toolpath", PATH_SYNC_CALENDAR, NULL);
+ }
+
+ /* Sync notes */
+ if (prefs_get_string_value_index("path", PATH_SYNC_NOTES, &buf))
+ {
+ prefs_set_string("itdb_0_path_sync_notes", buf);
+ g_free(buf);
+ prefs_set_string_index("path", PATH_SYNC_NOTES, NULL);
+ }
+
+ if (prefs_get_string_value_index("toolpath", PATH_SYNC_NOTES, &buf))
+ {
+ prefs_set_string("itdb_0_path_sync_notes", buf);
+ g_free(buf);
+ prefs_set_string_index("toolpath", PATH_SYNC_NOTES, NULL);
+ }
+
+ /* MSERV music root */
+ if (prefs_get_string_value_index("path", PATH_MSERV_MUSIC_ROOT, &buf))
+ {
+ prefs_set_string("path_mserv_music_root", buf);
+ g_free(buf);
+ prefs_set_string_index("path", PATH_MSERV_MUSIC_ROOT, NULL);
+ }
+
+ if (prefs_get_string_value_index("toolpath", PATH_MSERV_MUSIC_ROOT, &buf))
+ {
+ prefs_set_string("path_mserv_music_root", buf);
+ g_free(buf);
+ prefs_set_string_index("toolpath", PATH_MSERV_MUSIC_ROOT, NULL);
+ }
+
+ /* MSERV track info root */
+ if (prefs_get_string_value_index("path", PATH_MSERV_TRACKINFO_ROOT, &buf))
+ {
+ prefs_set_string("path_mserv_trackinfo_root", buf);
+ g_free(buf);
+ prefs_set_string_index("path", PATH_MSERV_TRACKINFO_ROOT, NULL);
+ }
+
+ if (prefs_get_string_value_index("toolpath", PATH_MSERV_TRACKINFO_ROOT, &buf))
+ {
+ prefs_set_string("path_mserv_trackinfo_root", buf);
+ g_free(buf);
+ prefs_set_string_index("toolpath", PATH_MSERV_TRACKINFO_ROOT, NULL);
+ }
+
+ /* If there's an extra (PATH_NUM) key, delete it */
+ prefs_set_string_index("path", PATH_NUM, NULL);
+ prefs_set_string_index("toolpath", PATH_NUM, NULL);
+
+ /* Ignore/remove some keys */
+ prefs_set_string("play_now_path", NULL);
+ prefs_set_string("sync_remove", NULL);
+ prefs_set_string("sync_remove_confirm", NULL);
+ prefs_set_string("show_sync_dirs", NULL);
+ prefs_set_string("play_enqueue_path", NULL);
+ prefs_set_string("mp3gain_path", NULL);
+ prefs_set_string("statusbar_timeout", NULL);
+ prefs_set_string("offline", NULL);
+ prefs_set_string("time_format", NULL);
+ prefs_set_string("id3_all", NULL);
+ prefs_set_string("pm_autostore", NULL);
+ prefs_set_string("backups", NULL);
+ prefs_set_string("save_sorted_order", NULL);
+ prefs_set_string("fix_path", NULL);
+ prefs_set_string("write_gaintag", NULL);
+ prefs_set_string("automount", NULL);
+ prefs_set_string("display_artcovers", NULL);
+ prefs_set_string("block_display", NULL);
+ prefs_set_string("tmp_disable_sort", NULL);
+ prefs_set_string("size_file_dialog.x", NULL);
+ prefs_set_string("size_file_dialog.y", NULL);
+ prefs_set_string("size_file_dialog_details.x", NULL);
+ prefs_set_string("size_file_dialog_details.y", NULL);
+ prefs_set_string("autoimport", NULL);
+ prefs_set_string("auto_import", NULL);
+
+ /* sp_created_cond renamed to sp_added_cond */
+ for (i = 0; i < SORT_TAB_MAX; i++)
+ {
+ if (prefs_get_int_value_index("sp_created_cond", i, &int_buf))
+ {
+ prefs_set_int_index("sp_added_cond", i, int_buf);
+ prefs_set_string("sp_created_cond", NULL);
+ }
+ }
+
+ /* sp_created_state renamed to sp_added_state */
+ for (i = 0; i < SORT_TAB_MAX; i++)
+ {
+ if (prefs_get_int_value_index("sp_created_state", i, &int_buf))
+ {
+ prefs_set_int_index("sp_added_state", i, int_buf);
+ prefs_set_string("sp_created_state", NULL);
+ }
+ }
+
+ /* sm_col_width renamed to tm_col_width */
+ for (i = 0; i < TM_NUM_COLUMNS; i++)
+ {
+ if (prefs_get_int_value_index("sm_col_width", i, &int_buf))
+ {
+ prefs_set_int_index("tm_col_width", i, int_buf);
+ prefs_set_string_index("sm_col_width", i, NULL);
+ }
+ }
+
+ /* handle version changes in prefs */
+ if (version == 0.0)
+ {
+ /* most likely prefs file written by V0.50 */
+ /* I added two new PANED elements since V0.50 --> shift */
+ for (i=PANED_NUM_ST-1; i>=0; --i)
+ {
+ prefs_set_int_index("paned_pos_", PANED_NUM_GLADE + i,
+ prefs_get_int_index("paned_pos_", PANED_NUM_GLADE + i - 2));
+ }
+ prefs_set_int_index("paned_pos_", PANED_STATUS1, -1);
+ prefs_set_int_index("paned_pos_", PANED_STATUS2, -1);
+ }
+
+ /* set statusbar paned to a decent value if unset */
+ if (prefs_get_int_index("paned_pos_", PANED_STATUS1) == -1)
+ {
+ x = prefs_get_int("size_gtkpod.x");
+ /* set to about 2/3 of the window width */
+ if (x>0)
+ prefs_set_int_index("paned_pos_", PANED_STATUS1, 20*x/30);
+ }
+
+ if (prefs_get_int_index("paned_pos_", PANED_STATUS2) == -1)
+ {
+ x = prefs_get_int("size_gtkpod.x");
+ y = prefs_get_int("size_gtkpod.y");
+ p = prefs_get_int_index("paned_pos_", PANED_STATUS1);
+ /* set to about half of the remaining window */
+ if (x>0)
+ prefs_set_int_index("paned_pos_", PANED_STATUS2, (x-p)/2 );
+ }
+
+ /* Changed layout of info window between 0.72 and 0.73 */
+ if (version < 0.73)
+ {
+ prefs_set_string("size_info.x", NULL);
+ prefs_set_string("size_info.y", NULL);
+ }
+
+ /* not_played_song renamed to not_played_track */
+ if (prefs_get_int_value("not_played_song", &int_buf))
+ {
+ prefs_set_int("not_played_track", int_buf);
+ prefs_set_string("not_played_song", NULL);
+ }
+
+ /* misc_song_nr renamed to misc_track_nr */
+ if (prefs_get_int_value("misc_song_nr", &int_buf))
+ {
+ prefs_set_int("misc_track_nr", int_buf);
+ prefs_set_string("misc_song_nr", NULL);
+ }
+
+ /* sm_autostore renamed to tm_autostore */
+ if (prefs_get_int_value("sm_autostore", &int_buf))
+ {
+ prefs_set_int("tm_autostore", int_buf);
+ prefs_set_string("sm_autostore", NULL);
+ }
+
+ /* sm_sortcol renamed to tm_sortcol */
+ if (prefs_get_int_value("sm_sortcol", &int_buf))
+ {
+ prefs_set_int("tm_sortcol", int_buf);
+ prefs_set_string("sm_sortcol", NULL);
+ }
+
+ /* sm_sort_ renamed to tm_sort */
+ if (prefs_get_int_value("sm_sort_", &int_buf))
+ {
+ prefs_set_int("tm_sort", int_buf);
+ prefs_set_string("sm_sort_", NULL);
+ }
+
+ /* filename_format renamed to export_template */
+ if (prefs_get_string_value("filename_format", &buf))
+ {
+ prefs_set_string("export_template", buf);
+ g_free(buf);
+ prefs_set_string("filename_format", NULL);
+ }
+
+ /* This string was a wrong autoconvert--just ignore it */
+ buf = prefs_get_string("export_template");
+
+ if (buf && strcmp(buf, "%a - %a/%T - %T.mp3") == 0)
+ prefs_set_string("export_template", NULL);
+
+ g_free (buf);
+
+ /* We changed the meaning of the %x in export_template */
+ if (version < 0.72)
+ {
+ /* changed the meaning of the %x in export_template */
+ if (sp) while (*sp)
+ {
+ if (sp[0] == '%')
+ {
+ switch (sp[1]) {
+ case 'A':
+ sp[1] = 'a';
+ break;
+ case 'd':
+ sp[1] = 'A';
+ break;
+ case 'n':
+ sp[1] = 't';
+ break;
+ case 't':
+ sp[1] = 'T';
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ /* For versions < 0.91, remove all itdb keys */
+ if (version < 0.91)
+ prefs_flush_subkey("itdb_");
+
+ prefs_set_string ("version", VERSION);
+}
+
+/* Initialize the prefs table and read configuration */
+void prefs_init (int argc, char *argv[])
+{
+ if (!prefs_table_mutex)
+ prefs_table_mutex = g_mutex_new ();
+
+ lock_prefs_table ();
+
+ /* Create the prefs hash table */
+ prefs_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+ g_free);
+
+ unlock_prefs_table ();
+
+ /* Load preferences */
+ load_prefs();
+
+ /* Clean up old prefs keys */
+ cleanup_keys();
+
+ /* Read environment variables */
+ read_environment();
+
+ /* Read commandline arguments */
+ read_commandline(argc, argv);
+}
+
+/* Delete the hash table */
+void prefs_shutdown ()
+{
+ lock_prefs_table ();
+
+ if (!prefs_table)
+ {
+ unlock_prefs_table ();
+ g_return_if_reached ();
+ }
+
+ /* Delete the prefs hash table */
+ g_hash_table_destroy(prefs_table);
+ prefs_table = NULL;
+
+ unlock_prefs_table ();
+
+ /* We can't free the prefs_table_mutex in a thread-safe way */
+}
+
+/* Create the temp prefs tree */
+/* Free the returned structure with delete_temp_prefs() */
+TempPrefs *temp_prefs_create ()
+{
+ TempPrefs *temp_prefs; /* Returned temp prefs structure */
+
+ temp_prefs = (TempPrefs*)g_malloc(sizeof(TempPrefs));
+
+ temp_prefs->tree = g_tree_new_full((GCompareDataFunc)strcmp, NULL,
+ g_free, g_free);
+
+ return temp_prefs;
+}
+
+/* Delete temp prefs */
+void temp_prefs_destroy (TempPrefs *temp_prefs)
+{
+ g_return_if_fail (temp_prefs);
+ g_return_if_fail (temp_prefs->tree);
+
+ g_tree_destroy(temp_prefs->tree);
+ g_free(temp_prefs);
+}
+
+/* Copy key data from the temp prefs tree to the hash table */
+static gboolean copy_key (gpointer key, gpointer value, gpointer user_data)
+{
+ prefs_set_string(key, value);
+
+ return FALSE;
+}
+
+/* Copy the data from the temp prefs tree to the permanent prefs table */
+void temp_prefs_apply (TempPrefs *temp_prefs)
+{
+ g_return_if_fail (temp_prefs);
+ g_return_if_fail (temp_prefs->tree);
+
+ g_tree_foreach (temp_prefs->tree, copy_key, NULL);
+}
+
+
+/* Create a temp_prefs tree containing a subset of keys in the
+ permanent prefs table (those starting with @subkey */
+static TempPrefs *prefs_create_subset_unlocked (const gchar *subkey)
+{
+ struct sub_data sub_data;
+
+ g_return_val_if_fail (prefs_table, NULL);
+
+ sub_data.temp_prefs = temp_prefs_create ();
+ sub_data.subkey = subkey;
+
+ g_hash_table_foreach (prefs_table, (GHFunc)get_subset, &sub_data);
+
+ return sub_data.temp_prefs;
+}
+
+/* Create a temp_prefs tree containing a subset of keys in the
+ permanent prefs table (those starting with @subkey */
+TempPrefs *prefs_create_subset (const gchar *subkey)
+{
+ TempPrefs *temp_prefs;
+
+ lock_prefs_table ();
+
+ temp_prefs = prefs_create_subset_unlocked (subkey);
+
+ unlock_prefs_table ();
+
+ return temp_prefs;
+}
+
+
+/* Create a temp_prefs tree containing a subset of keys in the
+ permanent prefs table (those starting with @subkey */
+TempPrefs *temp_prefs_create_subset (TempPrefs *temp_prefs,
+ const gchar *subkey)
+{
+ struct sub_data sub_data;
+
+ g_return_val_if_fail (temp_prefs, NULL);
+ g_return_val_if_fail (temp_prefs->tree, NULL);
+
+ sub_data.temp_prefs = temp_prefs_create ();
+ sub_data.subkey = subkey;
+
+ g_tree_foreach (temp_prefs->tree, get_subset, &sub_data);
+
+ return sub_data.temp_prefs;
+}
+
+
+/* Remove all keys in the temp prefs tree from the permanent prefs
+ table */
+void temp_prefs_flush (TempPrefs *temp_prefs)
+{
+ g_return_if_fail (temp_prefs);
+ g_return_if_fail (temp_prefs->tree);
+
+ lock_prefs_table ();
+
+ g_tree_foreach (temp_prefs->tree, flush_key, NULL);
+
+ unlock_prefs_table ();
+}
+
+/* Return the number of keys stored in @temp_prefs */
+gint temp_prefs_size (TempPrefs *temp_prefs)
+{
+ g_return_val_if_fail (temp_prefs, 0);
+ g_return_val_if_fail (temp_prefs->tree, 0);
+
+ return g_tree_nnodes (temp_prefs->tree);
+}
+
+
+/* Returns TRUE if at least one key starting with @subkey exists */
+gboolean temp_prefs_subkey_exists (TempPrefs *temp_prefs,
+ const gchar *subkey)
+{
+ struct sub_data sub_data;
+
+ g_return_val_if_fail (temp_prefs && subkey, FALSE);
+
+ sub_data.temp_prefs = NULL;
+ sub_data.subkey = subkey;
+ sub_data.exists = FALSE;
+
+ g_tree_foreach (temp_prefs->tree, check_subkey, &sub_data);
+
+ return sub_data.exists;
+}
+
+
+/* Special functions */
+
+/* Remove all keys that start with @subkey */
+void prefs_flush_subkey (const gchar *subkey)
+{
+ lock_prefs_table ();
+
+ if (!prefs_table)
+ {
+ unlock_prefs_table ();
+ g_return_if_reached ();
+ }
+
+ g_hash_table_foreach_remove (prefs_table, match_subkey, (gchar *)subkey);
+
+ unlock_prefs_table ();
+}
+
+
+/* Rename all keys that start with @subkey_old in such a way that they
+ start with @subkey_new */
+void prefs_rename_subkey (const gchar *subkey_old, const gchar *subkey_new){
+ struct sub_data sub_data;
+
+ g_return_if_fail (subkey_old);
+ g_return_if_fail (subkey_new);
+
+ lock_prefs_table ();
+
+ if (!prefs_table)
+ {
+ unlock_prefs_table ();
+ g_return_if_reached ();
+ }
+
+ sub_data.temp_prefs = prefs_create_subset_unlocked (subkey_old);
+ sub_data.temp_prefs_orig = NULL;
+
+ if (temp_prefs_size (sub_data.temp_prefs) > 0)
+ {
+ sub_data.subkey = subkey_old;
+ sub_data.subkey2 = subkey_new;
+ g_tree_foreach (sub_data.temp_prefs->tree, subst_key, &sub_data);
+ }
+
+ temp_prefs_destroy (sub_data.temp_prefs);
+
+ unlock_prefs_table ();
+}
+
+
+/* Rename all keys that start with @subkey_old in such a way that they
+ start with @subkey_new */
+void temp_prefs_rename_subkey (TempPrefs *temp_prefs,
+ const gchar *subkey_old,
+ const gchar *subkey_new)
+{
+ struct sub_data sub_data;
+
+ g_return_if_fail (temp_prefs);
+ g_return_if_fail (subkey_old);
+ g_return_if_fail (subkey_new);
+
+ sub_data.temp_prefs_orig = temp_prefs;
+ sub_data.temp_prefs = temp_prefs_create_subset (temp_prefs,
+ subkey_old);
+
+ if (temp_prefs_size (sub_data.temp_prefs) > 0)
+ {
+ sub_data.subkey = subkey_old;
+ sub_data.subkey2 = subkey_new;
+ g_tree_foreach (sub_data.temp_prefs->tree, subst_key, &sub_data);
+ }
+
+ temp_prefs_destroy (sub_data.temp_prefs);
+}
+
+/* Functions for non-numbered pref keys */
+
+/* Set a string value with the given key, or remove key if @value is
+ NULL */
+void prefs_set_string(const gchar *key, const gchar *value)
+{
+ g_return_if_fail (key);
+
+ lock_prefs_table ();
+
+ if (!prefs_table)
+ {
+ unlock_prefs_table ();
+ g_return_if_reached ();
+ }
+
+ if (value)
+ g_hash_table_insert (prefs_table,
+ g_strdup(key), g_strdup(value));
+ else
+ g_hash_table_remove (prefs_table, key);
+
+ unlock_prefs_table ();
+}
+
+/* Set a key value to a given integer */
+void prefs_set_int(const gchar *key, const gint value)
+{
+ gchar *strvalue; /* String value converted from integer */
+
+ lock_prefs_table ();
+
+ if (!prefs_table)
+ {
+ unlock_prefs_table ();
+ g_return_if_reached ();
+ }
+
+ strvalue = g_strdup_printf("%i", value);
+ g_hash_table_insert(prefs_table, g_strdup(key), strvalue);
+
+ unlock_prefs_table ();
+}
+
+/* Set a key to an int64 value */
+void prefs_set_int64(const gchar *key, const gint64 value)
+{
+ gchar *strvalue; /* String value converted from int64 */
+
+ lock_prefs_table ();
+
+ if (!prefs_table)
+ {
+ unlock_prefs_table ();
+ g_return_if_reached ();
+ }
+
+ strvalue = g_strdup_printf("%" G_GINT64_FORMAT, value);
+ g_hash_table_insert(prefs_table, g_strdup(key), strvalue);
+
+ unlock_prefs_table ();
+}
+
+void prefs_set_double(const gchar *key, gdouble value)
+{
+ gchar *strvalue; /* String value converted from integer */
+
+ lock_prefs_table ();
+
+ if (!prefs_table)
+ {
+ unlock_prefs_table ();
+ g_return_if_reached ();
+ }
+
+ strvalue = g_strdup_printf("%f", value);
+ g_hash_table_insert(prefs_table, g_strdup(key), strvalue);
+
+ unlock_prefs_table ();
+}
+
+/* Get a string value associated with a key. Free returned string. */
+gchar *prefs_get_string(const gchar *key)
+{
+ gchar *string = NULL;
+
+ lock_prefs_table ();
+
+ g_return_val_if_fail (prefs_table, (unlock_prefs_table(), NULL));
+
+ string = g_strdup(g_hash_table_lookup(prefs_table, key));
+
+ unlock_prefs_table ();
+
+ return string;
+}
+
+/* Use this if you need to know if the given key actually exists */
+/* The value parameter can be NULL if you don't need the value itself. */
+gboolean prefs_get_string_value(const gchar *key, gchar **value)
+{
+ const gchar *string; /* String value from prefs table */
+ gboolean valid = FALSE;
+
+ lock_prefs_table ();
+
+ g_return_val_if_fail (prefs_table, (unlock_prefs_table(), FALSE));
+
+ string = g_hash_table_lookup(prefs_table, key);
+
+ if (value)
+ *value = g_strdup (string);
+ if (string)
+ valid = TRUE;
+
+ unlock_prefs_table ();
+
+ return valid;
+}
+
+/* Get an integer value from a key */
+gint prefs_get_int(const gchar *key)
+{
+ gchar *string; /* Hash value string */
+ gint value; /* Returned value */
+
+ value = 0;
+
+ lock_prefs_table ();
+
+ g_return_val_if_fail (prefs_table, (unlock_prefs_table(), value));
+
+ string = g_hash_table_lookup(prefs_table, key);
+
+ if (string)
+ value = atoi(string);
+
+ unlock_prefs_table ();
+
+ return value;
+}
+
+/* Use this if you need to know if the given key actually exists */
+/* The value parameter can be NULL if you don't need the value itself. */
+gboolean prefs_get_int_value(const gchar *key, gint *value)
+{
+ gchar *string; /* String value from prefs table */
+ gboolean valid = FALSE;
+
+ lock_prefs_table ();
+
+ g_return_val_if_fail (prefs_table, (unlock_prefs_table(), FALSE));
+
+ string = g_hash_table_lookup(prefs_table, key);
+
+ if (value)
+ {
+ if (string)
+ *value = atoi(string);
+ else
+ *value = 0;
+ }
+
+ if (string)
+ valid = TRUE;
+
+ unlock_prefs_table ();
+
+ return valid;
+}
+
+/* Get a 64 bit integer value from a key */
+gint64 prefs_get_int64(const gchar *key)
+{
+ gchar *string; /* Key value string */
+ gint64 value; /* Returned value */
+
+ value = 0;
+
+ lock_prefs_table ();
+
+ g_return_val_if_fail (prefs_table, (unlock_prefs_table(), value));
+
+ string = g_hash_table_lookup(prefs_table, key);
+
+ if (string)
+ value = g_ascii_strtoull(string, NULL, 10);
+
+ unlock_prefs_table ();
+
+ return value;
+}
+
+/* Get a 64 bit integer value from a key */
+/* Use this if you need to know if the given key actually exists */
+/* The value parameter can be NULL if you don't need the value itself. */
+gboolean prefs_get_int64_value(const gchar *key, gint64 *value)
+{
+ gchar *string; /* String value from prefs table */
+ gboolean valid = FALSE;
+
+ lock_prefs_table ();
+
+ g_return_val_if_fail (prefs_table, (unlock_prefs_table(), FALSE));
+
+ string = g_hash_table_lookup(prefs_table, key);
+
+ if (value)
+ {
+ if (string)
+ *value = g_ascii_strtoull(string, NULL, 10);
+ else
+ *value = 0;
+ }
+
+ if (string)
+ valid = TRUE;
+
+ unlock_prefs_table ();
+
+ return valid;
+}
+
+gdouble prefs_get_double(const gchar *key)
+{
+ gchar *string; /* Key value string */
+ gdouble value; /* Returned value */
+
+ value = 0;
+
+ lock_prefs_table ();
+
+ g_return_val_if_fail (prefs_table, (unlock_prefs_table(), value));
+
+ string = g_hash_table_lookup(prefs_table, key);
+
+ if (string)
+ value = g_ascii_strtod(string, NULL);
+
+ unlock_prefs_table ();
+
+ return value;
+}
+
+gboolean prefs_get_double_value(const gchar *key, gdouble *value)
+{
+ gchar *string; /* String value from prefs table */
+ gboolean valid = FALSE;
+
+ lock_prefs_table ();
+
+ g_return_val_if_fail (prefs_table, (unlock_prefs_table(), FALSE));
+
+ string = g_hash_table_lookup(prefs_table, key);
+
+ if (value)
+ {
+ if (string)
+ *value = g_ascii_strtod(string, NULL);
+ else
+ *value = 0;
+ }
+
+ if (string)
+ valid = TRUE;
+
+ unlock_prefs_table ();
+
+ return valid;
+}
+
+/* Functions for numbered pref keys */
+
+/* Set a string value with the given key */
+void prefs_set_string_index(const gchar *key, const guint index,
+ const gchar *value)
+{
+ gchar *full_key; /* Complete numbered key */
+
+ full_key = create_full_key(key, index);
+ prefs_set_string(full_key, value);
+
+ g_free(full_key);
+}
+
+/* Set a key value to a given integer */
+void prefs_set_int_index(const gchar *key, const guint index,
+ const gint value)
+{
+ gchar *full_key; /* Complete numbered key */
+
+ full_key = create_full_key(key, index);
+ prefs_set_int(full_key, value);
+
+ g_free(full_key);
+}
+
+/* Set a key to an int64 value */
+void prefs_set_int64_index(const gchar *key, const guint index,
+ const gint64 value)
+{
+ gchar *full_key; /* Complete numbered key */
+
+ full_key = create_full_key(key, index);
+ prefs_set_int64(full_key, value);
+
+ g_free(full_key);
+}
+
+/* Set a key to a gdouble value */
+void prefs_set_double_index(const gchar *key, guint index,
+ gdouble value)
+{
+ gchar *full_key; /* Complete numbered key */
+
+ full_key = create_full_key(key, index);
+ prefs_set_double(full_key, value);
+
+ g_free(full_key);
+}
+
+/* Get a string value associated with a key. Free returned string. */
+gchar *prefs_get_string_index(const gchar *key, const guint index)
+{
+ gchar *full_key; /* Complete numbered key */
+ gchar *string; /* Return string */
+
+ full_key = create_full_key(key, index);
+ string = prefs_get_string(full_key);
+
+ g_free(full_key);
+ return string;
+}
+
+/* Get a string value associated with a key. Free returned string. */
+/* Use this if you need to know if the given key actually exists */
+gboolean prefs_get_string_value_index(const gchar *key, const guint index,
+ gchar **value)
+{
+ gchar *full_key; /* Complete numbered key */
+ gboolean ret; /* Return value */
+
+ full_key = create_full_key(key, index);
+ ret = prefs_get_string_value(full_key, value);
+
+ g_free(full_key);
+ return ret;
+}
+
+/* Get an integer value from a key */
+gint prefs_get_int_index(const gchar *key, const guint index)
+{
+ gchar *full_key; /* Complete numbered key */
+ gint value; /* Returned integer value */
+
+ full_key = create_full_key(key, index);
+ value = prefs_get_int(full_key);
+
+ g_free(full_key);
+ return value;
+}
+
+/* Get an integer value from a key */
+/* Use this if you need to know if the given key actually exists */
+gboolean prefs_get_int_value_index(const gchar *key, const guint index,
+ gint *value)
+{
+ gchar *full_key; /* Complete numbered key */
+ gboolean ret; /* Return value */
+
+ full_key = create_full_key(key, index);
+ ret = prefs_get_int_value(full_key, value);
+
+ g_free(full_key);
+ return ret;
+}
+
+/* Get a 64 bit integer value from a key */
+gint64 prefs_get_int64_index(const gchar *key, const guint index)
+{
+ gchar *full_key; /* Complete numbered key */
+ gint64 value; /* Return value */
+
+ full_key = create_full_key(key, index);
+ value = prefs_get_int64(full_key);
+
+ g_free(full_key);
+ return value;
+}
+
+/* Get a 64 bit integer value from a key */
+/* Use this if you need to know if the given key actually exists */
+gboolean prefs_get_int64_value_index(const gchar *key, const guint index,
+ gint64 *value)
+{
+ gchar *full_key; /* Complete numbered key */
+ gboolean ret; /* Return value */
+
+ full_key = create_full_key(key, index);
+ ret = prefs_get_int64_value(full_key, value);
+
+ g_free(full_key);
+ return ret;
+}
+
+gdouble prefs_get_double_index(const gchar *key, guint index)
+{
+ gchar *full_key; /* Complete numbered key */
+ gdouble value; /* Return value */
+
+ full_key = create_full_key(key, index);
+ value = prefs_get_double(full_key);
+
+ g_free(full_key);
+ return value;
+}
+
+gboolean prefs_get_double_value_index(const gchar *key, guint index,
+ gdouble *value)
+{
+ gchar *full_key; /* Complete numbered key */
+ gboolean ret; /* Return value */
+
+ full_key = create_full_key(key, index);
+ ret = prefs_get_double_value(full_key, value);
+
+ g_free(full_key);
+ return ret;
+}
+
+/* Add string value with the given key to temp prefs. Note: use
+ * temp_prefs_remove_key() to remove key from the temp prefs. Setting
+ * it to NULL will not remove the key. It will instead remove the key
+ * in the main prefs table when you call temp_prefs_apply(). */
+void temp_prefs_set_string (TempPrefs *temp_prefs, const gchar *key,
+ const gchar *value)
+{
+ g_return_if_fail (temp_prefs && temp_prefs->tree);
+ g_return_if_fail (key);
+
+ g_tree_insert (temp_prefs->tree, g_strdup(key), g_strdup(value));
+}
+
+/* Add string value with the given key to temp prefs. Remove the key
+ * if @value is NULL. */
+void temp_prefs_remove_key (TempPrefs *temp_prefs, const gchar *key)
+{
+ g_return_if_fail (temp_prefs && temp_prefs->tree);
+ g_return_if_fail (key);
+
+ g_tree_remove (temp_prefs->tree, key);
+}
+
+/* Add an integer value to temp prefs */
+void temp_prefs_set_int(TempPrefs *temp_prefs, const gchar *key,
+ const gint value)
+{
+ gchar *strvalue; /* String value converted from integer */
+
+ g_return_if_fail (temp_prefs && temp_prefs->tree);
+ g_return_if_fail (key);
+
+ strvalue = g_strdup_printf("%i", value);
+ g_tree_insert(temp_prefs->tree, g_strdup(key), strvalue);
+}
+
+/* Add an int64 to temp prefs */
+void temp_prefs_set_int64(TempPrefs *temp_prefs, const gchar *key,
+ const gint64 value)
+{
+ gchar *strvalue; /* String value converted from int64 */
+
+ g_return_if_fail (temp_prefs && temp_prefs->tree);
+ g_return_if_fail (key);
+
+ strvalue = g_strdup_printf("%" G_GINT64_FORMAT, value);
+ g_tree_insert(temp_prefs->tree, g_strdup(key), strvalue);
+}
+
+void temp_prefs_set_double(TempPrefs *temp_prefs, const gchar *key,
+ gdouble value)
+{
+ gchar *strvalue; /* String value converted from int64 */
+
+ g_return_if_fail (temp_prefs && temp_prefs->tree);
+ g_return_if_fail (key);
+
+ strvalue = g_strdup_printf("%fu", value);
+ g_tree_insert(temp_prefs->tree, g_strdup(key), strvalue);
+}
+
+/* Get a string value associated with a key. Free returned string. */
+gchar *temp_prefs_get_string(TempPrefs *temp_prefs, const gchar *key)
+{
+ g_return_val_if_fail (temp_prefs && temp_prefs->tree, NULL);
+ g_return_val_if_fail (key, NULL);
+
+ return g_strdup (g_tree_lookup (temp_prefs->tree, key));
+}
+
+/* Use this if you need to know if the given key actually exists */
+/* The value parameter can be NULL if you don't need the value itself. */
+gboolean temp_prefs_get_string_value(TempPrefs *temp_prefs,
+ const gchar *key, gchar **value)
+{
+ gchar *string; /* String value from prefs table */
+
+ g_return_val_if_fail (temp_prefs && temp_prefs->tree, FALSE);
+ g_return_val_if_fail (key, FALSE);
+
+ string = g_tree_lookup (temp_prefs->tree, key);
+
+ if (value)
+ *value = g_strdup (string);
+
+ if (string)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* Get an integer value from a key */
+gint temp_prefs_get_int(TempPrefs *temp_prefs, const gchar *key)
+{
+ gchar *string; /* Hash value string */
+ gint value; /* Returned value */
+
+ g_return_val_if_fail (temp_prefs && temp_prefs->tree, 0);
+ g_return_val_if_fail (key, 0);
+
+ value = 0;
+
+ string = g_tree_lookup (temp_prefs->tree, key);
+
+ if (string)
+ value = atoi(string);
+
+ return value;
+}
+
+/* Use this if you need to know if the given key actually exists */
+/* The value parameter can be NULL if you don't need the value itself. */
+gboolean temp_prefs_get_int_value(TempPrefs *temp_prefs,
+ const gchar *key, gint *value)
+{
+ gchar *string; /* String value from prefs table */
+
+ g_return_val_if_fail (temp_prefs && temp_prefs->tree, FALSE);
+ g_return_val_if_fail (key, FALSE);
+
+ string = g_tree_lookup (temp_prefs->tree, key);
+
+ if (value)
+ {
+ if (string)
+ *value = atoi(string);
+ else
+ *value = 0;
+ }
+
+ if (string)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+gdouble temp_prefs_get_double(TempPrefs *temp_prefs,
+ const gchar *key)
+{
+ gchar *string; /* Hash value string */
+ gdouble value; /* Returned value */
+
+ g_return_val_if_fail (temp_prefs && temp_prefs->tree, 0);
+ g_return_val_if_fail (key, 0);
+
+ value = 0.0f;
+
+ string = g_tree_lookup (temp_prefs->tree, key);
+
+ if (string)
+ value = g_ascii_strtod(string, NULL);
+
+ return value;
+}
+
+gboolean temp_prefs_get_double_value(TempPrefs *temp_prefs,
+ const gchar *key, gdouble *value)
+{
+ gchar *string; /* String value from prefs table */
+
+ g_return_val_if_fail (temp_prefs && temp_prefs->tree, FALSE);
+ g_return_val_if_fail (key, FALSE);
+
+ string = g_tree_lookup (temp_prefs->tree, key);
+
+ if (value)
+ {
+ if (string)
+ *value = g_ascii_strtod(string, NULL);
+ else
+ *value = 0;
+ }
+
+ if (string)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/* Functions for numbered pref keys */
+
+/* Set a string value with the given key */
+void temp_prefs_set_string_index(TempPrefs *temp_prefs, const gchar *key,
+ const guint index, const gchar *value)
+{
+ gchar *full_key; /* Complete numbered key */
+
+ g_return_if_fail (temp_prefs && temp_prefs->tree);
+ g_return_if_fail (key);
+
+ full_key = create_full_key(key, index);
+ temp_prefs_set_string(temp_prefs, full_key, value);
+
+ g_free(full_key);
+}
+
+/* Set a key value to a given integer */
+void temp_prefs_set_int_index(TempPrefs *temp_prefs, const gchar *key,
+ const guint index, const gint value)
+{
+ gchar *full_key; /* Complete numbered key */
+
+ g_return_if_fail (temp_prefs && temp_prefs->tree);
+ g_return_if_fail (key);
+
+ full_key = create_full_key(key, index);
+ temp_prefs_set_int(temp_prefs, full_key, value);
+
+ g_free(full_key);
+}
+
+/* Set a key to an int64 value */
+void temp_prefs_set_int64_index(TempPrefs *temp_prefs, const gchar *key,
+ const guint index, const gint64 value)
+{
+ gchar *full_key; /* Complete numbered key */
+
+ g_return_if_fail (temp_prefs && temp_prefs->tree);
+ g_return_if_fail (key);
+
+ full_key = create_full_key(key, index);
+ temp_prefs_set_int64(temp_prefs, full_key, value);
+
+ g_free(full_key);
+}
+
+/* Functions for variable-length lists */
+
+/* Create a tree that contains lists that need to be rebuilt */
+/* Free the returned structure with destroy_temp_lists */
+TempLists *temp_lists_create()
+{
+ TempLists *temp_lists; /* Allocated temp list structure */
+
+ temp_lists = (TempLists*)g_malloc(sizeof(TempLists));
+
+
+ temp_lists->tree = g_tree_new_full((GCompareDataFunc)strcmp, NULL,
+ g_free,
+ (GDestroyNotify)prefs_free_list);
+ return temp_lists;
+}
+
+/* Destroys the list tree */
+void temp_lists_destroy(TempLists *temp_lists)
+{
+ if (temp_lists)
+ {
+ if (temp_lists->tree)
+ g_tree_destroy(temp_lists->tree);
+
+ g_free(temp_lists);
+ }
+}
+
+/* Add a list with the given key prefix to a temp list tree */
+void temp_list_add(TempLists *temp_lists, const gchar *key, GList *list)
+{
+ if (temp_lists)
+ {
+ if (temp_lists->tree)
+ g_tree_insert(temp_lists->tree, g_strdup(key), list);
+ }
+}
+
+/* Copy the items of the lists in the given tree to the prefs table */
+void temp_lists_apply(TempLists *temp_lists)
+{
+ if (temp_lists)
+ {
+ if (temp_lists->tree)
+ g_tree_foreach(temp_lists->tree, copy_list, NULL);
+ }
+}
+
+/* Copy one list to the prefs table. Useful for lists not changed by a window */
+void prefs_apply_list(gchar *key, GList *list)
+{
+ GList *node; /* Current list node */
+ guint i; /* Counter */
+
+ i = 0;
+
+ if (prefs_table)
+ {
+ /* Clean the existing list */
+ wipe_list(key);
+
+ node = list;
+
+ /* Add the new list items to the table */
+ while (node)
+ {
+ g_hash_table_insert(prefs_table, create_full_key(key, i),
+ g_strdup(node->data));
+
+ node = g_list_next(node);
+ i++;
+ }
+
+ /* Add the end marker */
+ g_hash_table_insert(prefs_table, create_full_key(key, i),
+ g_strdup(LIST_END_MARKER));
+ }
+}
+
+/* Get the items in a variable-length list from the prefs table */
+GList *prefs_get_list(const gchar *key)
+{
+ guint end_marker_hash; /* Hash value of the list end marker */
+ guint item_hash; /* Hash value of current list string */
+ gchar *item_string; /* List item string */
+ guint i; /* Counter */
+ GList *list; /* List that contains items */
+
+ /* Go through each key in the table until we find the end marker */
+ end_marker_hash = g_str_hash(LIST_END_MARKER);
+ list = NULL;
+
+ for (i = 0;;i++)
+ {
+ item_string = prefs_get_string_index(key, i);
+
+ if (item_string)
+ {
+ item_hash = g_str_hash(item_string);
+
+ if (item_hash != end_marker_hash)
+ {
+ list = g_list_append(list, item_string);
+ continue;
+ }
+ else
+ {
+ g_free(item_string);
+ break;
+ }
+ }
+ }
+
+ return list;
+}
+
+/* Free a list and its strings */
+void prefs_free_list(GList *list)
+{
+ GList *node; /* Current list node */
+
+ node = list;
+
+ /* Go through the list, freeing the strings */
+
+ while (node)
+ {
+ if (node->data)
+ g_free(node->data);
+
+ node = g_list_next(node);
+ }
+
+ g_list_free(list);
+}
+
+/* Creates a list from lines in a GtkTextBuffer. Free the list when done. */
+GList *get_list_from_buffer(GtkTextBuffer *buffer)
+{
+ GtkTextIter start_iter; /* Start of buffer text */
+ GtkTextIter end_iter; /* End of buffer text */
+ gchar *text_buffer; /* Raw text buffer */
+ gchar **string_array; /* Contains each line of the buffer */
+ gchar **string_iter; /* Pointer for iterating through the string vector */
+ GList *list; /* List that contains each string */
+
+ list = NULL;
+
+ /* Grab the text from the buffer, and then split it up by lines */
+ gtk_text_buffer_get_start_iter(buffer, &start_iter);
+ gtk_text_buffer_get_end_iter(buffer, &end_iter);
+
+ text_buffer = gtk_text_buffer_get_text(buffer, &start_iter, &end_iter, FALSE);
+ string_array = g_strsplit(text_buffer, "\n", -1);
+ string_iter = string_array;
+
+ /* Go through each string and put it in the list */
+ while (*string_iter)
+ {
+ if (strlen(*string_iter) != 0)
+ list = g_list_append(list, g_strdup(*string_iter));
+
+ string_iter++;
+ }
+
+ return list;
+}
More information about the Pkg-gtkpod-devel
mailing list