Revision: 2369
http://gtkpod.svn.sourceforge.net/gtkpod/?rev=2369&view=rev
Author: teuf
Date: 2009-06-05 20:43:00 +0000 (Fri, 05 Jun 2009)
Log Message:
-----------
Parse zoneinfo files to get 'the' UTC offset for a given timezone
Modified Paths:
--------------
libgpod/trunk/ChangeLog
libgpod/trunk/src/itdb_tzinfo.c
Modified: libgpod/trunk/ChangeLog
===================================================================
--- libgpod/trunk/ChangeLog 2009-06-05 20:42:44 UTC (rev 2368)
+++ libgpod/trunk/ChangeLog 2009-06-05 20:43:00 UTC (rev 2369)
@@ -1,3 +1,13 @@
+2009-06-05 Christophe Fergeau <[email protected]>
+
+ * src/Makefile.am:
+ * src/itdb_device.c:
+ * src/itdb_tzinfo.c:
+ * src/itdb_tzinfo_data: move timezone related functions in their
+ own file, adds mapping from city names (present in the iPod
+ Preferences file) to timezone shift to be able to interpret
+ accurately timestamps from iPod Classic and similiar models.
+
2009-05-19 Christophe Fergeau <[email protected]>
* src/itdb_itunesdb.c: make sure playcounts is initialized before it's
Modified: libgpod/trunk/src/itdb_tzinfo.c
===================================================================
--- libgpod/trunk/src/itdb_tzinfo.c 2009-06-05 20:42:44 UTC (rev 2368)
+++ libgpod/trunk/src/itdb_tzinfo.c 2009-06-05 20:43:00 UTC (rev 2369)
@@ -35,6 +35,7 @@
#include "itdb_tzinfo_data.h"
#include <stdio.h>
+#include <string.h>
#include <time.h>
#include <glib/gstdio.h>
@@ -43,6 +44,9 @@
extern __IMPORT long _timezone;
#endif
+static gboolean parse_tzdata (const char *tzname, time_t start, time_t end,
+ int *offset, gboolean *has_dst, int *dst_offset);
+
G_GNUC_INTERNAL time_t device_time_mac_to_time_t (Itdb_Device *device, guint64
mactime)
{
g_return_val_if_fail (device, 0);
@@ -163,22 +167,31 @@
return TRUE;
}
-static gboolean raw_timezone_to_utc_shift_6g (gint16 raw_timezone,
+static gboolean raw_timezone_to_utc_shift_6g (gint16 city_id,
gint *utc_shift)
{
const ItdbTimezone *it;
for (it = timezones; it->city_name != NULL; it++) {
- if (it->city_index == raw_timezone) {
- break;
+ if (it->city_index == city_id) {
+ int offset;
+ gboolean unused1;
+ int unused2;
+ gboolean got_tzinfo;
+ g_print ("timezone: %s\n", it->tz_name);
+ got_tzinfo = parse_tzdata (it->tz_name, time (NULL), time (NULL),
+ &offset, &unused1, &unused2);
+ if (!got_tzinfo) {
+ return FALSE;
+ }
+ *utc_shift = offset*60;
+
+ return TRUE;
}
}
- if (it->city_name == NULL) {
- return FALSE;
- }
- g_print ("timezone: %s\n", it->tz_name);
- *utc_shift = 0;
- return TRUE;
+
+ /* unknown city ID */
+ return FALSE;
}
static gint get_local_timezone (void)
@@ -286,3 +299,122 @@
device->timezone_shift = timezone;
}
+
+/*
+ * The following function was copied from libgweather/gweather-timezone.c
+ *
+ * Copyright 2008, Red Hat, Inc.
+ *
+ * This library 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.
+ *
+ * libgweather uses it for a different purpose than libgpod's, namely
+ * finding if a given world location uses DST (not 'now' but at some point
+ * during the year) and getting the offset.
+ * libgpod only needs to know the offset from UTC, and if start == end when
+ * calling this function, this is exactly what we get!
+ */
+#define ZONEINFO_DIR "/usr/share/zoneinfo"
+
+#define TZ_MAGIC "TZif"
+#define TZ_HEADER_SIZE 44
+#define TZ_TIMECNT_OFFSET 32
+#define TZ_TRANSITIONS_OFFSET 44
+
+#define TZ_TTINFO_SIZE 6
+#define TZ_TTINFO_GMTOFF_OFFSET 0
+#define TZ_TTINFO_ISDST_OFFSET 4
+
+static gboolean
+parse_tzdata (const char *tzname, time_t start, time_t end,
+ int *offset, gboolean *has_dst, int *dst_offset)
+{
+ char *filename, *contents;
+ gsize length;
+ int timecnt, transitions_size, ttinfo_map_size;
+ int initial_transition = -1, second_transition = -1;
+ gint32 *transitions;
+ char *ttinfo_map, *ttinfos;
+ gint32 initial_offset, second_offset;
+ char initial_isdst, second_isdst;
+ int i;
+
+ filename = g_build_filename (ZONEINFO_DIR, tzname, NULL);
+ if (!g_file_get_contents (filename, &contents, &length, NULL)) {
+ g_free (filename);
+ return FALSE;
+ }
+ g_free (filename);
+
+ if (length < TZ_HEADER_SIZE ||
+ strncmp (contents, TZ_MAGIC, strlen (TZ_MAGIC)) != 0) {
+ g_free (contents);
+ return FALSE;
+ }
+
+ timecnt = GUINT32_FROM_BE (*(guint32 *)(contents + TZ_TIMECNT_OFFSET));
+ transitions = (void *)(contents + TZ_TRANSITIONS_OFFSET);
+ transitions_size = timecnt * sizeof (*transitions);
+ ttinfo_map = (void *)(contents + TZ_TRANSITIONS_OFFSET + transitions_size);
+ ttinfo_map_size = timecnt;
+ ttinfos = (void *)(ttinfo_map + ttinfo_map_size);
+
+ /* @transitions is an array of @timecnt time_t values. We need to
+ * find the transition into the current offset, which is the last
+ * transition before @start. If the following transition is before
+ * @end, then note that one too, since it presumably means we're
+ * doing DST.
+ */
+ for (i = 1; i < timecnt && initial_transition == -1; i++) {
+ if (GINT32_FROM_BE (transitions[i]) > start) {
+ initial_transition = ttinfo_map[i - 1];
+ if (GINT32_FROM_BE (transitions[i]) < end)
+ second_transition = ttinfo_map[i];
+ }
+ }
+ if (initial_transition == -1) {
+ if (timecnt)
+ initial_transition = ttinfo_map[timecnt - 1];
+ else
+ initial_transition = 0;
+ }
+
+ /* Copy the data out of the corresponding ttinfo structs */
+ initial_offset = *(gint32 *)(ttinfos +
+ initial_transition * TZ_TTINFO_SIZE +
+ TZ_TTINFO_GMTOFF_OFFSET);
+ initial_offset = GINT32_FROM_BE (initial_offset);
+ initial_isdst = *(ttinfos +
+ initial_transition * TZ_TTINFO_SIZE +
+ TZ_TTINFO_ISDST_OFFSET);
+
+ if (second_transition != -1) {
+ second_offset = *(gint32 *)(ttinfos +
+ second_transition * TZ_TTINFO_SIZE +
+ TZ_TTINFO_GMTOFF_OFFSET);
+ second_offset = GINT32_FROM_BE (second_offset);
+ second_isdst = *(ttinfos +
+ second_transition * TZ_TTINFO_SIZE +
+ TZ_TTINFO_ISDST_OFFSET);
+
+ *has_dst = (initial_isdst != second_isdst);
+ } else
+ *has_dst = FALSE;
+
+ if (!*has_dst)
+ *offset = initial_offset / 60;
+ else {
+ if (initial_isdst) {
+ *offset = second_offset / 60;
+ *dst_offset = initial_offset / 60;
+ } else {
+ *offset = initial_offset / 60;
+ *dst_offset = second_offset / 60;
+ }
+ }
+
+ g_free (contents);
+ return TRUE;
+}
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
OpenSolaris 2009.06 is a cutting edge operating system for enterprises
looking to deploy the next generation of Solaris that includes the latest
innovations from Sun and the OpenSource community. Download a copy and
enjoy capabilities such as Networking, Storage and Virtualization.
Go to: http://p.sf.net/sfu/opensolaris-get
_______________________________________________
gtkpod-cvs2 mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/gtkpod-cvs2