diff options
author | Jorg Schuler <jcsjcs@users.sourceforge.net> | 2006-03-16 15:34:34 +0000 |
---|---|---|
committer | Jorg Schuler <jcsjcs@users.sourceforge.net> | 2006-03-16 15:34:34 +0000 |
commit | ace89adce995bd158ef49390a6438c093bf306b3 (patch) | |
tree | c5a18421b35013c3fcd1ac5dbe72daa649a30b2b /src | |
parent | 86f4c354d7fa66d864b434169c633f85ed516e5c (diff) | |
download | libgpod-ace89adce995bd158ef49390a6438c093bf306b3.tar.gz libgpod-ace89adce995bd158ef49390a6438c093bf306b3.tar.xz libgpod-ace89adce995bd158ef49390a6438c093bf306b3.zip |
* itdb_device.[ch]: rewrote ipod-device.c, removed all hal-code,
removed all code irrelevant to writing the iTunesDB and
ArtworkDB.
* autodetect iControl directory now also works for ArtworkDB.
* db-artwork-parser.c (ipod_db_get_artwork_db_path): create
Artwork directory if not already present.
* itdb.h: Itdb_iTunesDB: moved mountpoint and musicdirs into
private Itdb_Device. Use itdb_set_mountpoint() and
itdb_get_mountpoint() to access the mountpoint.
git-svn-id: https://gtkpod.svn.sf.net/svnroot/gtkpod/libgpod/trunk@1220 f01d2545-417e-4e96-918e-98f8d0dbbcb6
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 8 | ||||
-rw-r--r-- | src/db-artwork-parser.c | 48 | ||||
-rw-r--r-- | src/db-artwork-writer.c | 10 | ||||
-rw-r--r-- | src/db-image-parser.c | 20 | ||||
-rw-r--r-- | src/db-image-parser.h | 5 | ||||
-rw-r--r-- | src/hal-common.c | 95 | ||||
-rw-r--r-- | src/hal-common.h | 95 | ||||
-rw-r--r-- | src/ipod-device.c | 1832 | ||||
-rw-r--r-- | src/ipod-device.h | 196 | ||||
-rw-r--r-- | src/itdb.h | 29 | ||||
-rw-r--r-- | src/itdb_artwork.c | 31 | ||||
-rw-r--r-- | src/itdb_device.c | 431 | ||||
-rw-r--r-- | src/itdb_device.h | 126 | ||||
-rw-r--r-- | src/itdb_itunesdb.c | 298 | ||||
-rw-r--r-- | src/itdb_private.h | 2 | ||||
-rw-r--r-- | src/itdb_track.c | 24 | ||||
-rw-r--r-- | src/ithumb-writer.c | 77 |
17 files changed, 909 insertions, 2418 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index dfc0a66..11feb18 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,14 +18,12 @@ libgpod_la_SOURCES = \ db-itunes-parser.h \ db-artwork-writer.c \ ithumb-writer.c \ - ipod-device.c \ - ipod-device.h \ - hal-common.c \ - hal-common.h \ + itdb_device.c \ + itdb_device.h \ glib-compat.h -libgpod_la_headers = itdb.h ipod-device.h +libgpod_la_headers = itdb.h libgpod_la_noinst_headers = itdb_private.h hal-common.h libgpod_la_LDFLAGS = -version-info $(LIBGPOD_CURRENT):$(LIBGPOD_REVISION):$(LIBGPOD_AGE) \ -no-undefined diff --git a/src/db-artwork-parser.c b/src/db-artwork-parser.c index 8731050..0599b78 100644 --- a/src/db-artwork-parser.c +++ b/src/db-artwork-parser.c @@ -27,6 +27,8 @@ #endif #include <string.h> +#include <sys/stat.h> +#include <sys/types.h> #include "itdb.h" #include "db-artwork-debug.h" @@ -440,21 +442,38 @@ parse_mhfd (DBParseContext *ctx, Itdb_iTunesDB *db, GError **error) G_GNUC_INTERNAL char * ipod_db_get_artwork_db_path (const char *mount_point) { - gchar *filename; - const char *paths[] = {"iPod_Control", "Artwork", "ArtworkDB", NULL}; - filename = itdb_resolve_path (mount_point, paths); + gchar *filename=NULL; + + /* fail silently if no mount point given */ + if (!mount_point) return NULL; + + filename = itdb_get_artworkdb_path (mount_point); /* itdb_resolve_path() only returns existing paths */ if (!filename) { - gchar *path; - paths[2] = NULL; - path = itdb_resolve_path (mount_point, (const char **)paths); - if (path) + gchar *artwork_dir; + + artwork_dir = itdb_get_artwork_dir (mount_point); + if (!artwork_dir) + { + /* attempt to create Artwork dir */ + gchar *control_dir = itdb_get_control_dir (mount_point); + gchar *dir; + if (control_dir) + { + dir = g_build_filename (control_dir, "Artwork", NULL); + mkdir (dir, 0777); + g_free (dir); + g_free (control_dir); + } + } + if (artwork_dir) { - filename = g_build_filename (path, "ArtworkDB", NULL); + filename = g_build_filename (artwork_dir, + "ArtworkDB", NULL); + g_free (artwork_dir); } - g_free (path); } return filename; @@ -471,15 +490,15 @@ ipod_db_get_photo_db_path (const char *mount_point) } static gboolean -ipod_supports_cover_art (IpodDevice *ipod) +ipod_supports_cover_art (Itdb_Device *device) { - const IpodArtworkFormat *formats; + const Itdb_ArtworkFormat *formats; - if (ipod == NULL) { + if (device == NULL) { return FALSE; } - g_object_get (G_OBJECT (ipod), "artwork-formats", &formats, NULL); + formats = itdb_device_get_artwork_formats (device); if (formats == NULL) { return FALSE; } @@ -502,12 +521,13 @@ ipod_parse_artwork_db (Itdb_iTunesDB *db) char *filename; g_return_val_if_fail (db, -1); + g_return_val_if_fail (db->device, -1); if (!ipod_supports_cover_art (db->device)) { return -1; } ctx = NULL; - filename = ipod_db_get_artwork_db_path (db->mountpoint); + filename = ipod_db_get_artwork_db_path (itdb_get_mountpoint (db)); if (filename == NULL) { goto error; } diff --git a/src/db-artwork-writer.c b/src/db-artwork-writer.c index 65fc089..b890495 100644 --- a/src/db-artwork-writer.c +++ b/src/db-artwork-writer.c @@ -444,7 +444,7 @@ write_mhii (Itdb_Track *song, iPodBuffer *buffer) for (it = song->artwork->thumbnails; it != NULL; it = it->next) { iPodBuffer *sub_buffer; Itdb_Thumb *thumb; - const IpodArtworkFormat *img_info; + const Itdb_ArtworkFormat *img_info; mhii->num_children = GINT_TO_LE (num_children); mhii->total_len = GINT_TO_LE (total_bytes); @@ -453,7 +453,7 @@ write_mhii (Itdb_Track *song, iPodBuffer *buffer) return -1; } thumb = (Itdb_Thumb *)it->data; - img_info = ipod_get_artwork_info_from_type ( + img_info = itdb_get_artwork_info_from_type ( song->itdb->device, thumb->type); if (img_info == NULL) { return -1; @@ -543,7 +543,7 @@ static int write_mhif (Itdb_iTunesDB *db, iPodBuffer *buffer, enum iPodThumbnailType type) { MhifHeader *mhif; - const IpodArtworkFormat *img_info; + const Itdb_ArtworkFormat *img_info; mhif = (MhifHeader *)init_header (buffer, "mhif", sizeof (MhifHeader)); if (mhif == NULL) { @@ -551,7 +551,7 @@ write_mhif (Itdb_iTunesDB *db, iPodBuffer *buffer, enum iPodThumbnailType type) } mhif->total_len = mhif->header_len; - img_info = ipod_get_artwork_info_from_type (db->device, type); + img_info = itdb_get_artwork_info_from_type (db->device, type); if (img_info == NULL) { return -1; } @@ -748,7 +748,7 @@ ipod_write_artwork_db (Itdb_iTunesDB *db) /* Now we can update the ArtworkDB file */ id_max = ipod_artwork_db_set_ids (db); - filename = ipod_db_get_artwork_db_path (db->mountpoint); + filename = ipod_db_get_artwork_db_path (itdb_get_mountpoint (db)); if (filename == NULL) { /* FIXME: the iTunesDB will be inconsistent wrt artwork_count * it might be better to 0 out this field in all tracks diff --git a/src/db-image-parser.c b/src/db-image-parser.c index ba4cda5..296d82c 100644 --- a/src/db-image-parser.c +++ b/src/db-image-parser.c @@ -29,20 +29,22 @@ #include <glib.h> #include <glib-object.h> +#include "itdb_device.h" #include "db-artwork-parser.h" #include "db-image-parser.h" #include <glib/gi18n-lib.h> static int -image_type_from_corr_id (IpodDevice *ipod, int corr_id) +image_type_from_corr_id (Itdb_Device *device, int corr_id) { - const IpodArtworkFormat *formats; + const Itdb_ArtworkFormat *formats; - if (ipod == NULL) { + if (device == NULL) { return -1; } - g_object_get (G_OBJECT (ipod), "artwork-formats", &formats, NULL); + formats = itdb_device_get_artwork_formats (device); + if (formats == NULL) { return -1; } @@ -58,16 +60,16 @@ image_type_from_corr_id (IpodDevice *ipod, int corr_id) } -G_GNUC_INTERNAL const IpodArtworkFormat * -ipod_get_artwork_info_from_type (IpodDevice *ipod, int image_type) +G_GNUC_INTERNAL const Itdb_ArtworkFormat * +itdb_get_artwork_info_from_type (Itdb_Device *device, int image_type) { - const IpodArtworkFormat *formats; + const Itdb_ArtworkFormat *formats; - if (ipod == NULL) { + if (device == NULL) { return NULL; } - g_object_get (G_OBJECT (ipod), "artwork-formats", &formats, NULL); + formats = itdb_device_get_artwork_formats (device); if (formats == NULL) { return NULL; } diff --git a/src/db-image-parser.h b/src/db-image-parser.h index 3e42c62..a8e2fe5 100644 --- a/src/db-image-parser.h +++ b/src/db-image-parser.h @@ -26,6 +26,7 @@ #define IMAGE_PARSER_H #include "db-itunes-parser.h" +#include "itdb_device.h" #include "itdb.h" #define RED_BITS 5 @@ -45,7 +46,7 @@ G_GNUC_INTERNAL Itdb_Thumb *ipod_image_new_from_mhni (MhniHeader *mhni, G_GNUC_INTERNAL int itdb_write_ithumb_files (Itdb_iTunesDB *db); -G_GNUC_INTERNAL const IpodArtworkFormat *ipod_get_artwork_info_from_type ( - IpodDevice *ipod, int image_type); +G_GNUC_INTERNAL const Itdb_ArtworkFormat *itdb_get_artwork_info_from_type ( + Itdb_Device *ipod, int image_type); #endif diff --git a/src/hal-common.c b/src/hal-common.c deleted file mode 100644 index d2bbd5d..0000000 --- a/src/hal-common.c +++ /dev/null @@ -1,95 +0,0 @@ -/* Time-stamp: <2005-12-10 00:22:44 jcs> -| -| Copyright (C) 2005 Jorg Schuler <jcsjcs at users sourceforge net> -| Part of the gtkpod project. -| -| URL: http://www.gtkpod.org/ -| URL: http://gtkpod.sourceforge.net/ -| -| -| The source is taken from libipoddevice, CVS version October 8 2005 -| (http://64.14.94.162/index.php/Libipoddevice). -| -| I decided not to make libgpod dependent on libipoddevice because -| the latter depends on libraries not widely available yet (libhal >= -| 0.5.2, glib >= 2.8). It is planned to replace these files with a -| libipoddevice dependence at some later time. -| -| The following changes were done: -| -| - libhal becomes optional (see #ifdef HAVE_LIBHAL sections) -| - provide some dummy libhal functions to make libhal-independence -| of ipod-device.c easier. -| -| Because of these changes only a limited amount of functionality is -| available. See ipod-device.h for summary. -| -| -| -| -| $Id$ -*/ -/* ex: set ts=4: */ -/*************************************************************************** -* hal-common.c -* Copyright (C) 2005 Novell -* Written by Aaron Bockover <aaron@aaronbock.net> -****************************************************************************/ - -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2.1 of the GNU Lesser General Public - * License as published by the Free Software Foundation. - * - * 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 Lesser Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "itdb_private.h" -#include "hal-common.h" - -#ifndef HAVE_LIBHAL -gchar **libhal_manager_find_device_string_match (LibHalContext *hal_ctx, - const gchar *type, - const gchar *str, - gint *vol_count, - void *error) -{ -/* gchar **volumes = g_new0 (gchar *, 2); - volumes[0] = g_strdup (type);*/ - gchar **volumes = NULL; - *vol_count = 0; - return volumes; -} -void libhal_free_string_array (gchar **volumes) -{ -/* g_strfreev (volumes);*/ -} -gboolean libhal_device_property_exists (LibHalContext *hal_ctx, - const gchar *vol, - const gchar *prop, - void *error) -{ - return FALSE; -} -gboolean libhal_device_get_property_bool (LibHalContext *hal_ctx, - const gchar *vol, - const gchar *prop, - void *error) -{ - return FALSE; -} -void libhal_ctx_shutdown (LibHalContext *hal_ctx, void *error) {} -void libhal_ctx_free (LibHalContext *hal_ctx) {} -#endif diff --git a/src/hal-common.h b/src/hal-common.h deleted file mode 100644 index 8cdbe2b..0000000 --- a/src/hal-common.h +++ /dev/null @@ -1,95 +0,0 @@ -/* Time-stamp: <2005-10-10 01:23:30 jcs> -| -| Copyright (C) 2005 Jorg Schuler <jcsjcs at users sourceforge net> -| Part of the gtkpod project. -| -| URL: http://www.gtkpod.org/ -| URL: http://gtkpod.sourceforge.net/ -| -| -| The source is taken from libipoddevice, CVS version October 8 2005 -| (http://64.14.94.162/index.php/Libipoddevice). -| -| I decided not to make libgpod dependent on libipoddevice because -| the latter depends on libraries not widely available yet (libhal >= -| 0.5.2, glib >= 2.8). It is planned to replace these files with a -| libipoddevice dependence at some later time. -| -| The following changes were done: -| -| - libhal becomes optional (see #if HAVE_LIBHAL sections) -| - provide some dummy libhal functions to make libhal-independence -| of ipod-device.c easier. -| -| Because of these changes only a limited amount of functionality is -| available. See ipod-device.h for summary. -| -| -| -| -| $Id$ -*/ -/* ex: set ts=4: */ -/*************************************************************************** -* hal-common.h -* Copyright (C) 2005 Novell -* Written by Aaron Bockover <aaron@aaronbock.net> -****************************************************************************/ - -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2.1 of the GNU Lesser General Public - * License as published by the Free Software Foundation. - * - * 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 Lesser Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 - */ - -#ifndef HAL_COMMON_H -#define HAL_COMMON_H - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <glib.h> -#include <glib-object.h> - -#ifdef HAVE_LIBHAL - -#include <libhal.h> -#include <dbus/dbus.h> -#include <dbus/dbus-glib.h> - -dbus_bool_t hal_mainloop_integration(LibHalContext *ctx, DBusError *error); -void ipod_device_set_global_main_context(GMainContext *ctx); - -#else -typedef void LibHalContext; -G_GNUC_INTERNAL gchar **libhal_manager_find_device_string_match (LibHalContext *hal_ctx, - const gchar *dev, - const gchar *str, - gint *vol_count, - void *error); -G_GNUC_INTERNAL void libhal_free_string_array (gchar **volumes); -G_GNUC_INTERNAL gboolean libhal_device_property_exists (LibHalContext *hal_ctx, - const gchar *vol, - const gchar *prop, - void *error); -G_GNUC_INTERNAL gboolean libhal_device_get_property_bool (LibHalContext *hal_ctx, - const gchar *vol, - const gchar *prop, - void *error); -G_GNUC_INTERNAL void libhal_ctx_shutdown (LibHalContext *hal_ctx, void *error); -G_GNUC_INTERNAL void libhal_ctx_free (LibHalContext *hal_ctx); -#endif - - -#endif /* HAL_COMMON_H */ diff --git a/src/ipod-device.c b/src/ipod-device.c deleted file mode 100644 index 411b182..0000000 --- a/src/ipod-device.c +++ /dev/null @@ -1,1832 +0,0 @@ -/* Time-stamp: <2006-03-09 21:50:38 jcs> -| -| Copyright (C) 2005 Jorg Schuler <jcsjcs at users sourceforge net> -| Part of the gtkpod project. -| -| URL: http://www.gtkpod.org/ -| URL: http://gtkpod.sourceforge.net/ -| -| -| The source is taken from libipoddevice, CVS version October 8 2005 -| (http://64.14.94.162/index.php/Libipoddevice). -| -| I decided not to make libgpod dependent on libipoddevice because -| the latter depends on libraries not widely available yet (libhal >= -| 0.5.2, glib >= 2.8). It is planned to replace these files with a -| libipoddevice dependence at some later time. -| -| The following changes were done: -| -| - libhal becomes optional (see #ifdef HAVE_LIBHAL sections) -| - g_mkdir_with_parents() is provided if not available (glib < 2.8) -| - publicly available functions were renamed from ipod_device_...() -| to itdb_device_...() -| -| Because of these changes only a limited amount of functionality is -| available. See ipod-device.h for summary. -| -| -| -| -| $Id$ -*/ -/* ex: set ts=4: */ -/*************************************************************************** -* ipod-device.c -* Copyright (C) 2005 Novell -* Written by Aaron Bockover <aaron@aaronbock.net> -****************************************************************************/ - -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2.1 of the GNU Lesser General Public - * License as published by the Free Software Foundation. - * - * 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 Lesser Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 - */ - - -/* JCS: Change from ipod_device... to itdb_device for public functions */ -#define ipod_device_get_type itdb_device_get_type -#define ipod_device_new itdb_device_new -#define ipod_device_rescan_disk itdb_device_rescan_disk -#define ipod_device_eject itdb_device_eject -#define ipod_device_reboot itdb_device_reboot -#define ipod_device_debug itdb_device_debug -#define ipod_device_save itdb_device_save -#define ipod_device_list_devices itdb_device_list_devices -#define ipod_device_list_device_udis itdb_device_list_device_udis - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#include "glib-compat.h" - -#include <stdlib.h> -#include <stdio.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <string.h> -#include <ctype.h> -#include <errno.h> - -#include "hal-common.h" -#include "ipod-device.h" - -#define GB 1024 - -typedef struct _IpodModel { - const gchar *model_number; - const guint64 capacity; - guint model_type; - guint generation; -} IpodModel; - - -static const IpodModel ipod_model_table [] = { - /* Handle idiots who hose their iPod file system, or - lucky people with iPods we don't yet know about*/ - {"Invalid", 0, MODEL_TYPE_INVALID, UNKNOWN_GENERATION}, - {"Unknown", 0, MODEL_TYPE_UNKNOWN, UNKNOWN_GENERATION}, - - /* First Generation */ - {"8513", 5 * GB, MODEL_TYPE_REGULAR, FIRST_GENERATION}, - {"8541", 5 * GB, MODEL_TYPE_REGULAR, FIRST_GENERATION}, - {"8697", 5 * GB, MODEL_TYPE_REGULAR, FIRST_GENERATION}, - {"8709", 10 * GB, MODEL_TYPE_REGULAR, FIRST_GENERATION}, - - /* Second Generation */ - {"8737", 10 * GB, MODEL_TYPE_REGULAR, SECOND_GENERATION}, - {"8740", 10 * GB, MODEL_TYPE_REGULAR, SECOND_GENERATION}, - {"8738", 20 * GB, MODEL_TYPE_REGULAR, SECOND_GENERATION}, - {"8741", 20 * GB, MODEL_TYPE_REGULAR, SECOND_GENERATION}, - - /* Third Generation */ - {"8976", 10 * GB, MODEL_TYPE_REGULAR, THIRD_GENERATION}, - {"8946", 15 * GB, MODEL_TYPE_REGULAR, THIRD_GENERATION}, - {"9460", 15 * GB, MODEL_TYPE_REGULAR, THIRD_GENERATION}, - {"9244", 20 * GB, MODEL_TYPE_REGULAR, THIRD_GENERATION}, - {"8948", 30 * GB, MODEL_TYPE_REGULAR, THIRD_GENERATION}, - {"9245", 40 * GB, MODEL_TYPE_REGULAR, THIRD_GENERATION}, - - - /* Fourth Generation */ - {"9282", 20 * GB, MODEL_TYPE_REGULAR, FOURTH_GENERATION}, - {"9787", 25 * GB, MODEL_TYPE_REGULAR_U2, FOURTH_GENERATION}, - {"9268", 40 * GB, MODEL_TYPE_REGULAR, FOURTH_GENERATION}, - {"A079", 20 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION}, - {"A127", 20 * GB, MODEL_TYPE_COLOR_U2, FOURTH_GENERATION}, - {"9830", 60 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION}, - - /* First Generation Mini */ - {"9160", 4 * GB, MODEL_TYPE_MINI, FIRST_GENERATION}, - {"9436", 4 * GB, MODEL_TYPE_MINI_BLUE, FIRST_GENERATION}, - {"9435", 4 * GB, MODEL_TYPE_MINI_PINK, FIRST_GENERATION}, - {"9434", 4 * GB, MODEL_TYPE_MINI_GREEN, FIRST_GENERATION}, - {"9437", 4 * GB, MODEL_TYPE_MINI_GOLD, FIRST_GENERATION}, - - /* Second Generation Mini */ - {"9800", 4 * GB, MODEL_TYPE_MINI, SECOND_GENERATION}, - {"9802", 4 * GB, MODEL_TYPE_MINI_BLUE, SECOND_GENERATION}, - {"9804", 4 * GB, MODEL_TYPE_MINI_PINK, SECOND_GENERATION}, - {"9806", 4 * GB, MODEL_TYPE_MINI_GREEN, SECOND_GENERATION}, - {"9801", 6 * GB, MODEL_TYPE_MINI, SECOND_GENERATION}, - {"9803", 6 * GB, MODEL_TYPE_MINI_BLUE, SECOND_GENERATION}, - {"9805", 6 * GB, MODEL_TYPE_MINI_PINK, SECOND_GENERATION}, - {"9807", 6 * GB, MODEL_TYPE_MINI_GREEN, SECOND_GENERATION}, - - /* Photo / Fourth Generation */ - {"9829", 30 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION}, - {"9585", 40 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION}, - {"9586", 60 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION}, - {"9830", 60 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION}, - - /* Shuffle / Fourth Generation */ - {"9724", GB / 2, MODEL_TYPE_SHUFFLE, FOURTH_GENERATION}, - {"9725", GB, MODEL_TYPE_SHUFFLE, FOURTH_GENERATION}, - - /* Nano / Fifth Generation */ - {"A350", GB * 1, MODEL_TYPE_NANO_WHITE, FIFTH_GENERATION}, - {"A352", GB * 1, MODEL_TYPE_NANO_BLACK, FIFTH_GENERATION}, - {"A004", GB * 2, MODEL_TYPE_NANO_WHITE, FIFTH_GENERATION}, - {"A099", GB * 2, MODEL_TYPE_NANO_BLACK, FIFTH_GENERATION}, - {"A005", GB * 4, MODEL_TYPE_NANO_WHITE, FIFTH_GENERATION}, - {"A107", GB * 4, MODEL_TYPE_NANO_BLACK, FIFTH_GENERATION}, - - /* Video / Fifth Generation */ - {"A002", GB * 30, MODEL_TYPE_VIDEO_WHITE, FIFTH_GENERATION}, - {"A146", GB * 30, MODEL_TYPE_VIDEO_BLACK, FIFTH_GENERATION}, - {"A003", GB * 60, MODEL_TYPE_VIDEO_WHITE, FIFTH_GENERATION}, - {"A147", GB * 60, MODEL_TYPE_VIDEO_BLACK, FIFTH_GENERATION}, - - /* HP iPods, need contributions for this table */ - {"E436", 40 * GB, MODEL_TYPE_REGULAR, FOURTH_GENERATION}, - {"S492", 30 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION}, - - {NULL, 0, 0, 0} -}; - -static const gchar *ipod_model_name_table [] = { - "Invalid", - "Unknown", - "Color", - "Color U2", - "Grayscale", - "Grayscale U2", - "Mini (Silver)", - "Mini (Blue)", - "Mini (Pink)", - "Mini (Green)", - "Mini (Gold)", - "Shuffle", - "Nano (White)", - "Nano (Black)", - "Video (White)", - "Video (Black)", - NULL -}; - -static const IpodArtworkFormat ipod_color_artwork_info[] = { - {IPOD_COVER_SMALL, 56, 56, 1017}, - {IPOD_COVER_LARGE, 140, 140, 1016}, - {IPOD_PHOTO_SMALL, 42, 30, 1009}, - {IPOD_PHOTO_LARGE, 130, 88, 1015}, - {IPOD_PHOTO_FULL_SCREEN, 220, 176, 1013}, - {IPOD_PHOTO_TV_SCREEN, 720, 480, 1019}, - {-1, -1, -1, -1} -}; - -static const IpodArtworkFormat ipod_nano_artwork_info[] = { - {IPOD_COVER_SMALL, 42, 42, 1031}, - {IPOD_COVER_LARGE, 100, 100, 1027}, - {IPOD_PHOTO_LARGE, 42, 37, 1032}, - {IPOD_PHOTO_FULL_SCREEN, 176, 132, 1023}, - {-1, -1, -1, -1} -}; - -static const IpodArtworkFormat ipod_video_artwork_info[] = { - {IPOD_COVER_SMALL, 100, 100, 1028}, - {IPOD_COVER_LARGE, 200, 200, 1029}, - {IPOD_PHOTO_SMALL, 50, 41, 1036}, - {IPOD_PHOTO_LARGE, 130, 88, 1015}, - {IPOD_PHOTO_FULL_SCREEN, 320, 240, 1024}, - {IPOD_PHOTO_TV_SCREEN, 720, 480, 1019}, - {-1, -1, -1, -1} -}; - -/* This will be indexed using a value from the MODEL_TYPE enum */ -static const IpodArtworkFormat *ipod_artwork_info_table[] = { - NULL, /* Invalid */ - NULL, /* Unknown */ - ipod_color_artwork_info, /* Color */ - ipod_color_artwork_info, /* Color U2 */ - NULL, /* Grayscale */ - NULL, /* Grayscale U2 */ - NULL, /* Mini (Silver) */ - NULL, /* Mini (Blue) */ - NULL, /* Mini (Pink) */ - NULL, /* Mini (Green) */ - NULL, /* Mini (Gold) */ - NULL, /* Shuffle */ - ipod_nano_artwork_info, /* Nano (White) */ - ipod_nano_artwork_info, /* Nano (Black) */ - ipod_video_artwork_info, /* Video (White) */ - ipod_video_artwork_info /* Video (Black) */ -}; - - -#define g_free_if_not_null(o) \ - if(o != NULL) { \ - g_free(o); \ - o = NULL; \ - } - -static const gchar *sysinfo_field_names [] = { - "pszSerialNumber", - "ModelNumStr", - "visibleBuildID", - NULL -}; - -static gchar *sysinfo_arr_get_dup(gchar *arr[], const gchar *key) -{ - gint i = 0; - - for(i = 0; sysinfo_field_names[i] != NULL; i++) { - if(g_strcasecmp(sysinfo_field_names[i], key) == 0) - return g_strdup(arr[i]); - } - - return NULL; -} - - -#if ((GLIB_MAJOR_VERSION <= 2) && (GLIB_MINOR_VERSION < 8)) -/** - * g_mkdir_with_parents: - * @pathname: a pathname in the GLib file name encoding - * @mode: permissions to use for newly created directories - * - * Create a directory if it doesn't already exist. Create intermediate - * parent directories as needed, too. - * - * Returns: 0 if the directory already exists, or was successfully - * created. Returns -1 if an error occurred, with errno set. - * - * Since: 2.8 (copied from GLIB version 2.8 - JCS) - */ -static int -g_mkdir_with_parents (const gchar *pathname, - int mode) -{ - gchar *fn, *p; - - if (pathname == NULL || *pathname == '\0') - { - errno = EINVAL; - return -1; - } - - fn = g_strdup (pathname); - - if (g_path_is_absolute (fn)) - p = (gchar *) g_path_skip_root (fn); - else - p = fn; - - do - { - while (*p && !G_IS_DIR_SEPARATOR (*p)) - p++; - - if (!*p) - p = NULL; - else - *p = '\0'; - - if (!g_file_test (fn, G_FILE_TEST_EXISTS)) - { - if (g_mkdir (fn, mode) == -1) - { - int errno_save = errno; - g_free (fn); - errno = errno_save; - return -1; - } - } - else if (!g_file_test (fn, G_FILE_TEST_IS_DIR)) - { - g_free (fn); - errno = ENOTDIR; - return -1; - } - if (p) - { - *p++ = G_DIR_SEPARATOR; - while (*p && G_IS_DIR_SEPARATOR (*p)) - p++; - } - } - while (p); - - g_free (fn); - - return 0; -} -#endif - - -static void ipod_device_class_init(IpodDeviceClass *klass); -static void ipod_device_init(IpodDevice *sp); -static void ipod_device_finalize(GObject *object); - -static gchar *ipod_device_read_device_info_string(FILE *fd); -static void ipod_device_write_device_info_string(gchar *str, FILE *fd); - -static gboolean ipod_device_reload(IpodDevice *device); -static void ipod_device_construct_paths(IpodDevice *device); -static gboolean ipod_device_info_load(IpodDevice *device); -static guint ipod_device_detect_model(IpodDevice *device); -static gboolean ipod_device_detect_volume_info(IpodDevice *device); -static LibHalContext *ipod_device_hal_initialize(void); -static void ipod_device_detect_volume_used(IpodDevice *device); -static guint64 ipod_device_dir_size(const gchar *path); -static gboolean ipod_device_read_sysinfo(IpodDevice *device); -static gboolean ipod_device_detect_writeable(IpodDevice *device); -static void ipod_device_restore_reboot_preferences(IpodDevice *device); - -struct IpodDevicePrivate { - LibHalContext *hal_context; - - /* Paths */ - gchar *device_path; - gchar *mount_point; - gchar *control_path; - gchar *hal_volume_id; - - gchar *adv_capacity; - guint model_index; - - /* DeviceInfo Fields (All Devices) */ - gchar *device_name; - gchar *user_name; - gchar *host_name; - - /* Volume Size/Usage */ - guint64 volume_size; - guint64 volume_available; - guint64 volume_used; - - /* System Info */ - gchar *serial_number; - gchar *model_number; - gchar *firmware_version; - - gchar *volume_uuid; - gchar *volume_label; - - /* Fresh from the factory/restore? */ - gboolean is_new; - - /* Safety */ - gboolean is_ipod; - gboolean can_write; -}; - -static GObjectClass *parent_class = NULL; - -/* GObject Class Specific Methods */ - -GType -ipod_device_get_type() -{ - static GType type = 0; - - if(type == 0) { - static const GTypeInfo our_info = { - sizeof (IpodDeviceClass), - NULL, - NULL, - (GClassInitFunc)ipod_device_class_init, - NULL, - NULL, - sizeof (IpodDevice), - 0, - (GInstanceInitFunc)ipod_device_init, - }; - - type = g_type_register_static(G_TYPE_OBJECT, - "IpodDevice", &our_info, 0); - } - - return type; -} - -static void -ipod_device_get_property(GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - IpodDevice *device = IPOD_DEVICE(object); - - switch(prop_id) { - case PROP_HAL_CONTEXT: - g_value_set_pointer(value, device->priv->hal_context); - break; - case PROP_HAL_VOLUME_ID: - g_value_set_string(value, device->priv->hal_volume_id); - break; - case PROP_MOUNT_POINT: - g_value_set_string(value, device->priv->mount_point); - break; - case PROP_DEVICE_PATH: - g_value_set_string(value, device->priv->device_path); - break; - case PROP_CONTROL_PATH: - g_value_set_string(value, device->priv->control_path); - break; - case PROP_DEVICE_MODEL: - g_value_set_uint(value, - ipod_model_table[device->priv->model_index].model_type); - break; - case PROP_DEVICE_MODEL_STRING: - g_value_set_string(value, - ipod_model_name_table[ipod_model_table[ - device->priv->model_index].model_type]); - break; - case PROP_DEVICE_GENERATION: - g_value_set_uint(value, - ipod_model_table[device->priv->model_index].generation); - break; - case PROP_ADVERTISED_CAPACITY: - g_value_set_string(value, device->priv->adv_capacity); - break; - case PROP_DEVICE_NAME: - g_value_set_string(value, device->priv->device_name); - break; - case PROP_USER_NAME: - g_value_set_string(value, device->priv->user_name); - break; - case PROP_HOST_NAME: - g_value_set_string(value, device->priv->host_name); - break; - case PROP_VOLUME_SIZE: - g_value_set_uint64(value, device->priv->volume_size); - break; - case PROP_VOLUME_AVAILABLE: - g_value_set_uint64(value, device->priv->volume_available); - break; - case PROP_VOLUME_USED: - g_value_set_uint64(value, device->priv->volume_used); - break; - case PROP_IS_IPOD: - g_value_set_boolean(value, device->priv->is_ipod); - break; - case PROP_IS_NEW: - g_value_set_boolean(value, device->priv->is_new); - break; - case PROP_SERIAL_NUMBER: - g_value_set_string(value, device->priv->serial_number); - break; - case PROP_MODEL_NUMBER: - g_value_set_string(value, device->priv->model_number); - break; - case PROP_FIRMWARE_VERSION: - g_value_set_string(value, device->priv->firmware_version); - break; - case PROP_VOLUME_UUID: - g_value_set_string(value, device->priv->volume_uuid); - break; - case PROP_VOLUME_LABEL: - g_value_set_string(value, device->priv->volume_label); - break; - case PROP_CAN_WRITE: - g_value_set_boolean(value, device->priv->can_write); - break; - case PROP_ARTWORK_FORMAT: - g_value_set_pointer(value, - (gpointer)ipod_artwork_info_table[ipod_model_table[ - device->priv->model_index].model_type]); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -ipod_device_set_property(GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - IpodDevice *device = IPOD_DEVICE(object); - const gchar *str; - gchar **volumes; - gint volume_count; - - g_return_if_fail (device); - - switch(prop_id) { - case PROP_MOUNT_POINT: - case PROP_DEVICE_PATH: - case PROP_HAL_VOLUME_ID: - str = g_value_get_string(value); - volumes = NULL; - if (device->priv->hal_context) - { - volumes = libhal_manager_find_device_string_match( - device->priv->hal_context, "block.device", str, - &volume_count, NULL); - if(volume_count == 0) - { - libhal_free_string_array(volumes); - volumes = libhal_manager_find_device_string_match( - device->priv->hal_context, "volume.mount_point", - str, &volume_count, NULL); - } - if(volume_count >= 1) - { - str = volumes[0]; - } - } -#ifdef HAVE_LIBHAL - g_free_if_not_null(device->priv->hal_volume_id); - device->priv->hal_volume_id = g_strdup (str); -#else -/* JCS for libgpod */ - g_free (device->priv->mount_point); - device->priv->mount_point = g_strdup (str); -/* end JCS for libgpod */ -#endif - if (volumes) - libhal_free_string_array(volumes); - device->priv->is_ipod = ipod_device_reload(device); - break; - case PROP_DEVICE_NAME: - str = g_value_get_string(value); - g_free_if_not_null(device->priv->device_name); - device->priv->device_name = g_strdup(str); - break; - case PROP_USER_NAME: - str = g_value_get_string(value); - g_free_if_not_null(device->priv->user_name); - device->priv->user_name = g_strdup(str); - break; - case PROP_HOST_NAME: - str = g_value_get_string(value); - g_free_if_not_null(device->priv->host_name); - device->priv->host_name = g_strdup(str); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); - break; - } -} - -static void -ipod_device_class_init(IpodDeviceClass *klass) -{ - GParamSpec *hal_context_param; - GParamSpec *hal_volume_id_param; - GParamSpec *mount_point_param; - GParamSpec *device_path_param; - GParamSpec *control_path_param; - GParamSpec *device_model_param; - GParamSpec *device_model_string_param; - GParamSpec *device_name_param; - GParamSpec *user_name_param; - GParamSpec *host_name_param; - GParamSpec *volume_size_param; - GParamSpec *volume_available_param; - GParamSpec *volume_used_param; - GParamSpec *is_ipod_param; - GParamSpec *is_new_param; - GParamSpec *serial_number_param; - GParamSpec *model_number_param; - GParamSpec *firmware_version_param; - GParamSpec *volume_uuid_param; - GParamSpec *volume_label_param; - GParamSpec *can_write_param; - GParamSpec *device_generation_param; - GParamSpec *advertised_capacity_param; - GParamSpec *artwork_format_param; - - GObjectClass *class = G_OBJECT_CLASS(klass); - - parent_class = g_type_class_peek_parent(klass); - class->finalize = ipod_device_finalize; - - hal_context_param = g_param_spec_pointer("hal-context", "HAL Context", - "LibHalContext handle", G_PARAM_READABLE); - - hal_volume_id_param = g_param_spec_string("hal-volume-id", "HAL Volume ID", - "Volume ID of a device in HAL", - NULL, G_PARAM_READWRITE); - - mount_point_param = g_param_spec_string("mount-point", "Mount Point", - "Where iPod is mounted (parent of an iPod_Control directory)", - NULL, G_PARAM_READWRITE); - - device_path_param = g_param_spec_string("device-path", "Device Path", - "Path to raw iPod Device (/dev/sda2, for example)", - NULL, G_PARAM_READWRITE); - - control_path_param = g_param_spec_string("control-path", - "iPod_Control Path","Full path to iPod_Control", - NULL, G_PARAM_READABLE); - - device_model_param = g_param_spec_uint("device-model", "Device Model", - "Type of iPod (Regular, Photo, Shuffle)", 0, 2, 0, G_PARAM_READABLE); - - device_model_string_param = g_param_spec_string("device-model-string", - "Device Model String", "String type of iPod (Regular, Shuffle)", - NULL, G_PARAM_READABLE); - - device_name_param = g_param_spec_string("device-name", "Device Name", - "The user-assigned name of their iPod", NULL, G_PARAM_READWRITE); - - user_name_param = g_param_spec_string("user-name", "User Name", - "On Windows, Maybe Mac, the user account owning the iPod", - NULL, G_PARAM_READWRITE); - - host_name_param = g_param_spec_string("host-name", "Host Name", - "On Windows, Maybe Mac, the host/computer name owning the iPod", - NULL, G_PARAM_READWRITE); - - volume_size_param = g_param_spec_uint64("volume-size", "Volume Size", - "Total size of the iPod's hard drive", 0, G_MAXLONG, 0, - G_PARAM_READABLE); - - volume_available_param = g_param_spec_uint64("volume-available", - "Volume Available", "Available space on the iPod", - 0, G_MAXLONG, 0, G_PARAM_READABLE); - - volume_used_param = g_param_spec_uint64("volume-used", "Volume Used", - "How much space has been used", 0, G_MAXLONG, 0, G_PARAM_READABLE); - - is_ipod_param = g_param_spec_boolean("is-ipod", "Is iPod", - "If all device checks are okay, then this is true", - FALSE, G_PARAM_READABLE); - - is_new_param = g_param_spec_boolean("is-new", "Is iPod", - "If device is fresh from factory/restore, this is true", - FALSE, G_PARAM_READABLE); - - serial_number_param = g_param_spec_string("serial-number", "Serial Number", - "Serial Number of the iPod", - NULL, G_PARAM_READABLE); - - model_number_param = g_param_spec_string("model-number", "Model Number", - "Model Number of the iPod", - NULL, G_PARAM_READABLE); - - firmware_version_param = g_param_spec_string("firmware-version", - "Firmware Version", "iPod Firmware Version", - NULL, G_PARAM_READABLE); - - volume_uuid_param = g_param_spec_string("volume-uuid", "Volume UUID", - "Volume UUID of the iPod", - NULL, G_PARAM_READABLE); - - volume_label_param = g_param_spec_string("volume-label", "Volume Label", - "Volume Label of the iPod", - NULL, G_PARAM_READABLE); - - can_write_param = g_param_spec_boolean("can-write", "Can Write", - "True if device can be written to (mounted read/write)", - FALSE, G_PARAM_READABLE); - - advertised_capacity_param = g_param_spec_string("advertised-capacity", - "Advertised Capacity", "Apple Marketed/Advertised Capacity String", - NULL, G_PARAM_READABLE); - - device_generation_param = g_param_spec_uint("device-generation", - "Generation", "Generation of the iPod", - 0, G_MAXUINT, 0, G_PARAM_READABLE); - - artwork_format_param = g_param_spec_pointer("artwork-formats", - "Artwork Format", "Support Artwork Formats", G_PARAM_READABLE); - - class->set_property = ipod_device_set_property; - class->get_property = ipod_device_get_property; - g_object_class_install_property(class, PROP_HAL_CONTEXT, - hal_context_param); - - g_object_class_install_property(class, PROP_HAL_VOLUME_ID, - hal_volume_id_param); - - g_object_class_install_property(class, PROP_MOUNT_POINT, - mount_point_param); - - g_object_class_install_property(class, PROP_DEVICE_PATH, - device_path_param); - - g_object_class_install_property(class, PROP_CONTROL_PATH, - control_path_param); - - g_object_class_install_property(class, PROP_DEVICE_MODEL, - device_model_param); - - g_object_class_install_property(class, PROP_DEVICE_MODEL_STRING, - device_model_string_param); - - g_object_class_install_property(class, PROP_DEVICE_NAME, - device_name_param); - - g_object_class_install_property(class, PROP_USER_NAME, - user_name_param); - - g_object_class_install_property(class, PROP_HOST_NAME, - host_name_param); - - g_object_class_install_property(class, PROP_VOLUME_SIZE, - volume_size_param); - - g_object_class_install_property(class, PROP_VOLUME_AVAILABLE, - volume_available_param); - - g_object_class_install_property(class, PROP_VOLUME_USED, - volume_used_param); - - g_object_class_install_property(class, PROP_IS_IPOD, is_ipod_param); - - g_object_class_install_property(class, PROP_IS_NEW, is_new_param); - - g_object_class_install_property(class, PROP_SERIAL_NUMBER, - serial_number_param); - - g_object_class_install_property(class, PROP_MODEL_NUMBER, - model_number_param); - - g_object_class_install_property(class, PROP_FIRMWARE_VERSION, - firmware_version_param); - - g_object_class_install_property(class, PROP_VOLUME_UUID, - volume_uuid_param); - - g_object_class_install_property(class, PROP_VOLUME_LABEL, - volume_label_param); - - g_object_class_install_property(class, PROP_CAN_WRITE, - can_write_param); - - g_object_class_install_property(class, PROP_DEVICE_GENERATION, - device_generation_param); - - g_object_class_install_property(class, PROP_ADVERTISED_CAPACITY, - advertised_capacity_param); - - g_object_class_install_property(class, PROP_ARTWORK_FORMAT, - artwork_format_param); - -} - -static void -ipod_device_init(IpodDevice *device) -{ - device->priv = g_new0(IpodDevicePrivate, 1); - - device->priv->hal_context = ipod_device_hal_initialize(); - - device->priv->hal_volume_id = NULL; - device->priv->mount_point = NULL; - device->priv->device_path = NULL; - device->priv->control_path = NULL; - device->priv->device_name = NULL; - device->priv->user_name = NULL; - device->priv->host_name = NULL; - device->priv->adv_capacity = NULL; - device->priv->serial_number = NULL; - device->priv->model_number = NULL; - device->priv->firmware_version = NULL; - device->priv->volume_uuid = NULL; - device->priv->volume_label = NULL; - - device->priv->volume_size = 0; - device->priv->volume_available = 0; - device->priv->volume_used = 0; - - device->priv->is_new = FALSE; - device->priv->can_write = FALSE; -} - -static void -ipod_device_finalize(GObject *object) -{ - IpodDevice *device = IPOD_DEVICE(object); - - /* Free private members, etc. */ - g_free_if_not_null(device->priv->hal_volume_id); - g_free_if_not_null(device->priv->device_path); - g_free_if_not_null(device->priv->mount_point); - g_free_if_not_null(device->priv->control_path); - g_free_if_not_null(device->priv->device_name); - g_free_if_not_null(device->priv->user_name); - g_free_if_not_null(device->priv->host_name); - g_free_if_not_null(device->priv->adv_capacity); - g_free_if_not_null(device->priv->serial_number); - g_free_if_not_null(device->priv->model_number); - g_free_if_not_null(device->priv->firmware_version); - g_free_if_not_null(device->priv->volume_uuid); - g_free_if_not_null(device->priv->volume_label); - - if(device->priv->hal_context != NULL) { - libhal_ctx_shutdown(device->priv->hal_context, NULL); - libhal_ctx_free(device->priv->hal_context); - } - g_free(device->priv); - G_OBJECT_CLASS(parent_class)->finalize(object); -} - -/* PRIVATE METHODS */ - -LibHalContext * -ipod_device_hal_initialize() -{ -#ifdef HAVE_LIBHAL - LibHalContext *hal_context; - DBusError error; - DBusConnection *dbus_connection; - char **devices; - gint device_count; - - hal_context = libhal_ctx_new(); - if(hal_context == NULL) - return NULL; - - dbus_error_init(&error); - dbus_connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); - if(dbus_error_is_set(&error)) { - dbus_error_free(&error); - libhal_ctx_free(hal_context); - return NULL; - } - - libhal_ctx_set_dbus_connection(hal_context, dbus_connection); - - if(!libhal_ctx_init(hal_context, &error)) { - dbus_error_free(&error); - libhal_ctx_free(hal_context); - return NULL; - } - - devices = libhal_get_all_devices(hal_context, &device_count, NULL); - if(devices == NULL) { - libhal_ctx_shutdown(hal_context, NULL); - libhal_ctx_free(hal_context); - hal_context = NULL; - return NULL; - } - - libhal_free_string_array(devices); - - return hal_context; -#else - return NULL; -#endif -} - -gboolean -ipod_device_reload(IpodDevice *device) -{ - g_return_val_if_fail(IS_IPOD_DEVICE(device), FALSE); - - device->priv->model_index = 0; - - if(!ipod_device_detect_volume_info(device)) - return FALSE; - - ipod_device_construct_paths(device); - - device->priv->is_new = !ipod_device_info_load(device); - - ipod_device_detect_volume_used(device); - ipod_device_detect_writeable(device); - ipod_device_read_sysinfo(device); - ipod_device_detect_model(device); - ipod_device_restore_reboot_preferences(device); - - return device->priv->model_index != 0; -} - -void -ipod_device_construct_paths(IpodDevice *device) -{ - int len; - - g_return_if_fail(IS_IPOD_DEVICE(device)); - g_return_if_fail(device->priv->mount_point != NULL); - - len = strlen(device->priv->mount_point); - if(device->priv->mount_point[len - 1] == '/') - device->priv->mount_point[len - 1] = '\0'; - - if(strlen(device->priv->mount_point) == 0) - return; - - device->priv->control_path = g_strdup_printf("%s/%s", - device->priv->mount_point, "iPod_Control/"); -} - -gchar * -ipod_device_read_device_info_string(FILE *fd) -{ - gshort length; - gunichar2 *utf16; - gchar *utf8; - - if (fread(&length, sizeof(gshort), 1, fd) != 1) - return NULL; - - if(length <= 0) - return NULL; - - utf16 = (gunichar2 *)g_malloc(length * sizeof(gunichar2)); - if (fread(utf16, sizeof(gunichar2), length, fd) != length) - return NULL; - - if(utf16 == NULL) - return NULL; - - utf8 = g_utf16_to_utf8(utf16, length, NULL, NULL, NULL); - - g_free(utf16); - utf16 = NULL; - - return utf8; -} - -void -ipod_device_write_device_info_string(gchar *str, FILE *fd) -{ - gunichar2 *unistr; - gshort length; - size_t res; - - if(str == NULL) - return; - - length = strlen(str); - unistr = g_utf8_to_utf16(str, length, NULL, NULL, NULL); - - length = length > 0x198 ? 0x198 : length; - - /* FIXME: we do not check if the write was successful */ - res = fwrite(&length, 2, 1, fd); - res = fwrite(unistr, 2, length, fd); - - g_free(unistr); -} - -gboolean -ipod_device_read_sysinfo(IpodDevice *device) -{ - gchar *field_values[sizeof(sysinfo_field_names) + 1]; - gchar *tmp, *path, buf[512]; - gint i, name_len; - FILE *fd; - - g_return_val_if_fail(IS_IPOD_DEVICE(device), FALSE); - - path = g_strdup_printf("%sDevice/SysInfo", - device->priv->control_path); - - fd = fopen(path, "r"); - if(fd == NULL) { - g_free(path); - return FALSE; - } - - while(fgets(buf, sizeof(buf), fd)) { - buf[strlen(buf) - 1] = '\0'; - - for(i = 0; sysinfo_field_names[i] != NULL; i++) { - name_len = strlen(sysinfo_field_names[i]); - if(strncasecmp(buf, sysinfo_field_names[i], name_len) == 0) { - field_values[i] = strdup(buf + name_len + 2); - if(strncasecmp(field_values[i], "0x", 2) == 0) { - if((tmp = strstr(field_values[i], "(")) != NULL) { - field_values[i] = tmp + 1; - field_values[i][strlen(field_values[i]) - 1] = '\0'; - } - } - - field_values[i] = g_strdup(field_values[i]); - } - } - } - - fclose(fd); - - device->priv->serial_number = sysinfo_arr_get_dup(field_values, - "pszSerialNumber"); - device->priv->model_number = sysinfo_arr_get_dup(field_values, - "ModelNumStr"); - device->priv->firmware_version = sysinfo_arr_get_dup(field_values, - "visibleBuildID"); - - g_free(path); - - return TRUE; -} - -gboolean -ipod_device_info_load(IpodDevice *device) -{ - gchar *path; - FILE *fd; - gint intres; - - g_return_val_if_fail(IS_IPOD_DEVICE(device), FALSE); - - path = g_strdup_printf("%siTunes/DeviceInfo", - device->priv->control_path); - - fd = fopen(path, "r"); - if(fd == NULL) { - g_free(path); - return FALSE; - } - - device->priv->device_name = ipod_device_read_device_info_string(fd); - if(device->priv->device_name == NULL) - device->priv->device_name = g_strdup("iPod"); - - intres=fseek(fd, 0x200, SEEK_SET); - device->priv->user_name = ipod_device_read_device_info_string(fd); - - intres=fseek(fd, 0x400, SEEK_SET); - device->priv->host_name = ipod_device_read_device_info_string(fd); - - fclose(fd); - g_free(path); - - return TRUE; -} - -gboolean -ipod_device_detect_writeable(IpodDevice *device) -{ - FILE *fp; - gchar *itunes_dir, *music_dir, *itunesdb_path; - struct stat finfo; - - g_return_val_if_fail(IS_IPOD_DEVICE(device), FALSE); - - device->priv->can_write = FALSE; - - itunes_dir = g_strdup_printf("%siTunes", device->priv->control_path); - - if(!g_file_test(itunes_dir, G_FILE_TEST_IS_DIR)) { - if(g_mkdir_with_parents(itunes_dir, 0755) != 0) { - g_free(itunes_dir); - return FALSE; - } - } - - itunesdb_path = g_strdup_printf("%s/iTunesDB", itunes_dir); - - if((fp = fopen(itunesdb_path, "a+")) != NULL) { - device->priv->can_write = TRUE; - fclose(fp); - - memset(&finfo, 0, sizeof(finfo)); - if(stat(itunesdb_path, &finfo) == 0) { - if(finfo.st_size == 0) { - unlink(itunesdb_path); - } - } - } else { - g_free(itunes_dir); - g_free(itunesdb_path); - return FALSE; - } - - music_dir = g_strdup_printf("%sMusic", device->priv->control_path); - - if(!g_file_test(music_dir, G_FILE_TEST_IS_DIR)) { - device->priv->can_write = g_mkdir_with_parents(music_dir, 0755) == 0; - } - - g_free(itunes_dir); - g_free(itunesdb_path); - g_free(music_dir); - - return device->priv->can_write; -} - -static gint -ipod_device_get_model_index_from_table(const gchar *_model_num) -{ - gint i; - gchar *model_num = g_strdup(_model_num); - gchar *p = model_num; - - if(isalpha(model_num[0])) - p++; - - for(i = 2; ipod_model_table[i].model_number != NULL; i++) { - if(g_strncasecmp(p, ipod_model_table[i].model_number, 4) == 0) { - g_free(model_num); - return i; - } - } - - g_free(model_num); - return 1; -} - -guint -ipod_device_detect_model(IpodDevice *device) -{ - gint i; - guint64 adv, act; - gint cap; - - g_return_val_if_fail(IS_IPOD_DEVICE(device), 0); - - device->priv->model_index = 0; - - /* Shuffle! */ - if(device->priv->model_number == NULL) { - for(i = 2; ipod_model_table[i].model_number != NULL; i++) { - if(ipod_model_table[i].model_type != MODEL_TYPE_SHUFFLE) - continue; - - cap = ipod_model_table[i].capacity; - adv = cap * 1048576; - act = device->priv->volume_size; - - if((adv - act) / 1048576 < 50) { - device->priv->model_index = i; - device->priv->model_number = g_strdup_printf("M%s", - ipod_model_table[i].model_number); - - device->priv->adv_capacity = g_strdup_printf("%d %s", - cap < 1024 ? cap : cap / 1024, - cap < 1024 ? "MB" : "GB"); - break; - } - } - } else { - /* Anything Else */ - device->priv->model_index = - ipod_device_get_model_index_from_table(device->priv->model_number); - - cap = ipod_model_table[device->priv->model_index].capacity; - - device->priv->adv_capacity = g_strdup_printf("%d %s", - cap < 1024 ? cap : cap / 1024, - cap < 1024 ? "MB" : "GB"); - } - - return device->priv->model_index; -} - -void -ipod_device_restore_reboot_preferences(IpodDevice *device) -{ - gchar *backup_prefs, *prefs; - - backup_prefs = g_strdup_printf("%s/.Reboot_Preferences", - device->priv->control_path); - prefs = g_strdup_printf("%s/Device/Preferences", - device->priv->control_path); - - g_return_if_fail(IS_IPOD_DEVICE(device)); - - if(g_file_test(backup_prefs, G_FILE_TEST_EXISTS)) { - unlink(prefs); - g_rename(backup_prefs, prefs); - } -} - -gboolean -ipod_device_detect_volume_info(IpodDevice *device) -{ -#ifdef HAVE_LIBHAL - LibHalContext *hal_context; - gchar **volumes; - gchar *hd_mount_point, *hd_device_path; - gchar *hd_hal_id = NULL, *maybe_hd_hal_id = NULL; - gint volume_count, i; - - g_return_val_if_fail(IS_IPOD_DEVICE(device), FALSE); - hal_context = device->priv->hal_context; - - g_free_if_not_null(device->priv->device_path); - g_free_if_not_null(device->priv->mount_point); - device->priv->volume_size = 0; - - if(!libhal_device_exists(hal_context, device->priv->hal_volume_id, NULL)) { - /* For testing/debugging... we don't have a real device, but - the location may be a directory containing an iPod image */ - if(g_strncasecmp(device->priv->hal_volume_id, "/dev/", 5) == 0 || - device->priv->hal_volume_id[0] != '/') - return FALSE; - - g_free_if_not_null(device->priv->mount_point); - device->priv->mount_point = g_strdup(device->priv->hal_volume_id); - - g_free_if_not_null(device->priv->hal_volume_id); - g_free_if_not_null(device->priv->device_path); - - /* Let's find out about the disk drive containing our image */ - - volumes = libhal_manager_find_device_string_match(hal_context, - "info.category", "volume", &volume_count, NULL); - - for(i = 0; i < volume_count; i++) { - if(!libhal_device_property_exists(hal_context, - volumes[i], "volume.is_mounted", NULL) || - !libhal_device_get_property_bool(hal_context, - volumes[i], "volume.is_mounted", NULL)) { - continue; - } - - hd_mount_point = libhal_device_get_property_string(hal_context, - volumes[i], "volume.mount_point", NULL); - - if(g_strncasecmp(hd_mount_point, device->priv->mount_point, - strlen(hd_mount_point)) != 0) - continue; - - if(g_strcasecmp(hd_mount_point, "/") == 0) - maybe_hd_hal_id = volumes[i]; - else - hd_hal_id = volumes[i]; - } - - if(hd_hal_id == NULL && maybe_hd_hal_id != NULL) - hd_hal_id = maybe_hd_hal_id; - - if(hd_hal_id == NULL) { - libhal_free_string_array(volumes); - return FALSE; - } - - if(!libhal_device_exists(hal_context, hd_hal_id, NULL)) { - libhal_free_string_array(volumes); - return FALSE; - } - - hd_device_path = libhal_device_get_property_string(hal_context, - hd_hal_id, "block.device", NULL); - - device->priv->hal_volume_id = g_strdup(hd_hal_id); - device->priv->device_path = g_strdup(hd_device_path); - device->priv->volume_size = libhal_device_get_property_uint64( - hal_context, hd_hal_id, "volume.size", NULL); - - libhal_free_string_array(volumes); - - return TRUE; - } - - if(!libhal_device_property_exists(hal_context, - device->priv->hal_volume_id, "volume.is_mounted", NULL) - || !libhal_device_get_property_bool(hal_context, - device->priv->hal_volume_id, "volume.is_mounted", NULL)) { - return FALSE; - } - - if(libhal_device_property_exists(hal_context, device->priv->hal_volume_id, - "block.device", NULL)) - device->priv->device_path = libhal_device_get_property_string( - hal_context, device->priv->hal_volume_id, "block.device", NULL); - - if(libhal_device_property_exists(hal_context, device->priv->hal_volume_id, - "volume.mount_point", NULL)) - device->priv->mount_point = libhal_device_get_property_string( - hal_context, device->priv->hal_volume_id, - "volume.mount_point", NULL); - - if(libhal_device_property_exists(hal_context, device->priv->hal_volume_id, - "volume.size", NULL)) - device->priv->volume_size = libhal_device_get_property_uint64( - hal_context, device->priv->hal_volume_id, "volume.size", NULL); - - if(libhal_device_property_exists(hal_context, device->priv->hal_volume_id, - "volume.uuid", NULL)) { - device->priv->volume_uuid = libhal_device_get_property_string( - hal_context, device->priv->hal_volume_id, - "volume.uuid", NULL); - - if(strlen(device->priv->volume_uuid) == 0) { - g_free(device->priv->volume_uuid); - device->priv->volume_uuid = NULL; - } - } - - if(libhal_device_property_exists(hal_context, device->priv->hal_volume_id, - "volume.label", NULL)) - device->priv->volume_label = libhal_device_get_property_string( - hal_context, device->priv->hal_volume_id, - "volume.label", NULL); -#endif - return TRUE; -} - -void -ipod_device_detect_volume_used(IpodDevice *device) -{ - device->priv->volume_used = - ipod_device_dir_size(device->priv->mount_point); - device->priv->volume_available = device->priv->volume_size - - device->priv->volume_used; -} - -static void -_ipod_device_dir_size(const gchar *path, guint64 *total_size) -{ - GDir *dir; - const gchar *next_path; - gchar *fullpath; - struct stat finfo; - - if((dir = g_dir_open(path, 0, NULL)) == NULL) - return; - - while((next_path = g_dir_read_name(dir)) != NULL) { - fullpath = g_strdup_printf("%s/%s", path, next_path); - - if(g_file_test(fullpath, G_FILE_TEST_IS_DIR)) - _ipod_device_dir_size(fullpath, total_size); - else - *total_size += stat(fullpath, &finfo) == 0 ? finfo.st_size : 0; - - g_free(fullpath); - fullpath = NULL; - } - - g_dir_close(dir); -} - -guint64 -ipod_device_dir_size(const gchar *path) -{ - guint64 retsize, *size = g_new(guint64, 1); - *size = 0; - _ipod_device_dir_size(path, size); - retsize = *size; - g_free(size); - return retsize; -} - -#ifdef HAVE_LIBHAL -static gboolean -ipod_device_has_open_fd(IpodDevice *device) -{ - GDir *dir, *fddir; - gchar *fdpath, *fdidpath, *realpath; - const gchar *procpath, *fdid; - - g_return_val_if_fail(IS_IPOD_DEVICE(device), FALSE); - - if((dir = g_dir_open("/proc", 0, NULL)) == NULL) - return FALSE; - - while((procpath = g_dir_read_name(dir)) != NULL) { - if(atoi(procpath) <= 0) - continue; - - fdpath = g_strdup_printf("/proc/%s/fd", procpath); - - if(!g_file_test(fdpath, G_FILE_TEST_IS_DIR)) { - g_free(fdpath); - continue; - } - - if((fddir = g_dir_open(fdpath, 0, NULL)) == NULL) { - g_free(fdpath); - continue; - } - - while((fdid = g_dir_read_name(fddir)) != NULL) { - fdidpath = g_strdup_printf("%s/%s", fdpath, fdid); - realpath = g_file_read_link(fdidpath, NULL); - - if(realpath == NULL) { - g_free(fdidpath); - continue; - } - - if(g_strncasecmp(realpath, device->priv->mount_point, - strlen(device->priv->mount_point)) == 0) { - g_dir_close(fddir); - g_dir_close(dir); - g_free(realpath); - g_free(fdidpath); - return TRUE; - } - - g_free(realpath); - g_free(fdidpath); - } - - g_dir_close(fddir); - } - - g_dir_close(dir); - - return FALSE; -} - -/* modded from g-v-m */ -static int -ipod_device_run_command(IpodDevice *device, const char *command, - GError **error_out) -{ - char *path; - const char *inptr, *start; - GError *error = NULL; - GString *exec; - char *argv[4]; - int status = 0; - - exec = g_string_new(NULL); - - /* perform s/%d/device/, s/%m/mount_point/ and s/%h/udi/ */ - start = inptr = command; - while((inptr = strchr (inptr, '%')) != NULL) { - g_string_append_len(exec, start, inptr - start); - inptr++; - switch (*inptr) { - case 'd': - g_string_append(exec, device->priv->device_path ? - device->priv->device_path : ""); - break; - case 'm': - if(device->priv->mount_point) { - path = g_shell_quote(device->priv->mount_point); - g_string_append(exec, path); - g_free(path); - } else { - g_string_append(exec, "\"\""); - } - break; - case 'h': - g_string_append(exec, device->priv->hal_volume_id); - break; - case '%': - g_string_append_c(exec, '%'); - break; - default: - g_string_append_c(exec, '%'); - if(*inptr) - g_string_append_c(exec, *inptr); - break; - } - - if(*inptr) - inptr++; - start = inptr; - } - - g_string_append(exec, start); - - argv[0] = "/bin/sh"; - argv[1] = "-c"; - argv[2] = exec->str; - argv[3] = NULL; - - g_spawn_sync(g_get_home_dir(), argv, NULL, 0, NULL, - NULL, NULL, NULL, &status, &error); - - if(error != NULL) - g_propagate_error(error_out, error); - - g_string_free(exec, TRUE); - - return status; -} -#endif - -/* PUBLIC METHODS */ - -IpodDevice * -ipod_device_new(const gchar *hal_volume_id) -{ - IpodDevice *device = g_object_new(TYPE_IPOD_DEVICE, - "hal-volume-id", hal_volume_id, NULL); - - if (device == NULL) { - /* This can happen if one forgot to call g_type_init before - * calling ipod_device_new - */ - return NULL; - } - - if(!device->priv->is_ipod) { - g_object_unref(device); - return NULL; - } - - return device; -} - -gboolean -ipod_device_rescan_disk(IpodDevice *device) -{ - g_return_val_if_fail(IS_IPOD_DEVICE(device), FALSE); - ipod_device_detect_volume_used(device); - return TRUE; -} - -guint -ipod_device_eject(IpodDevice *device, GError **error_out) -{ -#ifdef HAVE_LIBHAL - gint exit_status; - GError *error = NULL; - - g_return_val_if_fail(IS_IPOD_DEVICE(device), EJECT_ERROR); - g_return_val_if_fail(device->priv->is_ipod, EJECT_ERROR); - - if(ipod_device_has_open_fd(device)) - return EJECT_BUSY; - -#ifdef ASSUME_SUBMOUNT - sync(); - - exit_status = ipod_device_run_command(device, EJECT_COMMAND, &error); - if(error) { - g_propagate_error(error_out, error); - return EJECT_ERROR; - } - - return exit_status == 0 ? EJECT_OK : EJECT_ERROR; -#endif - - exit_status = ipod_device_run_command(device, UNMOUNT_COMMAND, &error); - - if(!error && exit_status == 0) { - exit_status = ipod_device_run_command(device, EJECT_COMMAND, &error); - if(error) { - g_propagate_error(error_out, error); - return EJECT_ERROR; - } - - return exit_status == 0 ? EJECT_OK : EJECT_ERROR; - } - - if(error) - g_propagate_error(error_out, error); - - return EJECT_ERROR; -} - -guint -ipod_device_reboot(IpodDevice *device, GError **error_out) -{ - gchar *sysinfo, *prefs, *backup_prefs, *devpath; - gboolean can_eject = TRUE; - - g_return_val_if_fail(IS_IPOD_DEVICE(device), EJECT_ERROR); - g_return_val_if_fail(device->priv->is_ipod, EJECT_ERROR); - - devpath = g_strdup_printf("%s/Device/", device->priv->control_path); - sysinfo = g_strdup_printf("%sSysInfo", devpath); - prefs = g_strdup_printf("%sPreferences", devpath); - backup_prefs = g_strdup_printf("%s/.Reboot_Preferences", - device->priv->control_path); - - if(g_file_test(sysinfo, G_FILE_TEST_EXISTS)) - can_eject = unlink(sysinfo) == 0; - - if(g_file_test(prefs, G_FILE_TEST_EXISTS) && can_eject) { - if(g_file_test(backup_prefs, G_FILE_TEST_EXISTS)) - unlink(backup_prefs); - - g_rename(prefs, backup_prefs); - unlink(prefs); - - can_eject = TRUE; - } - - if(can_eject) - can_eject = rmdir(devpath) == 0; - - g_free(devpath); - g_free(sysinfo); - g_free(prefs); - g_free(backup_prefs); - - if(can_eject) - return ipod_device_eject(device, error_out); - - g_propagate_error(error_out, g_error_new(g_quark_from_string("UNLINK"), - errno, "Could not remove file to initiate iPod reboot")); -#endif - return EJECT_ERROR; -} - -static GList * -_ipod_device_list_devices(gboolean create_device) -{ - LibHalContext *hal_context; - GList *finalDevices = NULL; - gchar **ipods, **volumes; - gint ipod_count, volume_count, i, j; - IpodDevice *ipod; - gboolean validIpod = FALSE; - - hal_context = ipod_device_hal_initialize(); - if(hal_context == NULL) - return NULL; - - ipods = libhal_manager_find_device_string_match(hal_context, - "info.product", "iPod", &ipod_count, NULL); - - for(i = 0; i < ipod_count; i++) { - volumes = libhal_manager_find_device_string_match(hal_context, - "info.parent", ipods[i], &volume_count, NULL); - - for(j = 0; j < volume_count; j++) { - if(!libhal_device_property_exists(hal_context, - volumes[j], "volume.is_mounted", NULL) - || !libhal_device_get_property_bool(hal_context, - volumes[j], "volume.is_mounted", NULL)) - continue; - - if(!create_device) { - finalDevices = g_list_append(finalDevices, - g_strdup(volumes[j])); - continue; - } - - if((ipod = ipod_device_new(volumes[j])) == NULL) - continue; - - g_object_get(ipod, "is-ipod", &validIpod, NULL); - if(validIpod) - finalDevices = g_list_append(finalDevices, ipod); - } - } - - libhal_ctx_shutdown(hal_context, NULL); - libhal_ctx_free(hal_context); - - return finalDevices; -} - -GList * -ipod_device_list_devices() -{ - return _ipod_device_list_devices(TRUE); -} - -GList * -ipod_device_list_device_udis() -{ - return _ipod_device_list_devices(FALSE); -} - -gboolean -ipod_device_save(IpodDevice *device, GError **error_out) -{ - FILE *fd; - gchar *path, *itunes_dir; - gchar bs = 0; - GError *error = NULL; - size_t res; - gint intres; - - g_return_val_if_fail(IS_IPOD_DEVICE(device), FALSE); - - itunes_dir = g_strdup_printf("%siTunes", device->priv->control_path); - path = g_strdup_printf("%s/DeviceInfo", itunes_dir); - - if(!g_file_test(itunes_dir, G_FILE_TEST_IS_DIR)) { - if(g_mkdir_with_parents(itunes_dir, 0744) != 0) { - if(error_out != NULL) { - error = g_error_new(g_quark_from_static_string("IPOD_DEVICE"), - ERROR_SAVE, "Could not create iTunes Directory: %s", - itunes_dir); - g_propagate_error(error_out, error); - } - - g_free(path); - g_free(itunes_dir); - - return FALSE; - } - } - - fd = fopen(path, "w+"); - if(fd == NULL) { - if(error_out != NULL) { - error = g_error_new(g_quark_from_static_string("IPOD_DEVICE"), - ERROR_SAVE, "Could not save DeviceInfo file: %s", path); - g_propagate_error(error_out, error); - } - - g_free(path); - g_free(itunes_dir); - - return FALSE; - } - - ipod_device_write_device_info_string(device->priv->device_name, fd); - - fseek(fd, 0x200, SEEK_SET); - ipod_device_write_device_info_string(device->priv->user_name, fd); - - intres = fseek(fd, 0x400, SEEK_SET); - ipod_device_write_device_info_string(device->priv->host_name, fd); - - intres = fseek(fd, 0X5FF, SEEK_SET); - /* FIXME: we do not check if the write was successful */ - res = fwrite(&bs, 1, 1, fd); - - fclose(fd); - - g_free(path); - g_free(itunes_dir); - - return TRUE; -} - -void -ipod_device_debug(IpodDevice *device) -{ - static const gchar *generation_names [] = { - "Unknown", - "First", - "Second", - "Third", - "Fourth" - }; - - gchar *device_path, *mount_point, *control_path, *hal_id; - gchar *model_number, *adv_capacity, *model_string; - guint model, generation; - gboolean is_new, can_write; - gchar *serial_number, *firmware_version; - guint64 volume_size, volume_used, volume_available; - gchar *volume_uuid, *volume_label; - gchar *device_name, *user_name, *host_name; - - g_return_if_fail(IS_IPOD_DEVICE(device)); - - g_object_get(device, - "device-path", &device_path, - "mount-point", &mount_point, - "control-path", &control_path, - "hal-volume-id", &hal_id, - "model-number", &model_number, - "device-model", &model, - "device-model-string", &model_string, - "device-generation", &generation, - "advertised-capacity", &adv_capacity, - "is-new", &is_new, - "can-write", &can_write, - "serial-number", &serial_number, - "firmware-version", &firmware_version, - "volume-size", &volume_size, - "volume-used", &volume_used, - "volume-available", &volume_available, - "volume_uuid", &volume_uuid, - "volume-label", &volume_label, - "device-name", &device_name, - "user-name", &user_name, - "host-name", &host_name, - NULL); - - g_printf("Path Info\n"); - g_printf(" Device Path: %s\n", device_path); - g_printf(" Mount Point: %s\n", mount_point); - g_printf(" Control Path: %s\n", control_path); - g_printf(" HAL ID: %s\n", hal_id); - - g_printf("Device Info\n"); - g_printf(" Model Number: %s\n", model_number); - g_printf(" Device Model: %s\n", model_string); - g_printf(" iPod Generation: %s\n", generation_names[generation]); - g_printf(" Adv. Capacity: %s\n", adv_capacity); - g_printf(" Is New: %s\n", is_new ? "YES" : "NO"); - g_printf(" Writeable: %s\n", can_write ? "YES" : "NO"); - g_printf(" Serial Number: %s\n", serial_number); - g_printf(" Firmware Version: %s\n", firmware_version); - g_printf("Volume Info\n"); - g_printf(" Volume Size: %lld\n", (long long int)volume_size); - g_printf(" Volume Used: %lld\n", (long long int)volume_used); - g_printf(" Available %lld\n", (long long int)volume_available); - g_printf(" UUID: %s\n", volume_uuid); - g_printf(" Label %s\n", volume_label); - g_printf("User-Provided Info\n"); - g_printf(" Device Name: %s\n", device_name); - g_printf(" User Name: %s\n", user_name); - g_printf(" Host Name: %s\n", host_name); - - g_printf("\n"); - fflush(stdout); -} diff --git a/src/ipod-device.h b/src/ipod-device.h deleted file mode 100644 index 416c13e..0000000 --- a/src/ipod-device.h +++ /dev/null @@ -1,196 +0,0 @@ -/* Time-stamp: <2005-10-10 01:23:28 jcs> -| -| Copyright (C) 2005 Jorg Schuler <jcsjcs at users sourceforge net> -| Part of the gtkpod project. -| -| URL: http://www.gtkpod.org/ -| URL: http://gtkpod.sourceforge.net/ -| -| -| The source is taken from libipoddevice, CVS version October 8 2005 -| (http://64.14.94.162/index.php/Libipoddevice). -| -| I decided not to make libgpod dependent on libipoddevice because -| the latter depends on libraries not widely available yet (libhal >= -| 0.5.2, glib >= 2.8). It is planned to replace these files with a -| libipoddevice dependence at some later time. -| -| The following changes were done: -| -| - libhal becomes optional (see #ifdef HAVE_LIBHAL sections) -| - publicly available functions were renamed from ipod_device_...() -| to itdb_device_...() -| -| Because of these changes only a limited amount of functionality is -| available if libhal is not present. In particular the following -| functions are non-functional: -| -| GList *ipod_device_list_devices(void); -| GList *ipod_device_list_device_udis(void); -| guint ipod_device_eject(IpodDevice *device, GError **error); -| guint ipod_device_reboot(IpodDevice *device, GError **error_out); -| -| Only the following properties are available: -| -| -| device-model -| device-model-string -| device-generation -| advertised-capacity -| is-new -| can-write -| serial-number -| firmware-version -| device-name -| user-name -| host-name -| -| -| $Id$ -*/ -/* ex: set ts=4: */ -/*************************************************************************** -* ipod-device.h -* Copyright (C) 2005 Novell -* Written by Aaron Bockover <aaron@aaronbock.net> -****************************************************************************/ - -/* - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2.1 of the GNU Lesser General Public - * License as published by the Free Software Foundation. - * - * 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 Lesser Public License for more details. - * - * You should have received a copy of the GNU Lesser 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 - */ - -#ifndef IPOD_DEVICE_H -#define IPOD_DEVICE_H - -#include <glib.h> -#include <glib-object.h> - -G_BEGIN_DECLS - -#define TYPE_IPOD_DEVICE (ipod_device_get_type ()) -#define IPOD_DEVICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_IPOD_DEVICE, IpodDevice)) -#define IPOD_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), TYPE_IPOD_DEVICE, IpodDeviceClass)) -#define IS_IPOD_DEVICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_IPOD_DEVICE)) -#define IS_IPOD_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TYPE_IPOD_DEVICE)) -#define IPOD_DEVICE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TYPE_IPOD_DEVICE, IpodDeviceClass)) - -typedef struct IpodDevicePrivate IpodDevicePrivate; - -typedef struct { - GObject parent; - IpodDevicePrivate *priv; -} IpodDevice; - -typedef struct { - GObjectClass parent_class; -} IpodDeviceClass; - -enum { - UNKNOWN_GENERATION, - FIRST_GENERATION, - SECOND_GENERATION, - THIRD_GENERATION, - FOURTH_GENERATION, - FIFTH_GENERATION -}; - -enum { - MODEL_TYPE_INVALID, - MODEL_TYPE_UNKNOWN, - MODEL_TYPE_COLOR, - MODEL_TYPE_COLOR_U2, - MODEL_TYPE_REGULAR, - MODEL_TYPE_REGULAR_U2, - MODEL_TYPE_MINI, - MODEL_TYPE_MINI_BLUE, - MODEL_TYPE_MINI_PINK, - MODEL_TYPE_MINI_GREEN, - MODEL_TYPE_MINI_GOLD, - MODEL_TYPE_SHUFFLE, - MODEL_TYPE_NANO_WHITE, - MODEL_TYPE_NANO_BLACK, - MODEL_TYPE_VIDEO_WHITE, - MODEL_TYPE_VIDEO_BLACK -}; - -enum { - EJECT_OK, - EJECT_ERROR, - EJECT_BUSY -}; - -enum { - PROP_IPOD_0, - PROP_HAL_VOLUME_ID, - PROP_HAL_CONTEXT, - PROP_MOUNT_POINT, - PROP_DEVICE_PATH, - PROP_CONTROL_PATH, - PROP_DEVICE_MODEL, - PROP_DEVICE_MODEL_STRING, - PROP_DEVICE_GENERATION, - PROP_ADVERTISED_CAPACITY, - PROP_DEVICE_NAME, - PROP_USER_NAME, - PROP_HOST_NAME, - PROP_VOLUME_SIZE, - PROP_VOLUME_AVAILABLE, - PROP_VOLUME_USED, - PROP_IS_IPOD, - PROP_IS_NEW, - PROP_SERIAL_NUMBER, - PROP_MODEL_NUMBER, - PROP_FIRMWARE_VERSION, - PROP_VOLUME_UUID, - PROP_VOLUME_LABEL, - PROP_CAN_WRITE, - PROP_ARTWORK_FORMAT -}; - -enum { - ERROR_SAVE -}; - -enum { - IPOD_COVER_SMALL, - IPOD_COVER_LARGE, - IPOD_PHOTO_SMALL, - IPOD_PHOTO_LARGE, - IPOD_PHOTO_FULL_SCREEN, - IPOD_PHOTO_TV_SCREEN -}; - - -typedef struct { - gint type; - gint16 width; - gint16 height; - gint16 correlation_id; -} IpodArtworkFormat; - - -GType itdb_device_get_type(void); -IpodDevice *itdb_device_new(const gchar *mount_point); -gboolean itdb_device_rescan_disk(IpodDevice *device); -guint itdb_device_eject(IpodDevice *device, GError **error); -guint itdb_device_reboot(IpodDevice *device, GError **error_out); -void itdb_device_debug(IpodDevice *device); -gboolean itdb_device_save(IpodDevice *device, GError **error); -GList *itdb_device_list_devices(void); -GList *itdb_device_list_device_udis(void); - -G_END_DECLS - -#endif /* IPOD_DEVICE_H */ @@ -1,4 +1,4 @@ -/* Time-stamp: <2006-03-13 23:01:23 jcs> +/* Time-stamp: <2006-03-16 23:50:32 jcs> | | Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net> | Part of the gtkpod project. @@ -40,8 +40,6 @@ # include <config.h> #endif -#include "ipod-device.h" - #include <sys/types.h> #include <time.h> #include <glib.h> @@ -56,6 +54,7 @@ G_BEGIN_DECLS typedef void (* ItdbUserDataDestroyFunc) (gpointer userdata); typedef gpointer (* ItdbUserDataDuplicateFunc) (gpointer userdata); +typedef struct _Itdb_Device Itdb_Device; typedef struct _Itdb_Artwork Itdb_Artwork; typedef struct _Itdb_Thumb Itdb_Thumb; typedef struct _SPLPref SPLPref; @@ -394,12 +393,8 @@ struct _Itdb_iTunesDB GList *tracks; GList *playlists; gchar *filename; /* filename of iTunesDB */ - gchar *mountpoint; /* mountpoint of iPod (if available) */ - IpodDevice *device; - gint musicdirs; /* number of /iPod_Control/Music/F.. dirs */ + Itdb_Device *device;/* iPod device info */ guint32 version; - gboolean reversed; /* this iTunesDB has to be written in reversed - endian order (e.g. mobile phone iTunesDBs) */ guint64 id; /* below is for use by application */ guint64 usertype; @@ -746,8 +741,22 @@ void itdb_filename_fs2ipod (gchar *filename); void itdb_filename_ipod2fs (gchar *ipod_file); gchar *itdb_filename_on_ipod (Itdb_Track *track); void itdb_set_mountpoint (Itdb_iTunesDB *itdb, const gchar *mp); +const gchar *itdb_get_mountpoint (Itdb_iTunesDB *itdb); gchar *itdb_get_control_dir (const gchar *mountpoint); gchar *itdb_get_itunes_dir (const gchar *mountpoint); +gchar *itdb_get_music_dir (const gchar *mountpoint); +gchar *itdb_get_artwork_dir (const gchar *mountpoint); +gchar *itdb_get_device_dir (const gchar *mountpoint); +gchar *itdb_get_itunesdb_path (const gchar *mountpoint); +gchar *itdb_get_artworkdb_path (const gchar *mountpoint); +gchar *itdb_get_path (const gchar *dir, const gchar *file); + +/* itdb_device functions */ +Itdb_Device *itdb_device_new (void); +void itdb_device_free (Itdb_Device *device); +void itdb_device_set_mountpoint (Itdb_Device *device, const gchar *mp); +gboolean itdb_device_read_sysinfo (Itdb_Device *device); +gchar *itdb_device_get_sysinfo (Itdb_Device *device, const gchar *field); /* track functions */ Itdb_Track *itdb_track_new (void); @@ -825,12 +834,12 @@ void itdb_artwork_remove_thumbnails (Itdb_Artwork *artwork); /* itdb_thumb_... */ /* the following funciton returns a pointer to a GdkPixbuf if gdk-pixbuf is installed -- a NULL pointer otherwise. */ -gpointer itdb_thumb_get_gdk_pixbuf (IpodDevice *device, +gpointer itdb_thumb_get_gdk_pixbuf (Itdb_Device *device, Itdb_Thumb *thumb); Itdb_Thumb *itdb_thumb_duplicate (Itdb_Thumb *thumb); void itdb_thumb_free (Itdb_Thumb *thumb); Itdb_Thumb *itdb_thumb_new (void); -gchar *itdb_thumb_get_filename (IpodDevice *device, Itdb_Thumb *thumb); +gchar *itdb_thumb_get_filename (Itdb_Device *device, Itdb_Thumb *thumb); /* time functions */ diff --git a/src/itdb_artwork.c b/src/itdb_artwork.c index 8142403..a233486 100644 --- a/src/itdb_artwork.c +++ b/src/itdb_artwork.c @@ -1,4 +1,4 @@ -/* Time-stamp: <2005-12-11 16:27:33 jcs> +/* Time-stamp: <2006-03-16 22:30:22 jcs> | | Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net> | Part of the gtkpod project. @@ -178,10 +178,9 @@ Itdb_Thumb *itdb_artwork_get_thumb_by_type (Itdb_Artwork *artwork, the original file. g_free() when not needed any more. */ -gchar *itdb_thumb_get_filename (IpodDevice *device, Itdb_Thumb *thumb) +gchar *itdb_thumb_get_filename (Itdb_Device *device, Itdb_Thumb *thumb) { - gchar *paths[] = {"iPod_Control", "Artwork", NULL, NULL}; - gchar *filename, *mountpoint; + gchar *artwork_dir, *filename=NULL; g_return_val_if_fail (device, NULL); g_return_val_if_fail (thumb, NULL); @@ -196,18 +195,18 @@ gchar *itdb_thumb_get_filename (IpodDevice *device, Itdb_Thumb *thumb) return NULL; } - g_object_get (G_OBJECT (device), - "mount-point", &mountpoint, - NULL); - - if (!mountpoint) + if (!device->mountpoint) { g_print (_("Mountpoint not set.\n")); return NULL; } - paths[2] = thumb->filename+1; - filename = itdb_resolve_path (mountpoint, (const char **)paths); + artwork_dir = itdb_get_artwork_dir (device->mountpoint); + if (artwork_dir) + { + filename = itdb_get_path (artwork_dir, thumb->filename+1); + g_free (artwork_dir); + } return filename; } @@ -245,7 +244,7 @@ unpack_RGB_565 (guint16 *pixels, guint bytes_len) static guchar * -get_pixel_data (IpodDevice *device, Itdb_Thumb *thumb) +get_pixel_data (Itdb_Device *device, Itdb_Thumb *thumb) { gchar *filename = NULL; guchar *result = NULL; @@ -305,7 +304,7 @@ get_pixel_data (IpodDevice *device, Itdb_Thumb *thumb) } static guchar * -itdb_thumb_get_rgb_data (IpodDevice *device, Itdb_Thumb *thumb) +itdb_thumb_get_rgb_data (Itdb_Device *device, Itdb_Thumb *thumb) { void *pixels565; guchar *pixels; @@ -340,12 +339,12 @@ itdb_thumb_get_rgb_data (IpodDevice *device, Itdb_Thumb *thumb) The returned GdkPixbuf must be freed with gdk_pixbuf_unref() after use. */ gpointer -itdb_thumb_get_gdk_pixbuf (IpodDevice *device, Itdb_Thumb *thumb) +itdb_thumb_get_gdk_pixbuf (Itdb_Device *device, Itdb_Thumb *thumb) { #if HAVE_GDKPIXBUF GdkPixbuf *pixbuf=NULL; guchar *pixels; - const IpodArtworkFormat *img_info=NULL; + const Itdb_ArtworkFormat *img_info=NULL; g_return_val_if_fail (thumb, NULL); @@ -358,7 +357,7 @@ itdb_thumb_get_gdk_pixbuf (IpodDevice *device, Itdb_Thumb *thumb) */ if (device != NULL) { - img_info = ipod_get_artwork_info_from_type (device, thumb->type); + img_info = itdb_get_artwork_info_from_type (device, thumb->type); } if (thumb->size == 0) diff --git a/src/itdb_device.c b/src/itdb_device.c new file mode 100644 index 0000000..c0fe191 --- /dev/null +++ b/src/itdb_device.c @@ -0,0 +1,431 @@ +/* Time-stamp: <2006-03-17 00:02:22 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/ +| +| Part of this code is based on ipod-device.c from the libipoddevice +| project (http://64.14.94.162/index.php/Libipoddevice). +| +| The code contained in this file is free software; you can redistribute +| it and/or modify it under the terms of the GNU Lesser General Public +| License as published by the Free Software Foundation; either version +| 2.1 of the License, or (at your option) any later version. +| +| This file is distributed in the hope that it will be useful, +| but WITHOUT ANY WARRANTY; without even the implied warranty of +| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +| Lesser General Public License for more details. +| +| You should have received a copy of the GNU Lesser General Public +| License along with this code; 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$ +*/ + +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include "itdb_device.h" + +#define GB 1024 + +static const Itdb_IpodModel ipod_model_table [] = { + /* Handle idiots who hose their iPod file system, or + lucky people with iPods we don't yet know about*/ + {"Invalid", 0, MODEL_TYPE_INVALID, UNKNOWN_GENERATION}, + {"Unknown", 0, MODEL_TYPE_UNKNOWN, UNKNOWN_GENERATION}, + + /* First Generation */ + {"8513", 5 * GB, MODEL_TYPE_REGULAR, FIRST_GENERATION}, + {"8541", 5 * GB, MODEL_TYPE_REGULAR, FIRST_GENERATION}, + {"8697", 5 * GB, MODEL_TYPE_REGULAR, FIRST_GENERATION}, + {"8709", 10 * GB, MODEL_TYPE_REGULAR, FIRST_GENERATION}, + + /* Second Generation */ + {"8737", 10 * GB, MODEL_TYPE_REGULAR, SECOND_GENERATION}, + {"8740", 10 * GB, MODEL_TYPE_REGULAR, SECOND_GENERATION}, + {"8738", 20 * GB, MODEL_TYPE_REGULAR, SECOND_GENERATION}, + {"8741", 20 * GB, MODEL_TYPE_REGULAR, SECOND_GENERATION}, + + /* Third Generation */ + {"8976", 10 * GB, MODEL_TYPE_REGULAR, THIRD_GENERATION}, + {"8946", 15 * GB, MODEL_TYPE_REGULAR, THIRD_GENERATION}, + {"9460", 15 * GB, MODEL_TYPE_REGULAR, THIRD_GENERATION}, + {"9244", 20 * GB, MODEL_TYPE_REGULAR, THIRD_GENERATION}, + {"8948", 30 * GB, MODEL_TYPE_REGULAR, THIRD_GENERATION}, + {"9245", 40 * GB, MODEL_TYPE_REGULAR, THIRD_GENERATION}, + + + /* Fourth Generation */ + {"9282", 20 * GB, MODEL_TYPE_REGULAR, FOURTH_GENERATION}, + {"9787", 25 * GB, MODEL_TYPE_REGULAR_U2, FOURTH_GENERATION}, + {"9268", 40 * GB, MODEL_TYPE_REGULAR, FOURTH_GENERATION}, + {"A079", 20 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION}, + {"A127", 20 * GB, MODEL_TYPE_COLOR_U2, FOURTH_GENERATION}, + {"9830", 60 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION}, + + /* First Generation Mini */ + {"9160", 4 * GB, MODEL_TYPE_MINI, FIRST_GENERATION}, + {"9436", 4 * GB, MODEL_TYPE_MINI_BLUE, FIRST_GENERATION}, + {"9435", 4 * GB, MODEL_TYPE_MINI_PINK, FIRST_GENERATION}, + {"9434", 4 * GB, MODEL_TYPE_MINI_GREEN, FIRST_GENERATION}, + {"9437", 4 * GB, MODEL_TYPE_MINI_GOLD, FIRST_GENERATION}, + + /* Second Generation Mini */ + {"9800", 4 * GB, MODEL_TYPE_MINI, SECOND_GENERATION}, + {"9802", 4 * GB, MODEL_TYPE_MINI_BLUE, SECOND_GENERATION}, + {"9804", 4 * GB, MODEL_TYPE_MINI_PINK, SECOND_GENERATION}, + {"9806", 4 * GB, MODEL_TYPE_MINI_GREEN, SECOND_GENERATION}, + {"9801", 6 * GB, MODEL_TYPE_MINI, SECOND_GENERATION}, + {"9803", 6 * GB, MODEL_TYPE_MINI_BLUE, SECOND_GENERATION}, + {"9805", 6 * GB, MODEL_TYPE_MINI_PINK, SECOND_GENERATION}, + {"9807", 6 * GB, MODEL_TYPE_MINI_GREEN, SECOND_GENERATION}, + + /* Photo / Fourth Generation */ + {"9829", 30 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION}, + {"9585", 40 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION}, + {"9586", 60 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION}, + {"9830", 60 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION}, + + /* Shuffle / Fourth Generation */ + {"9724", GB / 2, MODEL_TYPE_SHUFFLE, FOURTH_GENERATION}, + {"9725", GB, MODEL_TYPE_SHUFFLE, FOURTH_GENERATION}, + + /* Nano / Fifth Generation */ + {"A350", GB * 1, MODEL_TYPE_NANO_WHITE, FIFTH_GENERATION}, + {"A352", GB * 1, MODEL_TYPE_NANO_BLACK, FIFTH_GENERATION}, + {"A004", GB * 2, MODEL_TYPE_NANO_WHITE, FIFTH_GENERATION}, + {"A099", GB * 2, MODEL_TYPE_NANO_BLACK, FIFTH_GENERATION}, + {"A005", GB * 4, MODEL_TYPE_NANO_WHITE, FIFTH_GENERATION}, + {"A107", GB * 4, MODEL_TYPE_NANO_BLACK, FIFTH_GENERATION}, + + /* Video / Fifth Generation */ + {"A002", GB * 30, MODEL_TYPE_VIDEO_WHITE, FIFTH_GENERATION}, + {"A146", GB * 30, MODEL_TYPE_VIDEO_BLACK, FIFTH_GENERATION}, + {"A003", GB * 60, MODEL_TYPE_VIDEO_WHITE, FIFTH_GENERATION}, + {"A147", GB * 60, MODEL_TYPE_VIDEO_BLACK, FIFTH_GENERATION}, + + /* HP iPods, need contributions for this table */ + {"E436", 40 * GB, MODEL_TYPE_REGULAR, FOURTH_GENERATION}, + {"S492", 30 * GB, MODEL_TYPE_COLOR, FOURTH_GENERATION}, + + {NULL, 0, 0, 0} +}; + +#if 0 +static const gchar *ipod_model_name_table [] = { + "Invalid", + "Unknown", + "Color", + "Color U2", + "Grayscale", + "Grayscale U2", + "Mini (Silver)", + "Mini (Blue)", + "Mini (Pink)", + "Mini (Green)", + "Mini (Gold)", + "Shuffle", + "Nano (White)", + "Nano (Black)", + "Video (White)", + "Video (Black)", + NULL +}; +#endif + +static const Itdb_ArtworkFormat ipod_color_artwork_info[] = { + {IPOD_COVER_SMALL, 56, 56, 1017}, + {IPOD_COVER_LARGE, 140, 140, 1016}, + {IPOD_PHOTO_SMALL, 42, 30, 1009}, + {IPOD_PHOTO_LARGE, 130, 88, 1015}, + {IPOD_PHOTO_FULL_SCREEN, 220, 176, 1013}, + {IPOD_PHOTO_TV_SCREEN, 720, 480, 1019}, + {-1, -1, -1, -1} +}; + +static const Itdb_ArtworkFormat ipod_nano_artwork_info[] = { + {IPOD_COVER_SMALL, 42, 42, 1031}, + {IPOD_COVER_LARGE, 100, 100, 1027}, + {IPOD_PHOTO_LARGE, 42, 37, 1032}, + {IPOD_PHOTO_FULL_SCREEN, 176, 132, 1023}, + {-1, -1, -1, -1} +}; + +static const Itdb_ArtworkFormat ipod_video_artwork_info[] = { + {IPOD_COVER_SMALL, 100, 100, 1028}, + {IPOD_COVER_LARGE, 200, 200, 1029}, + {IPOD_PHOTO_SMALL, 50, 41, 1036}, + {IPOD_PHOTO_LARGE, 130, 88, 1015}, + {IPOD_PHOTO_FULL_SCREEN, 320, 240, 1024}, + {IPOD_PHOTO_TV_SCREEN, 720, 480, 1019}, + {-1, -1, -1, -1} +}; + +/* This will be indexed using a value from the MODEL_TYPE enum */ +static const Itdb_ArtworkFormat *ipod_artwork_info_table[] = { + NULL, /* Invalid */ + NULL, /* Unknown */ + ipod_color_artwork_info, /* Color */ + ipod_color_artwork_info, /* Color U2 */ + NULL, /* Grayscale */ + NULL, /* Grayscale U2 */ + NULL, /* Mini (Silver) */ + NULL, /* Mini (Blue) */ + NULL, /* Mini (Pink) */ + NULL, /* Mini (Green) */ + NULL, /* Mini (Gold) */ + NULL, /* Shuffle */ + ipod_nano_artwork_info, /* Nano (White) */ + ipod_nano_artwork_info, /* Nano (Black) */ + ipod_video_artwork_info, /* Video (White) */ + ipod_video_artwork_info /* Video (Black) */ +}; + + +/* Reset or create the SysInfo hash table */ +static void itdb_device_reset_sysinfo (Itdb_Device *device) +{ + if (device->sysinfo) + g_hash_table_destroy (device->sysinfo); + device->sysinfo = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, g_free); +} + + +/* Create new Itdb_Device structure */ +Itdb_Device *itdb_device_new () +{ + Itdb_Device *dev; + + dev = g_new0 (Itdb_Device, 1); + itdb_device_reset_sysinfo (dev); + return dev; +} + +/* Free memory used by @device */ +void itdb_device_free (Itdb_Device *device) +{ + if (device) + { + g_free (device->mountpoint); + if (device->sysinfo) + g_hash_table_destroy (device->sysinfo); + g_free (device); + } +} + + +/* Set mountpoint and read SysInfo file */ +void itdb_device_set_mountpoint (Itdb_Device *device, const gchar *mp) +{ + g_return_if_fail (device); + + g_free (device->mountpoint); + device->mountpoint = g_strdup (mp); + if (mp) + itdb_device_read_sysinfo (device); +} + + +/* Read SysInfo file and store information in device->sysinfo for + * later use. + * + * Return value: TRUE if file could be read, FALSE otherwise */ +gboolean itdb_device_read_sysinfo (Itdb_Device *device) +{ + const gchar *p_sysinfo[] = {"SysInfo", NULL}; + gchar *dev_path, *sysinfo_path; + FILE *fd; + gboolean result = FALSE; + gchar buf[1024]; + + g_return_val_if_fail (device, FALSE); + g_return_val_if_fail (device->mountpoint, FALSE); + + itdb_device_reset_sysinfo (device); + + g_return_val_if_fail (device->sysinfo, FALSE); + + dev_path = itdb_get_device_dir (device->mountpoint); + + if (!dev_path) return FALSE; + + sysinfo_path = itdb_resolve_path (dev_path, p_sysinfo); + + if (sysinfo_path) + { + fd = fopen (sysinfo_path, "r"); + if (fd) + { + result = TRUE; + while(fgets(buf, sizeof(buf), fd)) + { + gchar *ptr; + gint len = strlen (buf); + /* suppress newline at end of line */ + if ((len>0) && (buf[len-1]==0x0a)) + { + buf[len-1] = 0; + --len; + } + ptr = strchr (buf, ':'); + if (ptr && (ptr!=buf)) + { + gchar *key, *value; + *ptr = 0; + ++ptr; + key = g_strdup (buf); + g_strstrip (ptr); + value = g_strdup (ptr); + g_hash_table_insert (device->sysinfo, key, value); + } + } + fclose (fd); + } + g_free (sysinfo_path); + } + g_free (dev_path); + return result; +} + + +/* Retrieve specified field from the SysInfo file. + * + * Return value: g_free() after use + */ +gchar *itdb_device_get_sysinfo (Itdb_Device *device, const gchar *field) +{ + g_return_val_if_fail (device, NULL); + g_return_val_if_fail (device->sysinfo, NULL); + g_return_val_if_fail (field, NULL); + + return g_strdup (g_hash_table_lookup (device->sysinfo, field)); +} + + +/* Return Itdb_IpodModel entry for this iPod */ +G_GNUC_INTERNAL const Itdb_IpodModel * +itdb_device_get_ipod_model (Itdb_Device *device) +{ + gint i; + gchar *model_num, *p; + + model_num = itdb_device_get_sysinfo (device, "ModelNumStr"); + + if (!model_num) + return &ipod_model_table[0]; + + p = model_num; + + if(isalpha(model_num[0])) + p++; + + for(i=2; ipod_model_table[i].model_number != NULL; i++) + { + if(g_strncasecmp(p, ipod_model_table[i].model_number, 4) == 0) + { + g_free(model_num); + return &ipod_model_table[i]; + } + } + g_free(model_num); + return &ipod_model_table[1]; +} + + +/* Return supported artwork formats supported by this iPod */ +G_GNUC_INTERNAL const Itdb_ArtworkFormat * +itdb_device_get_artwork_formats (Itdb_Device *device) +{ + const Itdb_IpodModel *model; + + g_return_val_if_fail (device, NULL); + + model = itdb_device_get_ipod_model (device); + + g_return_val_if_fail (model, NULL); + + return ipod_artwork_info_table[model->model_type]; +} + + +/* Determine the number of F.. directories in iPod_Control/Music. + + If device->musicdirs is already set, simply return the previously + determined number. Otherwise count the directories first and set + itdb->musicdirs. */ +G_GNUC_INTERNAL gint +itdb_device_musicdirs_number (Itdb_Device *device) +{ + gchar *dir_filename = NULL; + gint dir_num; + + g_return_val_if_fail (device, 0); + + if (device->musicdirs <= 0) + { + gchar *music_dir = itdb_get_music_dir (device->mountpoint); + if (!music_dir) return 0; + /* count number of dirs */ + for (dir_num=0; ;++dir_num) + { + gchar dir_num_str[5]; + + g_snprintf (dir_num_str, 5, "F%02d", dir_num); + + dir_filename = itdb_get_path (music_dir, dir_num_str); + + if (!dir_filename) break; + g_free (dir_filename); + } + device->musicdirs = dir_num; + g_free (music_dir); + } + return device->musicdirs; +} + + +/* Attempt to guess the endianess used by this iPod. + * + * It will overwrite the previous setting. + * + */ + +G_GNUC_INTERNAL void +itdb_device_autodetect_endianess (Itdb_Device *device) +{ + g_return_if_fail (device); + + /* endianess_set will be set to FALSE. This field is only set to + TRUE when importing an iTunesDB. */ + device->endianess_set = FALSE; + /* default: non-reversed */ + device->endianess_reversed = FALSE; + + if (device->mountpoint) + { + gchar *control_dir = itdb_get_control_dir (device->mountpoint); + + if (control_dir) + { + gchar *cd_l = g_ascii_strdown (control_dir, -1); + if (strstr (cd_l, "itunes/itunes_control") == + (cd_l + strlen (cd_l) - strlen ("itunes/itunes_control"))) + { + device->endianess_reversed = TRUE; + } + g_free (cd_l); + g_free (control_dir); + } + } +} diff --git a/src/itdb_device.h b/src/itdb_device.h new file mode 100644 index 0000000..5755d3c --- /dev/null +++ b/src/itdb_device.h @@ -0,0 +1,126 @@ +/* Time-stamp: <2006-03-16 23:02:20 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/ +| +| Most of the code in this file has been ported from the perl +| script "mktunes.pl" (part of the gnupod-tools collection) written +| by Adrian Ulrich <pab at blinkenlights.ch>. +| +| gnupod-tools: http://www.blinkenlights.ch/cgi-bin/fm.pl?get=ipod +| +| The code contained in this file is free software; you can redistribute +| it and/or modify it under the terms of the GNU Lesser General Public +| License as published by the Free Software Foundation; either version +| 2.1 of the License, or (at your option) any later version. +| +| This file is distributed in the hope that it will be useful, +| but WITHOUT ANY WARRANTY; without even the implied warranty of +| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +| Lesser General Public License for more details. +| +| You should have received a copy of the GNU Lesser General Public +| License along with this code; 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$ +*/ + +#ifndef __ITDB_DEVICE_H__ +#define __ITDB_DEVICE_H__ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "itdb.h" + +#include <glib.h> + +G_BEGIN_DECLS + +typedef struct _Itdb_IpodModel Itdb_IpodModel; +typedef struct _Itdb_ArtworkFormat Itdb_ArtworkFormat; + +struct _Itdb_Device +{ + gchar *mountpoint; /* mountpoint of the iPod */ + gint musicdirs; /* number of /iPod_Control/Music/F.. dirs */ + gboolean endianess_set; /* the endianess_reversed flag has been + detected or set */ + gboolean endianess_reversed; /* this iTunesDB has to be written in + reversed endian order (e.g. mobile phone + iTunesDBs) */ + GHashTable *sysinfo; /* hash with value/key pairs of all entries + in Device/SysInfo */ +}; + +struct _Itdb_ArtworkFormat +{ + gint type; + gint16 width; + gint16 height; + gint16 correlation_id; +}; + +struct _Itdb_IpodModel { + const gchar *model_number; + const guint64 capacity; + guint model_type; + guint generation; +}; + +typedef enum { + UNKNOWN_GENERATION, + FIRST_GENERATION, + SECOND_GENERATION, + THIRD_GENERATION, + FOURTH_GENERATION, + FIFTH_GENERATION +} Itdb_Generation; + +typedef enum { + MODEL_TYPE_INVALID, + MODEL_TYPE_UNKNOWN, + MODEL_TYPE_COLOR, + MODEL_TYPE_COLOR_U2, + MODEL_TYPE_REGULAR, + MODEL_TYPE_REGULAR_U2, + MODEL_TYPE_MINI, + MODEL_TYPE_MINI_BLUE, + MODEL_TYPE_MINI_PINK, + MODEL_TYPE_MINI_GREEN, + MODEL_TYPE_MINI_GOLD, + MODEL_TYPE_SHUFFLE, + MODEL_TYPE_NANO_WHITE, + MODEL_TYPE_NANO_BLACK, + MODEL_TYPE_VIDEO_WHITE, + MODEL_TYPE_VIDEO_BLACK +} Itdb_ModelType; + + +enum { + IPOD_COVER_SMALL, + IPOD_COVER_LARGE, + IPOD_PHOTO_SMALL, + IPOD_PHOTO_LARGE, + IPOD_PHOTO_FULL_SCREEN, + IPOD_PHOTO_TV_SCREEN +}; + +G_GNUC_INTERNAL const Itdb_ArtworkFormat *itdb_device_get_artwork_formats (Itdb_Device *device); +G_GNUC_INTERNAL const Itdb_IpodModel *itdb_device_get_ipod_model (Itdb_Device *device); +G_GNUC_INTERNAL gint itdb_device_musicdirs_number (Itdb_Device *device); +G_GNUC_INTERNAL void itdb_device_autodetect_endianess (Itdb_Device *device); + + +G_END_DECLS + +#endif diff --git a/src/itdb_itunesdb.c b/src/itdb_itunesdb.c index 2d91de3..7577da8 100644 --- a/src/itdb_itunesdb.c +++ b/src/itdb_itunesdb.c @@ -1,4 +1,4 @@ -/* Time-stamp: <2006-03-14 01:25:03 jcs> +/* Time-stamp: <2006-03-17 00:02:22 jcs> | | Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net> | Part of the gtkpod project. @@ -120,8 +120,10 @@ #include <errno.h> #include <stdio.h> #include "itdb_private.h" +#include "itdb_device.h" #include "db-artwork-parser.h" #include <glib/gi18n-lib.h> +#include <glib-object.h> #define ITUNESDB_DEBUG 0 #define ITUNESDB_MHIT_DEBUG 0 @@ -1054,10 +1056,7 @@ void itdb_free (Itdb_iTunesDB *itdb) (GFunc)(itdb_track_free), NULL); g_list_free (itdb->tracks); g_free (itdb->filename); - g_free (itdb->mountpoint); - if (itdb->device != NULL) { - g_object_unref (G_OBJECT (itdb->device)); - } + itdb_device_free (itdb->device); if (itdb->userdata && itdb->userdata_destroy) (*itdb->userdata_destroy) (itdb->userdata); g_free (itdb); @@ -1117,6 +1116,7 @@ Itdb_iTunesDB *itdb_new (void) g_once (&g_type_init_once, (GThreadFunc)g_type_init, NULL); itdb = g_new0 (Itdb_iTunesDB, 1); + itdb->device = itdb_device_new (); itdb->version = 0x09; itdb->id = ((guint64)g_random_int () << 32) | ((guint64)g_random_int ()); @@ -2526,7 +2526,8 @@ static gboolean parse_fimp (FImport *fimp) } /* copy the 'reversed endian flag' */ - fimp->itdb->reversed = cts->reversed; + fimp->itdb->device->endianess_set = TRUE; + fimp->itdb->device->endianess_reversed = cts->reversed; parse_tracks (fimp, mhsd_1); if (fimp->error) return FALSE; @@ -2569,6 +2570,24 @@ static void error_no_itunes_dir (const gchar *mp, GError **error) } /* Set @error with standard error message */ +static void error_no_music_dir (const gchar *mp, GError **error) +{ + gchar *str; + + g_return_if_fail (mp); + g_return_if_fail (error); + + str = g_build_filename (mp, "iPod_Control", "Music", NULL); + g_set_error (error, + ITDB_FILE_ERROR, + ITDB_FILE_ERROR_NOTFOUND, + _("Music directory not found: '%s' (or similar)."), + str); + g_free (str); +} + +#if 0 +/* Set @error with standard error message */ static void error_no_control_dir (const gchar *mp, GError **error) { gchar *str; @@ -2584,7 +2603,7 @@ static void error_no_control_dir (const gchar *mp, GError **error) str); g_free (str); } - +#endif /* Parse the Itdb_iTunesDB. Returns a pointer to the Itdb_iTunesDB struct holding the tracks and the @@ -4079,6 +4098,7 @@ gboolean itdb_write_file (Itdb_iTunesDB *itdb, const gchar *filename, gboolean result = TRUE;; g_return_val_if_fail (itdb, FALSE); + g_return_val_if_fail (itdb->device, FALSE); g_return_val_if_fail (filename || itdb->filename, FALSE); if (!filename) filename = itdb->filename; @@ -4097,8 +4117,10 @@ gboolean itdb_write_file (Itdb_iTunesDB *itdb, const gchar *filename, fexp->wcontents = wcontents_new (filename); cts = fexp->wcontents; - /* copy endianess flag */ - cts->reversed = itdb->reversed; + /* set endianess flag */ + if (!itdb->device->endianess_set) + itdb_device_autodetect_endianess (itdb->device); + cts->reversed = itdb->device->endianess_reversed; reassign_ids (fexp); @@ -4158,7 +4180,7 @@ gboolean itdb_write (Itdb_iTunesDB *itdb, GError **error) gboolean result = FALSE; g_return_val_if_fail (itdb, FALSE); - g_return_val_if_fail (itdb->mountpoint, FALSE); + g_return_val_if_fail (itdb_get_mountpoint (itdb), FALSE); /* First, let's try to write the .ithmb files containing the artwork data * since this operation modifies the 'artwork_count' and 'artwork_size' @@ -4168,11 +4190,11 @@ gboolean itdb_write (Itdb_iTunesDB *itdb, GError **error) */ - itunes_path = itdb_get_itunes_dir (itdb->mountpoint); + itunes_path = itdb_get_itunes_dir (itdb_get_mountpoint (itdb)); if(!itunes_path) { - error_no_itunes_dir (itdb->mountpoint, error); + error_no_itunes_dir (itdb_get_mountpoint (itdb), error); return FALSE; } @@ -4184,7 +4206,7 @@ gboolean itdb_write (Itdb_iTunesDB *itdb, GError **error) g_free (itunes_path); if (result == TRUE) - result = itdb_rename_files (itdb->mountpoint, error); + result = itdb_rename_files (itdb_get_mountpoint (itdb), error); /* make sure all buffers are flushed as some people tend to disconnect as soon as gtkpod returns */ @@ -4317,22 +4339,21 @@ All integers in the iTunesSD file are in BIG endian form... gboolean itdb_shuffle_write (Itdb_iTunesDB *itdb, GError **error) { gchar *itunes_filename, *itunes_path; - const gchar *db[] = {"iPod_Control","iTunes",NULL}; gboolean result = FALSE; g_return_val_if_fail (itdb, FALSE); - g_return_val_if_fail (itdb->mountpoint, FALSE); + g_return_val_if_fail (itdb_get_mountpoint (itdb), FALSE); - itunes_path = itdb_resolve_path (itdb->mountpoint, db); + itunes_path = itdb_get_itunes_dir (itdb_get_mountpoint (itdb)); if(!itunes_path) { - gchar *str = g_build_filename (itdb->mountpoint, - db[0], db[1], db[2], NULL); + gchar *str = g_build_filename (itdb_get_mountpoint (itdb), + "iPod_Control", "iTunes", NULL); g_set_error (error, ITDB_FILE_ERROR, ITDB_FILE_ERROR_NOTFOUND, - _("Path not found: '%s'."), + _("Path not found: '%s' (or similar)."), str); g_free (str); return FALSE; @@ -4346,7 +4367,7 @@ gboolean itdb_shuffle_write (Itdb_iTunesDB *itdb, GError **error) g_free(itunes_path); if (result == TRUE) - result = itdb_rename_files (itdb->mountpoint, error); + result = itdb_rename_files (itdb_get_mountpoint (itdb), error); /* make sure all buffers are flushed as some people tend to disconnect as soon as gtkpod returns */ @@ -4612,17 +4633,18 @@ void itdb_filename_ipod2fs (gchar *ipod_file) void itdb_set_mountpoint (Itdb_iTunesDB *itdb, const gchar *mp) { g_return_if_fail (itdb); + g_return_if_fail (itdb->device); - g_free (itdb->mountpoint); - itdb->mountpoint = g_strdup (mp); - if (itdb->device) - { - g_object_unref (G_OBJECT (itdb->device)); - itdb->device = NULL; - } - if (mp) - itdb->device = itdb_device_new (mp); - itdb->musicdirs = 0; + itdb_device_set_mountpoint (itdb->device, mp); + itdb->device->musicdirs = 0; +} + +/* Retrieve a reference to the mountpoint */ +const gchar *itdb_get_mountpoint (Itdb_iTunesDB *itdb) +{ + g_return_val_if_fail (itdb, NULL); + g_return_val_if_fail (itdb->device, NULL); + return itdb->device->mountpoint; } @@ -4633,41 +4655,14 @@ void itdb_set_mountpoint (Itdb_iTunesDB *itdb, const gchar *mp) itdb->musicdirs. */ gint itdb_musicdirs_number (Itdb_iTunesDB *itdb) { - gchar *dest_components[] = {"Music", NULL, NULL}; - gchar *dir_filename = NULL; - gint dir_num; - g_return_val_if_fail (itdb, 0); - g_return_val_if_fail (itdb->mountpoint, 0); + g_return_val_if_fail (itdb->device, 0); - if (itdb->musicdirs <= 0) - { - gchar *control_dir = itdb_get_control_dir (itdb->mountpoint); - if (!control_dir) return 0; - /* count number of dirs */ - for (dir_num=0; ;++dir_num) - { - gchar dir_num_str[5]; - - g_snprintf (dir_num_str, 5, "F%02d", dir_num); - dest_components[1] = dir_num_str; - - dir_filename = - itdb_resolve_path (control_dir, - (const gchar **)dest_components); - - if (!dir_filename) break; - g_free (dir_filename); - } - itdb->musicdirs = dir_num; - g_free (control_dir); - } - return itdb->musicdirs; + return itdb_device_musicdirs_number (itdb->device); } - /* Copy one track to the iPod. The PC filename is @filename and is taken literally. @@ -4699,12 +4694,12 @@ gboolean itdb_cp_track_to_ipod (Itdb_Track *track, g_return_val_if_fail (track, FALSE); g_return_val_if_fail (track->itdb, FALSE); - g_return_val_if_fail (track->itdb->mountpoint, FALSE); + g_return_val_if_fail (itdb_get_mountpoint (track->itdb), FALSE); g_return_val_if_fail (filename, FALSE); if(track->transferred) return TRUE; /* nothing to do */ - mountpoint = track->itdb->mountpoint; + mountpoint = itdb_get_mountpoint (track->itdb); itdb = track->itdb; /* If track->ipod_path exists, we use that one instead. */ @@ -4712,55 +4707,57 @@ gboolean itdb_cp_track_to_ipod (Itdb_Track *track, if (!ipod_fullfile) { - gchar *dest_components[] = {"Music", NULL, NULL, NULL}; - gchar *parent_dir_filename, *control_dir; + gchar *dest_components[] = {NULL, NULL, NULL}; + gchar *parent_dir_filename, *music_dir; gchar *original_suffix; gchar dir_num_str[5]; gint32 oops = 0; gint32 rand = g_random_int_range (0, 899999); /* 0 to 900000 */ - control_dir = itdb_get_control_dir (mountpoint); - if (!control_dir) + music_dir = itdb_get_music_dir (mountpoint); + if (!music_dir) { - error_no_control_dir (mountpoint, error); + error_no_music_dir (mountpoint, error); return FALSE; } if (itdb_musicdirs_number (itdb) <= 0) { - gchar *str = g_build_filename (control_dir, "Music", NULL); - g_set_error (error, ITDB_FILE_ERROR, ITDB_FILE_ERROR_NOTFOUND, - _("No 'F..' directories found in '%s' (or similar)."), - str); - g_free (str); - g_free (control_dir); + _("No 'F..' directories found in '%s'."), + music_dir); + g_free (music_dir); return FALSE; } - if (dir_num == -1) dir_num = g_random_int_range (0, itdb->musicdirs); - else dir_num = (dir_num + 1) % itdb_musicdirs_number (itdb); + if (dir_num == -1) + { + dir_num = g_random_int_range (0, itdb_musicdirs_number (itdb)); + } + else + { + dir_num = (dir_num + 1) % itdb_musicdirs_number (itdb); + } g_snprintf (dir_num_str, 5, "F%02d", dir_num); - dest_components[1] = dir_num_str; + dest_components[0] = dir_num_str; parent_dir_filename = - itdb_resolve_path (control_dir, (const gchar **)dest_components); + itdb_resolve_path (music_dir, (const gchar **)dest_components); if(parent_dir_filename == NULL) { /* Can't find the F%02d directory */ - gchar *str = g_build_filename (control_dir, - dest_components[0], - dest_components[1], NULL); + gchar *str = g_build_filename (music_dir, + dest_components[0], NULL); g_set_error (error, ITDB_FILE_ERROR, ITDB_FILE_ERROR_NOTFOUND, _("Path not found: '%s'."), str); g_free (str); - g_free (control_dir); + g_free (music_dir); return FALSE; } @@ -4773,12 +4770,12 @@ gboolean itdb_cp_track_to_ipod (Itdb_Track *track, do { /* we need to loop until we find an unused filename */ - dest_components[2] = + dest_components[1] = g_strdup_printf("gtkpod%06d%s", rand + oops, original_suffix); ipod_fullfile = itdb_resolve_path ( parent_dir_filename, - (const gchar **)&dest_components[2]); + (const gchar **)&dest_components[1]); if(ipod_fullfile) { /* already exists -- try next */ g_free(ipod_fullfile); @@ -4787,13 +4784,13 @@ gboolean itdb_cp_track_to_ipod (Itdb_Track *track, else { /* found unused file -- build filename */ ipod_fullfile = g_build_filename (parent_dir_filename, - dest_components[2], NULL); + dest_components[1], NULL); } - g_free (dest_components[2]); + g_free (dest_components[1]); ++oops; } while (!ipod_fullfile); g_free(parent_dir_filename); - g_free (control_dir); + g_free (music_dir); } /* now extract filepath for track->ipod_path from ipod_fullfile */ /* ipod_path must begin with a '/' */ @@ -4850,9 +4847,9 @@ gchar *itdb_filename_on_ipod (Itdb_Track *track) g_return_val_if_fail (track, NULL); g_return_val_if_fail (track->itdb, NULL); - if (!track->itdb->mountpoint) return NULL; + if (!itdb_get_mountpoint (track->itdb)) return NULL; - mp = track->itdb->mountpoint; + mp = itdb_get_mountpoint (track->itdb); if(track->ipod_path && *track->ipod_path) { @@ -4991,7 +4988,7 @@ gboolean itdb_cp (const gchar *from_file, const gchar *to_file, * passing a pointer to the itdb because this function may be used * without relation to a particular itdb. * - * Return value: path to the control dir or NULL of none exists. Must + * Return value: path to the control dir or NULL of non-existent. Must * g_free() after use. */ gchar *itdb_get_control_dir (const gchar *mountpoint) @@ -5013,29 +5010,140 @@ gchar *itdb_get_control_dir (const gchar *mountpoint) return result; } -/* Retrieve the iTunes directory (containing the iTunesDB) by first - * calling itdb_get_control_dir() and then adding 'iTunes' +/* Retrieve the directory @dir by first calling itdb_get_control_dir() + * and then adding @dir * - * Return value: path to the iTunes directory or NULL of non - * exists. Must g_free() after use. + * Return value: path to @dir or NULL if non-existent. Must g_free() + * after use. */ -gchar *itdb_get_itunes_dir (const gchar *mountpoint) +static gchar *itdb_get_dir (const gchar *mountpoint, const gchar *dir) { - const gchar *p_itunes[] = {"iTunes", NULL}; gchar *control_dir; gchar *result = NULL; g_return_val_if_fail (mountpoint, NULL); + g_return_val_if_fail (dir, NULL); control_dir = itdb_get_control_dir (mountpoint); if (control_dir) { - result = itdb_resolve_path (control_dir, p_itunes); + const gchar *p_dir[] = {NULL, NULL}; + p_dir[0] = dir; + result = itdb_resolve_path (control_dir, p_dir); g_free (control_dir); } return result; } +/* Retrieve a path to the @file in @dir + * + * Return value: path to the @file or NULL if non-existent. + */ +gchar *itdb_get_path (const gchar *dir, const gchar *file) +{ + const gchar *p_file[] = {NULL, NULL}; + + g_return_val_if_fail (dir, NULL); + + p_file[0] = dir; + + return itdb_resolve_path (dir, p_file); +} + +/* Retrieve the iTunes directory (containing the iTunesDB) by first + * calling itdb_get_control_dir() and then adding 'iTunes' + * + * Return value: path to the iTunes directory or NULL of non-existent. + * Must g_free() after use. + */ +gchar *itdb_get_itunes_dir (const gchar *mountpoint) +{ + g_return_val_if_fail (mountpoint, NULL); + + return itdb_get_dir (mountpoint, "iTunes"); +} + +/* Retrieve the Music directory (containing the Fnn dirs) by first + * calling itdb_get_control_dir() and then adding 'Music' + * + * Return value: path to the Music directory or NULL of + * non-existent. Must g_free() after use. + */ +gchar *itdb_get_music_dir (const gchar *mountpoint) +{ + g_return_val_if_fail (mountpoint, NULL); + + return itdb_get_dir (mountpoint, "Music"); +} + +/* Retrieve the Device directory (containing the SysInfo file) by + * first calling itdb_get_control_dir() and then adding 'Device' + * + * Return value: path to the Device directory or NULL of + * non-existent. Must g_free() after use. + */ +gchar *itdb_get_device_dir (const gchar *mountpoint) +{ + g_return_val_if_fail (mountpoint, NULL); + + return itdb_get_dir (mountpoint, "Device"); +} + +/* Retrieve the Artwork directory (containing the SysInfo file) by + * first calling itdb_get_control_dir() and then adding 'Artwork' + * + * Return value: path to the Artwork directory or NULL of + * non-existent. Must g_free() after use. + */ +gchar *itdb_get_artwork_dir (const gchar *mountpoint) +{ + g_return_val_if_fail (mountpoint, NULL); + + return itdb_get_dir (mountpoint, "Artwork"); +} + +/* Retrieve a path to the iTunesDB + * + * Return value: path to the iTunesDB or NULL if non-existent. + */ +gchar *itdb_get_itunesdb_path (const gchar *mountpoint) +{ + gchar *itunes_dir, *path=NULL; + + g_return_val_if_fail (mountpoint, NULL); + + itunes_dir = itdb_get_itunes_dir (mountpoint); + + if (itunes_dir) + { + path = itdb_get_path (itunes_dir, "iTunesDB"); + g_free (itunes_dir); + } + + return path; +} + +/* Retrieve a path to the ArtworkDB + * + * Return value: path to the ArtworkDB or NULL if non-existent. + */ +gchar *itdb_get_artworkdb_path (const gchar *mountpoint) +{ + gchar *itunes_dir, *path=NULL; + + g_return_val_if_fail (mountpoint, NULL); + + itunes_dir = itdb_get_artwork_dir (mountpoint); + + if (itunes_dir) + { + path = itdb_get_path (itunes_dir, "ArtworkDB"); + g_free (itunes_dir); + } + + return path; +} + /*------------------------------------------------------------------*\ * * diff --git a/src/itdb_private.h b/src/itdb_private.h index 5eacc3d..c67647e 100644 --- a/src/itdb_private.h +++ b/src/itdb_private.h @@ -1,4 +1,4 @@ -/* Time-stamp: <2006-03-11 01:27:48 jcs> +/* Time-stamp: <2006-03-15 00:11:00 jcs> | | Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net> | Part of the gtkpod project. diff --git a/src/itdb_track.c b/src/itdb_track.c index a89ea4f..c85e207 100644 --- a/src/itdb_track.c +++ b/src/itdb_track.c @@ -1,4 +1,4 @@ -/* Time-stamp: <2005-12-04 19:10:42 jcs> +/* Time-stamp: <2006-03-15 00:11:15 jcs> | | Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net> | Part of the gtkpod project. @@ -30,18 +30,24 @@ #include <config.h> #include "itdb_private.h" +#include "itdb_device.h" #include <string.h> -static gboolean is_video_ipod (IpodDevice *ipod) +static gboolean is_video_ipod (Itdb_Device *device) { - guint model; + const Itdb_IpodModel *model; - if (ipod == NULL) { - return FALSE; - } - g_object_get (G_OBJECT (ipod), "device-model", &model, NULL); - return ((model == MODEL_TYPE_VIDEO_WHITE) - || (model == MODEL_TYPE_VIDEO_BLACK)); + g_return_val_if_fail (device, FALSE); + + model = itdb_device_get_ipod_model (device); + + if (!model) return FALSE; + + if ((model->model_type == MODEL_TYPE_VIDEO_WHITE) || + (model->model_type == MODEL_TYPE_VIDEO_BLACK)) + return TRUE; + else + return FALSE; } diff --git a/src/ithumb-writer.c b/src/ithumb-writer.c index e6411b9..957aca8 100644 --- a/src/ithumb-writer.c +++ b/src/ithumb-writer.c @@ -45,7 +45,7 @@ struct _iThumbWriter { off_t cur_offset; FILE *f; gchar *filename; - IpodArtworkFormat *img_info; + Itdb_ArtworkFormat *img_info; GHashTable *cache; }; typedef struct _iThumbWriter iThumbWriter; @@ -105,35 +105,40 @@ pack_RGB_565 (GdkPixbuf *pixbuf, int dst_width, int dst_height) static char * ipod_image_get_ithmb_filename (const char *mount_point, gint correlation_id, gint index) { - char *paths[] = {"iPod_Control", "Artwork", NULL, NULL}; - char *filename, *buf; + gchar *artwork_dir, *filename, *buf; - buf = g_strdup_printf ("F%04u_%d.ithmb", correlation_id, index); + g_return_val_if_fail (mount_point, NULL); + artwork_dir = itdb_get_artwork_dir (mount_point); + if (!artwork_dir) + { + /* attempt to create Artwork dir */ + gchar *control_dir = itdb_get_control_dir (mount_point); + gchar *dir; + if (!control_dir) + { /* give up */ + return NULL; + } + dir = g_build_filename (control_dir, "Artwork", NULL); + mkdir (dir, 0777); + g_free (dir); + g_free (control_dir); + + /* try again */ + artwork_dir = itdb_get_artwork_dir (mount_point); + if (!artwork_dir) + { /* give up */ + return NULL; + } + } - paths[2] = buf; + buf = g_strdup_printf ("F%04u_%d.ithmb", correlation_id, index); - filename = itdb_resolve_path (mount_point, (const char **)paths); + filename = itdb_get_path (artwork_dir, buf); - /* itdb_resolve_path() only returns existing paths */ + /* itdb_get_path() only returns existing paths */ if (!filename) { - gchar *path; - paths[2] = NULL; - path = itdb_resolve_path (mount_point, (const char **)paths); - if (path == NULL) - { /* attempt to create directory */ - gchar *pth = g_build_filename (mount_point, - paths[0], paths[1], NULL); - mkdir (pth, 0777); - g_free (pth); - path = itdb_resolve_path (mount_point, - (const char **)paths); - } - if (path) - { - filename = g_build_filename (path, buf, NULL); - } - g_free (path); + filename = g_build_filename (artwork_dir, buf, NULL); } g_free (buf); @@ -239,14 +244,14 @@ write_thumbnail (gpointer _writer, gpointer _artwork) } static iThumbWriter * -ithumb_writer_new (const char *mount_point, const IpodArtworkFormat *info) +ithumb_writer_new (const char *mount_point, const Itdb_ArtworkFormat *info) { char *filename; iThumbWriter *writer; writer = g_new0 (iThumbWriter, 1); - writer->img_info = g_memdup (info, sizeof (IpodArtworkFormat)); + writer->img_info = g_memdup (info, sizeof (Itdb_ArtworkFormat)); writer->cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); @@ -499,7 +504,7 @@ static gboolean ithumb_rearrange_thumbnail_file (gpointer _key, */ static gboolean ithmb_rearrange_existing_thumbnails (Itdb_iTunesDB *itdb, - const IpodArtworkFormat *info) + const Itdb_ArtworkFormat *info) { GList *gl; GHashTable *filenamehash; @@ -507,10 +512,15 @@ ithmb_rearrange_existing_thumbnails (Itdb_iTunesDB *itdb, GList *thumbs; gint i; gchar *filename; + const gchar *mountpoint; g_return_val_if_fail (itdb, FALSE); g_return_val_if_fail (info, FALSE); - g_return_val_if_fail (itdb->mountpoint, FALSE); + g_return_val_if_fail (itdb->device, FALSE); + + mountpoint = itdb_get_mountpoint (itdb); + + g_return_val_if_fail (mountpoint, FALSE); filenamehash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); @@ -545,7 +555,7 @@ ithmb_rearrange_existing_thumbnails (Itdb_iTunesDB *itdb, for (i=0; i<10; ++i) { - filename = ipod_image_get_ithmb_filename (itdb->mountpoint, + filename = ipod_image_get_ithmb_filename (mountpoint, info->correlation_id, i); if (g_file_test (filename, G_FILE_TEST_EXISTS)) @@ -574,13 +584,13 @@ itdb_write_ithumb_files (Itdb_iTunesDB *db) #ifdef HAVE_GDKPIXBUF GList *writers; GList *it; - gchar *mount_point; - const IpodArtworkFormat *format; + const gchar *mount_point; + const Itdb_ArtworkFormat *format; /* g_print ("%s\n", G_GNUC_FUNCTION);*/ g_return_val_if_fail (db, -1); - mount_point = db->mountpoint; + mount_point = itdb_get_mountpoint (db); /* FIXME: support writing to directory rather than writing to iPod */ if (mount_point == NULL) @@ -590,8 +600,7 @@ itdb_write_ithumb_files (Itdb_iTunesDB *db) return -1; } - g_object_get (G_OBJECT (db->device), "artwork-formats", - &format, NULL); + format = itdb_device_get_artwork_formats (db->device); if (format == NULL) { return -1; } |