Пример #1
0
static GDateTime *parse_datetime(const char *str)
{
	if(str == NULL) return NULL;

	GDateTime *ret = NULL;
	char **bits = g_strsplit(str, " ", -1);
	int num_bits = g_strv_length(bits);
	if(num_bits < 6) {
		g_debug("num_bits for `%s' isn't valid; format unknown", str);
		goto fail;
	}

	/* #0 is day-of-week in english. that's skipped. */
	int month = parse_month(bits[1]);
	if(month <= 0) goto fail;
	int day = atoi(bits[2]);
	if(day == 0) goto fail;
	int hour, min, sec;
	if(sscanf(bits[3], "%d:%d:%d", &hour, &min, &sec) != 3) goto fail;
	int year = atoi(bits[5]);
	if(year < 0) goto fail;
	GTimeZone *tz = g_time_zone_new(bits[4]);
	if(tz == NULL) goto fail;

	ret = g_date_time_new(tz, year, month, day, hour, min, sec);
	g_time_zone_unref(tz);
	if(ret == NULL) {
		g_debug("couldn't make a new timestamp");
	}

fail:
	g_strfreev(bits);
	return ret;
}
Пример #2
0
static time_t
date_to_time_t (const xmlChar *str, const char * tzid)
{
    struct tm time = { 0 };
    GTimeZone *tz;
    GDateTime *dt;
    time_t rval;
    char *after;

    after = strptime ((const char*) str, "%Y-%m-%dT%T", &time);
    if (after == NULL) {
	g_warning ("Cannot parse date string \"%s\"", str);
	return 0;
    }

    if (*after == 'Z')
	tzid = "UTC";

    tz = g_time_zone_new (tzid);
    dt = g_date_time_new (tz,
			  time.tm_year + 1900,
			  time.tm_mon + 1,
			  time.tm_mday,
			  time.tm_hour,
			  time.tm_min,
			  time.tm_sec);

    rval = g_date_time_to_unix (dt);

    g_time_zone_unref (tz);
    g_date_time_unref (dt);

    return rval;
}
Пример #3
0
struct GDateTime *voy_cookie_parse_expires_date(char const *date_string) {
  struct tm tm;
  strptime(date_string, VOY_COOKIE_TIME_FORMAT, &tm);
  struct GDateTime *date_time = g_date_time_new(g_time_zone_new("Z"), tm.tm_year + 1900,
    tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
  return date_time;
}
DateTime DateTime::to_timezone(const std::string& zone) const
{
    auto gtz = g_time_zone_new(zone.c_str());
    auto gdt = g_date_time_to_timezone(get(), gtz);
    DateTime dt(gtz, gdt);
    g_time_zone_unref(gtz);
    g_date_time_unref(gdt);
    return dt;
}
Пример #5
0
/**
 * vu_get_time_string:
 *
 * @time_t: The time of which the string is wanted
 * @format  The format of the time string - such as "%c"
 * @vc:     Position of object for the time output - maybe NULL
 *          (only applicable for VIK_TIME_REF_WORLD)
 * @tz:     TimeZone string - maybe NULL.
 *          (only applicable for VIK_TIME_REF_WORLD)
 *          Useful to pass in the cached value from vu_get_tz_at_location() to save looking it up again for the same position
 *
 * Returns: A string of the time according to the time display property
 */
gchar* vu_get_time_string ( time_t *time, const gchar *format, const VikCoord* vc, const gchar *tz )
{
	if ( !format ) return NULL;
	gchar *str = NULL;
	switch ( a_vik_get_time_ref_frame() ) {
		case VIK_TIME_REF_UTC:
			str = g_malloc ( 64 );
			strftime ( str, 64, format, gmtime(time) ); // Always 'GMT'
			break;
		case VIK_TIME_REF_WORLD:
			if ( vc && !tz ) {
				// No timezone specified so work it out
				gchar *mytz = vu_get_tz_at_location ( vc );
				if ( mytz ) {
					GTimeZone *gtz = g_time_zone_new ( mytz );
					str = time_string_tz ( time, format, gtz );
					g_time_zone_unref ( gtz );
				}
				else {
					// No results (e.g. could be in the middle of a sea)
					// Fallback to simplistic method that doesn't take into account Timezones of countries.
					struct LatLon ll;
					vik_coord_to_latlon ( vc, &ll );
					str = time_string_adjusted ( time, round ( ll.lon / 15.0 ) * 3600 );
				}
			}
			else {
				// Use specified timezone
				GTimeZone *gtz = g_time_zone_new ( tz );
				str = time_string_tz ( time, format, gtz );
				g_time_zone_unref ( gtz );
			}
			break;
		default: // VIK_TIME_REF_LOCALE
			str = g_malloc ( 64 );
			strftime ( str, 64, format, localtime(time) );
			break;
	}
	return str;
}
Пример #6
0
static VALUE
rg_initialize(gint argc, VALUE *argv, VALUE self)
{
    VALUE rb_identifier = Qnil;
    const gchar *identifier = NULL;
    GTimeZone *time_zone = NULL;

    rb_scan_args(argc, argv, "01", &rb_identifier);

    if (!NIL_P(rb_identifier))
        identifier = RVAL2CSTR(rb_identifier);

    time_zone = g_time_zone_new(identifier);
    G_INITIALIZE(self, time_zone);
    return Qnil;
}
Пример #7
0
/***********************************************************\
 * GLib's GTimeZone doesn't work with MSWindows, which in turn breaks
 * g_date_time_new_local, g_date_time_new_from_unix_local,
 * g_date_time_new_from_timeval_local, and gnc_g_date_time_to_local. The
 * following functions provide a work-around.
 */
static GTimeZone*
gnc_g_time_zone_new_local (void)
{
#ifndef G_OS_WIN32
    return g_time_zone_new_local();
#else
    TIME_ZONE_INFORMATION tzinfo;
    gint64 dst = GetTimeZoneInformation (&tzinfo);
    gint bias = tzinfo.Bias + tzinfo.StandardBias;
    gint hours = -bias / 60; // 60 minutes per hour
    gint minutes = (bias < 0 ? -bias : bias) % 60;
    gchar *tzstr = g_strdup_printf ("%+03d:%02d", hours, minutes);
    GTimeZone *tz = g_time_zone_new(tzstr);
    g_free (tzstr);
    return tz;
#endif
}
static void
update_timestamp (IdoLocationMenuItem * self)
{
  GTimeZone * tz;
  GDateTime * date_time;

  tz = g_time_zone_new (self->priv->timezone);
  if (tz == NULL)
    tz = g_time_zone_new_local ();
  date_time = g_date_time_new_now (tz);

  ido_time_stamp_menu_item_set_date_time (IDO_TIME_STAMP_MENU_ITEM(self),
                                          date_time);

  g_date_time_unref (date_time);
  g_time_zone_unref (tz);
}
Пример #9
0
GDateTime*
icaltime_to_datetime (const icaltimetype  *date)
{
  GDateTime *dt;
  GTimeZone *tz;

  tz = date->zone ? g_time_zone_new (icaltime_get_tzid (*date)) : g_time_zone_new_utc ();
  dt = g_date_time_new (tz,
                        date->year,
                        date->month,
                        date->day,
                        date->is_date ? 0 : date->hour,
                        date->is_date ? 0 : date->minute,
                        date->is_date ? 0 : date->second);

  g_clear_pointer (&tz, g_time_zone_unref);

  return dt;
}
Пример #10
0
GstDateTime *
gst_date_time_new (gfloat tzoffset, gint year, gint month, gint day, gint hour,
    gint minute, gdouble seconds)
{
  gchar buf[6];
  GTimeZone *tz;
  GDateTime *dt;
  gint tzhour, tzminute;

  tzhour = (gint) ABS (tzoffset);
  tzminute = (gint) ((ABS (tzoffset) - tzhour) * 60);

  g_snprintf (buf, 6, "%c%02d%02d", tzoffset >= 0 ? '+' : '-', tzhour,
      tzminute);

  tz = g_time_zone_new (buf);

  dt = g_date_time_new (tz, year, month, day, hour, minute, seconds);
  g_time_zone_unref (tz);
  return gst_date_time_new_from_gdatetime (dt);
}
Пример #11
0
static GTimeZone*
gnc_g_time_zone_adjust_for_dst (GTimeZone* tz, GDateTime *date)
{
#ifdef G_OS_WIN32
    TIME_ZONE_INFORMATION tzinfo;
    gint64 dst = GetTimeZoneInformation (&tzinfo);
    gint bias, hours, minutes;
    gchar *tzstr;
    g_return_val_if_fail (date != NULL, NULL);
    if (dst > 0 && win32_in_dst (date, &tzinfo))
    {
        g_time_zone_unref (tz);
	bias = tzinfo.Bias + tzinfo.DaylightBias;
	hours = -bias / 60; // 60 minutes per hour
	minutes = (bias < 0 ? -bias : bias) % 60;
	tzstr = g_strdup_printf ("%+03d:%02d", hours, minutes);
	tz = g_time_zone_new(tzstr);
    }
#endif
    return tz;
}
Пример #12
0
/**
 * gst_date_time_new:
 * @tzoffset: Offset from UTC in hours.
 * @year: the gregorian year
 * @month: the gregorian month
 * @day: the day of the gregorian month
 * @hour: the hour of the day
 * @minute: the minute of the hour
 * @seconds: the second of the minute
 *
 * Creates a new #GstDateTime using the date and times in the gregorian calendar
 * in the supplied timezone.
 *
 * @year should be from 1 to 9999, @month should be from 1 to 12, @day from
 * 1 to 31, @hour from 0 to 23, @minutes and @seconds from 0 to 59.
 *
 * Note that @tzoffset is a float and was chosen so for being able to handle
 * some fractional timezones, while it still keeps the readability of
 * representing it in hours for most timezones.
 *
 * If value is -1 then all over value will be ignored. For example
 * if @month == -1, then #GstDateTime will created only for @year. If
 * @day == -1, then #GstDateTime will created for @year and @month and
 * so on.
 *
 * Free-function: gst_date_time_unref
 *
 * Return value: (transfer full) (nullable): the newly created #GstDateTime
 */
GstDateTime *
gst_date_time_new (gfloat tzoffset, gint year, gint month, gint day, gint hour,
    gint minute, gdouble seconds)
{
  GstDateTimeFields fields;
  gchar buf[6];
  GTimeZone *tz;
  GDateTime *dt;
  GstDateTime *datetime;
  gint tzhour, tzminute;

  g_return_val_if_fail (year > 0 && year <= 9999, NULL);
  g_return_val_if_fail ((month > 0 && month <= 12) || month == -1, NULL);
  g_return_val_if_fail ((day > 0 && day <= 31) || day == -1, NULL);
  g_return_val_if_fail ((hour >= 0 && hour < 24) || hour == -1, NULL);
  g_return_val_if_fail ((minute >= 0 && minute < 60) || minute == -1, NULL);
  g_return_val_if_fail ((seconds >= 0 && seconds < 60) || seconds == -1, NULL);
  g_return_val_if_fail (tzoffset >= -12.0 && tzoffset <= 12.0, NULL);
  g_return_val_if_fail ((hour >= 0 && minute >= 0) ||
      (hour == -1 && minute == -1 && seconds == -1 && tzoffset == 0.0), NULL);

  tzhour = (gint) ABS (tzoffset);
  tzminute = (gint) ((ABS (tzoffset) - tzhour) * 60);

  g_snprintf (buf, 6, "%c%02d%02d", tzoffset >= 0 ? '+' : '-', tzhour,
      tzminute);

  tz = g_time_zone_new (buf);

  fields = gst_date_time_check_fields (&year, &month, &day,
      &hour, &minute, &seconds);

  dt = g_date_time_new (tz, year, month, day, hour, minute, seconds);
  g_time_zone_unref (tz);

  datetime = gst_date_time_new_from_g_date_time (dt);
  datetime->fields = fields;

  return datetime;
}
Пример #13
0
Timespec
gnc_iso8601_to_timespec_gmt(const char *str)
{
    Timespec time = { 0L, 0L };
    GDateTime *gdt;
    gint hour = 0, minute = 0, day = 0, month = 0, year = 0;
    gchar zone[12];
    gdouble second = 0.0;
    gint fields;

    memset (zone, 0, sizeof (zone));

    if (!str)
	return time;

    fields = sscanf (str, ISO_DATE_FORMAT, &year, &month,
			  &day, &hour, &minute, &second, zone);
    if (fields < 1)
	return time;
    else if (fields > 6 && strlen (zone) > 0) /* Date string included a timezone */
    {
	GTimeZone *tz = g_time_zone_new (zone);
        time64 secs;
	second += 5e-10;
	gdt = g_date_time_new (tz, year, month, day, hour, minute, second);
        secs = g_date_time_to_unix (gdt);
	g_time_zone_unref (tz);
    }
    else /* No zone info, assume UTC */
    {
	second += 5e-10;
	gdt = g_date_time_new_utc (year, month, day, hour, minute, second);
    }

    time.tv_sec = g_date_time_to_unix (gdt);
    time.tv_nsec = g_date_time_get_microsecond (gdt) * 1000;
    g_date_time_unref (gdt);
    return time;
}
static void
location_changed_cb (CcTimezoneMap   *map,
                     TzLocation      *location,
                     CcDateTimePanel *self)
{
  CcDateTimePanelPrivate *priv = self->priv;
  GDateTime *old_date;
  GTimeZone *timezone;

  g_debug ("location changed to %s/%s", location->country, location->zone);

  priv->current_location = location;

  old_date = priv->date;

  timezone = g_time_zone_new (location->zone);
  priv->date = g_date_time_to_timezone (old_date, timezone);
  g_time_zone_unref (timezone);

  g_date_time_unref (old_date);

  update_timezone (self);
  queue_set_timezone (self);
}
Пример #15
0
int32_t dt_control_gpx_apply_job_run(dt_job_t *job)
{
  dt_control_image_enumerator_t *t1 = (dt_control_image_enumerator_t *)job->param;
  GList *t = t1->index;
  struct dt_gpx_t *gpx = NULL;
  uint32_t cntr = 0;
  const dt_control_gpx_apply_t *d = t1->data;
  const gchar *filename = d->filename;
  const gchar *tz = d->tz;

  /* do we have any selected images */
  if (!t)
    goto bail_out;

  /* try parse the gpx data */
  gpx = dt_gpx_new(filename);
  if (!gpx)
  {
    dt_control_log(_("failed to parse gpx file"));
    goto bail_out;
  }

  GTimeZone *tz_camera = (tz == NULL)?g_time_zone_new_utc():g_time_zone_new(tz);
  if(!tz_camera)
    goto bail_out;
  GTimeZone *tz_utc = g_time_zone_new_utc();

  /* go thru each selected image and lookup location in gpx */
  do
  {
    GTimeVal timestamp;
    GDateTime *exif_time, *utc_time;
    gdouble lon,lat;
    uint32_t imgid = (long int)t->data;

    /* get image */
    const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, imgid);
    if (!cimg)
      continue;

    /* convert exif datetime
       TODO: exiv2 dates should be iso8601 and we are probably doing some ugly
       convertion before inserting into database.
     */
    gint year;
    gint month;
    gint day;
    gint hour;
    gint minute;
    gint  seconds;

    if (sscanf(cimg->exif_datetime_taken, "%d:%d:%d %d:%d:%d",
               (int*)&year, (int*)&month, (int*)&day,
               (int*)&hour,(int*)&minute,(int*)&seconds) != 6)
    {
      fprintf(stderr,"broken exif time in db, '%s'\n", cimg->exif_datetime_taken);
      dt_image_cache_read_release(darktable.image_cache, cimg);
      continue;
    }

    /* release the lock */
    dt_image_cache_read_release(darktable.image_cache, cimg);

    exif_time = g_date_time_new(tz_camera, year, month, day, hour, minute, seconds);
    if(!exif_time)
      continue;
    utc_time = g_date_time_to_timezone(exif_time, tz_utc);
    g_date_time_unref(exif_time);
    if(!utc_time)
      continue;
    gboolean res = g_date_time_to_timeval(utc_time, &timestamp);
    g_date_time_unref(utc_time);
    if(!res)
      continue;

    /* only update image location if time is within gpx tack range */
    if(dt_gpx_get_location(gpx, &timestamp, &lon, &lat))
    {
      dt_image_set_location(imgid, lon, lat);
      cntr++;
    }

  }
  while((t = g_list_next(t)) != NULL);

  dt_control_log(_("applied matched gpx location onto %d image(s)"), cntr);

  g_time_zone_unref(tz_camera);
  g_time_zone_unref(tz_utc);
  dt_gpx_destroy(gpx);
  g_free(d->filename);
  g_free(d->tz);
  g_free(t1->data);
  return 0;

bail_out:
  if (gpx)
    dt_gpx_destroy(gpx);

  g_free(d->filename);
  g_free(d->tz);
  g_free(t1->data);
  return 1;
}
Пример #16
0
/*
 * gda_ldap_attr_value_to_g_value:
 * Converts a #BerValue to a new #GValue
 *
 * Returns: a new #GValue, or %NULL on error
 */
GValue *
gda_ldap_attr_value_to_g_value (LdapConnectionData *cdata, GType type, BerValue *bv)
{
	GValue *value = NULL;
	if ((type == G_TYPE_DATE_TIME) ||
	    (type == G_TYPE_DATE)) {
		/* see ftp://ftp.rfc-editor.org/in-notes/rfc4517.txt,
		 * section 3.3.13: Generalized Time
		 */
		GTimeVal tv;
		gboolean conv;
		if (! (conv = g_time_val_from_iso8601 (bv->bv_val,
						       &tv))) {
			/* Add the 'T' char */
			gchar *tmp, *str;
			gint i, len;
			str = bv->bv_val;
			len = strlen (str);
			if (len > 8) {
				tmp = g_new (gchar, len + 2);
				for (i = 0; i < 8; i++)
					tmp[i] = str[i];
				tmp [8] = 'T';
				for (i = 9; str[i]; i++)
					tmp[i] = str[i-1];
				tmp[i] = 0;
				conv = g_time_val_from_iso8601 (tmp, &tv);
				g_free (tmp);
			}
		}
		if (conv) {
			struct tm *ptm;
#ifdef HAVE_LOCALTIME_R
			struct tm tmpstm;
			ptm = localtime_r (&(tv.tv_sec), &tmpstm);
#elif HAVE_LOCALTIME_S
			struct tm tmpstm;
			if (localtime_s (&tmpstm, &(tv.tv_sec)) == 0)
				ptm = &tmpstm;
			else
				ptm = NULL;
#else
			ptm = localtime (&(tv.tv_sec));
#endif

			if (!ptm)
				return NULL;

			if (g_type_is_a (type, G_TYPE_DATE_TIME)) {
				GTimeZone *tz = g_time_zone_new ("Z"); // UTC
				GDateTime *ts = g_date_time_new (tz,
																				 ptm->tm_year + 1900,
																				 ptm->tm_mon + 1,
																				 ptm->tm_mday,
																				 ptm->tm_hour,
																				 ptm->tm_min,
																				 ptm->tm_sec);
				value = gda_value_new (G_TYPE_DATE_TIME);
				g_value_set_boxed (value, ts);
				g_date_time_unref (ts);
			}
			else {
				GDate *date;
				date = g_date_new ();
				g_date_set_time_val (date, &tv);
				value = gda_value_new (type);
				g_value_take_boxed (value, date);
			}
		}
	}
	else if (type == GDA_TYPE_BINARY) {
		guchar *data;
		data = g_new (guchar, bv->bv_len);
		memcpy (data, bv->bv_val, sizeof (guchar) * bv->bv_len);
		value = gda_value_new_binary (data, bv->bv_len);
	}
	else
		value = gda_value_new_from_string (bv->bv_val, type);

	return value;
}
static gboolean
get_result_metas_cb (GcalShellSearchProvider  *search_provider,
                     GDBusMethodInvocation    *invocation,
                     gchar                   **results,
                     GcalShellSearchProvider2 *skel)
{
  GcalShellSearchProviderPrivate *priv;
  gint i;
  gchar *uuid, *desc;
  const gchar* location;

  g_autoptr(GTimeZone) tz;
  g_autoptr (GDateTime) datetime;
  g_autoptr (GDateTime) local_datetime;
  ECalComponentDateTime dtstart;
  gchar *start_date;

  ECalComponentText summary;
  GdkRGBA color;
  GVariantBuilder abuilder, builder;
  GVariant *icon_variant;
  GcalEventData *data;
  GdkPixbuf *gicon;

  priv = search_provider->priv;

  g_variant_builder_init (&abuilder, G_VARIANT_TYPE ("aa{sv}"));
  for (i = 0; i < g_strv_length (results); i++)
    {
      uuid = results[i];
      data = g_hash_table_lookup (priv->events, uuid);

      g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
      g_variant_builder_add (&builder, "{sv}", "id", g_variant_new_string (uuid));

      e_cal_component_get_summary (data->event_component, &summary);
      g_variant_builder_add (&builder, "{sv}", "name", g_variant_new_string (summary.value));

      get_color_name_from_source (data->source, &color);
      gicon = get_circle_pixbuf_from_color (&color, 128);
      icon_variant = g_icon_serialize (G_ICON (gicon));
      g_variant_builder_add (&builder, "{sv}", "icon", icon_variant);
      g_object_unref (gicon);
      g_variant_unref (icon_variant);

      e_cal_component_get_dtstart (data->event_component, &dtstart);

      if (dtstart.tzid != NULL)
        tz = g_time_zone_new (dtstart.tzid);
      else if (dtstart.value->zone != NULL)
        tz = g_time_zone_new (icaltimezone_get_tzid ((icaltimezone*) dtstart.value->zone));
      else
        tz = g_time_zone_new_local ();

      datetime = g_date_time_new (tz,
                                  dtstart.value->year, dtstart.value->month, dtstart.value->day,
                                  dtstart.value->hour, dtstart.value->minute, dtstart.value->second);
      local_datetime = g_date_time_to_local (datetime);

      /* FIXME: respect 24h time format */
      start_date = g_date_time_format (local_datetime,
                                       (dtstart.value->is_date == 1) ? "%x" : "%c");
      e_cal_component_free_datetime (&dtstart);

      e_cal_component_get_location (data->event_component, &location);
      if (location != NULL)
        desc = g_strconcat (start_date, ". ", location, NULL);
      else
        desc = g_strdup (start_date);

      g_variant_builder_add (&builder, "{sv}", "description", g_variant_new_string (desc));
      g_free (start_date);
      g_free (desc);

      g_variant_builder_add_value (&abuilder, g_variant_builder_end (&builder));
    }
  g_dbus_method_invocation_return_value (invocation, g_variant_new ("(aa{sv})", &abuilder));

  return TRUE;
}
Пример #18
0
static void
test_g_time_zone (void)
{
  g_autoptr(GTimeZone) val = g_time_zone_new ("UTC");
  g_assert (val != NULL);
}
Пример #19
0
/**
 * g_time_zone_new_local:
 *
 * Creates a #GTimeZone corresponding to local time.
 *
 * This is equivalent to calling g_time_zone_new() with the value of the
 * <varname>TZ</varname> environment variable (including the possibility
 * of %NULL).  Changes made to <varname>TZ</varname> after the first
 * call to this function may or may not be noticed by future calls.
 *
 * You should release the return value by calling g_time_zone_unref()
 * when you are done with it.
 *
 * Returns: the local timezone
 *
 * Since: 2.26
 **/
GTimeZone *
g_time_zone_new_local (void)
{
  return g_time_zone_new (getenv ("TZ"));
}
Пример #20
0
/**
 * g_time_zone_new_utc:
 *
 * Creates a #GTimeZone corresponding to UTC.
 *
 * This is equivalent to calling g_time_zone_new() with a value like
 * "Z", "UTC", "+00", etc.
 *
 * You should release the return value by calling g_time_zone_unref()
 * when you are done with it.
 *
 * Returns: the universal timezone
 *
 * Since: 2.26
 **/
GTimeZone *
g_time_zone_new_utc (void)
{
  return g_time_zone_new ("UTC");
}
Пример #21
0
int main (int argc, char *argv[])
{
    GCContext    gc_context;
    GMainLoop   *mainLoop;
    GKeyFile    *keyFile;
    GThread     *displayThread;
    GThread     *inputControllerThread;
    GThread     *x11EventThread;
    int          i;

    
    GCConfig config = {
        .movie_path          = DEFAULT_MOVIE_PATH,
        .mask_path           = DEFAULT_MASK_PATH,
        .controller_path     = DEFAULT_CONTROLLER_PATH,
        .seconds_per_frame   = DEFAULT_SECONDS_PER_FRAME,
        .easing_factor       = DEFAULT_EASING_FACTOR,
        .frames_per_tick     = 0,
        .diameter_controller = 0,
        .diameter_rim        = 0,
        .ctr                 = 0,
        .fpr                 = 0,
        .number_of_frames    = 0,
        .fullscreen          = TRUE,
        .timeZone            = NULL,
    };

    Movie movie = {
        .planes             = NULL,
        .frame_offset       = 0,
        .fd_movie           = -1,
        .frame              = { .pitches = { FRAME_PITCH, 0, 0 } },
        .fd_mask            = -1,
        .mask               = { .pitches = { MASK_PITCH, 0, 0 } },
        .pre_load_surface   = VDP_INVALID_HANDLE,
        .play_direction     = DIRECTION_FORWARD,
        .ticks              = 0,
        .new_frame          = FALSE,
        .ease_to            = TRUE,
    };

    keyFile = g_key_file_new();
    if (argc > 1 && g_key_file_load_from_file(keyFile, argv[1], G_KEY_FILE_NONE, NULL)) {
        if (g_key_file_has_group(keyFile, "MAIN")) {
            if (g_key_file_has_key(keyFile, "MAIN", "utc_offset", NULL))
                config.timeZone = g_time_zone_new(g_key_file_get_string(keyFile, "MAIN", "utc_offset", NULL));
            if (g_key_file_has_key(keyFile, "MAIN", "ease_to_time", NULL))
                movie.ease_to = g_key_file_get_boolean(keyFile, "MAIN", "ease_to_time", NULL);
        }
 
        if (g_key_file_has_group(keyFile, "MOVIE")) {
           if (g_key_file_has_key(keyFile, "MOVIE", "file", NULL))
              config.movie_path = g_key_file_get_string(keyFile, "MOVIE", "file", NULL);
           if (g_key_file_has_key(keyFile, "MOVIE", "mask", NULL))
              config.mask_path = g_key_file_get_string(keyFile, "MOVIE", "mask", NULL);
           if (g_key_file_has_key(keyFile, "MOVIE", "seconds_per_frame", NULL))
              config.seconds_per_frame = (float)g_key_file_get_double(keyFile, "MOVIE", "seconds_per_frame", NULL);
           if (g_key_file_has_key(keyFile, "MOVIE", "easing_factor", NULL))
              config.easing_factor = (float)g_key_file_get_integer(keyFile, "MOVIE", "easing_factor", NULL);
        }
        
        if (g_key_file_has_group(keyFile, "CONTROLLER")) {
           if (g_key_file_has_key(keyFile, "CONTROLLER", "path", NULL))
              config.controller_path = g_key_file_get_string(keyFile, "CONTROLLER", "path", NULL);

           if (g_key_file_has_key(keyFile, "CONTROLLER", "diameter_controller", NULL))
              config.diameter_controller = (float)g_key_file_get_double(keyFile, "CONTROLLER", "diameter_controller", NULL);
           if (g_key_file_has_key(keyFile, "CONTROLLER", "diameter_rim", NULL))
              config.diameter_rim = (float)g_key_file_get_double(keyFile, "CONTROLLER", "diameter_rim", NULL);
           if (g_key_file_has_key(keyFile, "CONTROLLER", "ctr", NULL))
              config.ctr = (float)g_key_file_get_double(keyFile, "CONTROLLER", "ctr", NULL);
           if (g_key_file_has_key(keyFile, "CONTROLLER", "fpr", NULL))
              config.fpr = (float)g_key_file_get_double(keyFile, "CONTROLLER", "fpr", NULL);
           if (g_key_file_has_key(keyFile, "CONTROLLER", "frames_per_tick", NULL))
              config.frames_per_tick = (float)g_key_file_get_double(keyFile, "CONTROLLER", "frames_per_tick", NULL);
        }

        if (g_key_file_has_group(keyFile, "SCREEN")) {
           if (g_key_file_has_key(keyFile, "SCREEN", "fullscreen", NULL))
              config.fullscreen = g_key_file_get_boolean(keyFile, "SCREEN", "fullscreen", NULL);
        }
        g_key_file_free(keyFile);
    }

    if (!config.timeZone)
        config.timeZone = g_time_zone_new_local();

    if (!config.frames_per_tick && 
        !(config.frames_per_tick = frames_per_tick(config.diameter_controller,
                                                   config.diameter_rim,
                                                   config.ctr,
                                                   config.fpr)))
    {
        g_warning("No valid tick settings, using default frames per tick: %f", DEFAULT_FRAMES_PER_TICK);
        config.frames_per_tick = DEFAULT_FRAMES_PER_TICK;
    }

    config.movie_size = get_file_size(config.movie_path);
    config.number_of_frames = config.movie_size / FRAME_SIZE;
    
    mainLoop = g_main_loop_new(NULL, FALSE);

    gc_context.g_main_loop        = mainLoop;
    gc_context.g_main_context     = g_main_loop_get_context(mainLoop);
    gc_context.window_size.width  = MOVIE_WIDTH;
    gc_context.window_size.height = MOVIE_HEIGHT;
    gc_context.exit               = FALSE;
    gc_context.movie_context      = &movie;
    gc_context.config             = &config;


    g_message("movie file: %s",                           config.movie_path);
    g_message("movie size: %lu",                          config.movie_size);
    g_message("movie frames: %lu",                        config.number_of_frames);
    g_message("movie mask file: %s",                      config.mask_path);
    g_message("frames per minute: %f",                    get_frames_per_minute(&gc_context));
    g_message("frames per day:    %lu",                   get_frames_per_day(&gc_context));
    g_message("frames per tick:   %f",                    config.frames_per_tick);
    g_message("number of days:    %d",                    get_number_of_days(&gc_context));
    g_message("current day:       %d",                    get_current_day(&gc_context));

    if (movie.ease_to) {
        movie.ease_to_frame = get_frame_offset(&gc_context, GO_TO_RAND_DAY, DAY_OFFSET_NOW);
        g_message("ease to frame:    %lu", movie.ease_to_frame);
    }

    x11_init(&gc_context);
    vdpau_init(&gc_context);

    load_movie(&gc_context);
    load_mask(&gc_context);

    g_cond_init(&movie.tick_cond);
    g_mutex_init(&movie.tick_lock);
    g_mutex_init(&movie.frame_lock);

    displayThread = g_thread_new("Display thread", display_thread, (gpointer)&gc_context);
    inputControllerThread = g_thread_new("Input controller thread", input_controller_thread, (gpointer)&gc_context);
    x11EventThread = g_thread_new("X11 Event thread", x11_event_thread, (gpointer)&gc_context);

    g_main_loop_run(mainLoop);

    gc_context.exit = TRUE;
    g_thread_join(displayThread); 
    g_thread_join(inputControllerThread); 
    g_thread_join(x11EventThread); 
    g_cond_clear(&movie.tick_cond);
    g_mutex_clear(&movie.tick_lock);
    g_mutex_clear(&movie.frame_lock);
    g_time_zone_unref(config.timeZone);
}