[svn r389] Some improvements on recorded file detection.
4 * @file gmyth/gmyth_util.c
6 * @brief <p> This component provides utility functions.
8 * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
9 * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU Lesser General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU Lesser General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 #define _XOPEN_SOURCE_EXTENDED
37 #include <glib/gprintf.h>
40 #include <sys/timex.h>
44 #if !GLIB_CHECK_VERSION (2, 10, 0)
46 g_time_val_to_iso8601 (GTimeVal *time_);
48 g_time_val_from_iso8601 (const gchar *iso_date,
51 g_date_set_time_val (GDate *date,
56 static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
58 /** Converts a time_t struct in a GString at ISO standard format
59 * (e.g. 2006-07-20T09:56:41).
61 * The returned GString memory should be deallocated from
62 * the calling function.
64 * @param time_value the time value to be converted
65 * @return GString* the converted isoformat string
68 gmyth_util_time_to_isoformat (time_t time_value)
73 g_static_mutex_lock ( &mutex );
75 if (localtime_r(&time_value, &tm_time) == NULL) {
76 g_static_mutex_unlock ( &mutex );
77 g_warning ("gmyth_util_time_to_isoformat convertion error!\n");
81 result = g_string_sized_new(20);
82 g_string_printf(result, "%04d-%02d-%02dT%02d:%02d:%02d",
83 tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday,
84 tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec);
86 gmyth_debug( "Result (ISO 8601) = %s", result->str );
88 g_static_mutex_unlock ( &mutex );
93 /** Converts a time_t struct in a GString at ISO standard format
94 * (e.g. 2006-07-20T09:56:41).
96 * The returned GString memory should be deallocated from
97 * the calling function.
99 * @param time_value the GTimeValue to be converted
100 * @return GString* the converted isoformat string
103 gmyth_util_time_to_isoformat_from_time_val_fmt ( const gchar *fmt_string, const GTimeVal* time_val )
105 gchar *result = NULL;
106 struct tm *tm_time = NULL;
110 g_return_val_if_fail( fmt_string != NULL, NULL );
112 g_return_val_if_fail( time_val != NULL, NULL );
114 time_t time = time_val->tv_sec;// + (gint)( time_val->tv_usec / G_USEC_PER_SEC );
116 tm_time = g_malloc0( sizeof(struct tm) );
118 g_static_mutex_lock ( &mutex );
120 if ( NULL == localtime_r( &time, tm_time ) ) {
121 g_warning ("gmyth_util_time_to_isoformat convertion error!\n");
123 // we first check the return of strftime to allocate a buffer of the correct size
124 buffer_len = strftime( NULL, SSIZE_MAX, fmt_string, tm_time );
125 if ( buffer_len > 0 ) {
126 result = g_malloc0( buffer_len + 1 );
127 if( result == NULL ){
128 g_static_mutex_unlock ( &mutex );
129 g_warning ("gmyth_util_time_to_isoformat convertion error!\n");
132 strftime( result, buffer_len + 1, fmt_string, tm_time );
133 gmyth_debug( "Dateline (ISO result): %s", result );
138 gmyth_debug( "Result (strftime) = %s", result );
140 //strptime( result, "%Y-%m-%dT%H:%M:%SZ", tm_time );
142 //strftime( result, strlen(result), fmt_string, tm_time );
144 g_static_mutex_unlock ( &mutex );
146 gmyth_debug( "Result (ISO 8601) = %s", result );
152 /** Converts a time_t struct in a GString at ISO standard format
153 * (e.g. 2006-07-20 09:56:41).
155 * The returned GString memory should be deallocated from
156 * the calling function.
158 * @param time_value the GTimeValue to be converted
159 * @return GString* the converted isoformat string
162 gmyth_util_time_to_isoformat_from_time_val ( const GTimeVal* time )
164 gchar *result = gmyth_util_time_to_isoformat_from_time_val_fmt( "%Y-%m-%d %H:%M:%S", time );
166 //result[ strlen(result) - 1] = '\0';
171 /** Converts a time_t struct in a GString at ISO standard format 2
172 * (e.g. 2006-07-20T09:56:41).
174 * The returned GString memory should be deallocated from
175 * the calling function.
177 * @param time_value the GTimeValue to be converted
178 * @return GString* the converted isoformat string
181 gmyth_util_time_to_mythformat_from_time_val ( const GTimeVal* time )
183 gchar *result = gmyth_util_time_to_isoformat_from_time_val_fmt( "%Y-%m-%dT%H:%M:%S", time );
187 /** Converts a time_t struct in a GString at ISO standard format
188 * (e.g. 2006-07-20T09:56:41).
190 * The returned GString memory should be deallocated from
191 * the calling function.
193 * @param time_value the GTimeValue to be converted
194 * @return GString* the converted isoformat string
197 gmyth_util_time_to_string_only_date ( const GTimeVal* time )
199 gchar *result = gmyth_util_time_to_isoformat_from_time_val_fmt( "%Y-%m-%d", time );
201 //result[ strlen(result) - 1] = '\0';
205 /** Converts a time_t struct in a GString at ISO standard format
206 * (e.g. 2006-07-20T09:56:41).
208 * The returned GString memory should be deallocated from
209 * the calling function.
211 * @param time_value the GTimeValue to be converted
212 * @return GString* the converted isoformat string
215 gmyth_util_time_to_string_only_time ( const GTimeVal* time )
217 gchar *result = gmyth_util_time_to_isoformat_from_time_val_fmt( "%H:%M:%S", time );
219 //result[ strlen(result) - 1] = '\0';
223 /** Converts a time_t struct in a GString to the following
224 * format (e.g. 2006-07-20 09:56:41).
226 * The returned GString memory should be deallocated from
227 * the calling function.
229 * @param time_value the time value to be converted
230 * @return GString* the converted string
233 gmyth_util_time_to_string (time_t time_value)
235 GString *result = gmyth_util_time_to_isoformat (time_value);
236 result->str[10] = ' ';
237 result->str[ strlen(result->str) - 1] = '\0';
242 /** Converts a time_t struct in a GString to the following
243 * format (e.g. 2006-07-20 09:56:41).
245 * The returned GString memory should be deallocated from
246 * the calling function.
248 * @param time_value the time value to be converted
249 * @return GString* the converted string
252 gmyth_util_time_to_string_from_time_val ( const GTimeVal *time_val )
254 gchar *result = gmyth_util_time_to_isoformat_from_time_val_fmt ( "%Y-%m-%d %H:%M:%S", time_val );
260 /** Converts a GString in the following format
261 * (e.g. 2006-07-20 09:56:41) to a time_t struct.
263 * @param time_str the string to be converted
264 * @return time_t the time converted value
267 gmyth_util_string_to_time (GString* time_str)
269 gint year, month, day, hour, min, sec;
271 gmyth_debug( "[%s] time_str = %s. [%s]", __FUNCTION__, time_str != NULL ?
272 time_str->str : "[time string is NULL!]", time_str->str );
274 if ( sscanf (time_str->str, "%04d-%02d-%02d %02d:%02d:%02d",
275 &year, &month, &day, &hour, &min, &sec) < 3 ) {
276 g_warning ("GMythUtil: isoformat_to_time converter error!\n");
280 g_static_mutex_lock ( &mutex );
282 struct tm* tm_time = g_malloc0( sizeof(struct tm) );
283 tm_time->tm_year = year - 1900;
284 tm_time->tm_mon = month - 1;
285 tm_time->tm_mday = day;
286 tm_time->tm_hour = hour;
287 tm_time->tm_min = min;
288 tm_time->tm_sec = sec;
290 g_static_mutex_unlock ( &mutex );
292 return mktime( tm_time );
295 /** Converts a GString in the following format
296 * (e.g. 2006-07-20 09:56:41) to a time_t struct.
298 * @param time_str the string to be converted
299 * @return time_t the time converted value
302 gmyth_util_time_val_to_date ( const GTimeVal* time )
304 struct tm *date = g_malloc0( sizeof( struct tm ) );
305 time_t time_micros = time->tv_sec;// + (gint)( time->tv_usec / G_USEC_PER_SEC );
307 if ( NULL == date ) {
308 g_warning ( "GMythUtil: GDate *gmyth_util_time_val_to_date (GTimeVal* time) - converter error!\n" );
312 if ( NULL == localtime_r( &time_micros, date ) ) {
313 g_warning ( "gmyth_util_time_to_isoformat convertion error!\n" );
317 gmyth_debug( "Converted from GTimeVal == %s to GDate", asctime( date ) );
322 /** Converts a GString in the following format
323 * (e.g. 2006-07-20 09:56:41) to a time_t struct.
325 * @param time_str the string to be converted
326 * @return time_t the time converted value
329 gmyth_util_string_to_time_val_fmt ( const gchar *fmt_string, const gchar* time_str )
331 GTimeVal *time = g_new0( GTimeVal, 1 );
332 struct tm* tm_time = NULL;
336 gmyth_debug( "[%s] time_str = %s. [%s]", time_str, time_str != NULL ?
337 time_str : "[time string is NULL!]", time_str );
339 if ( NULL == time_str )
341 g_warning ("GMythUtil: isoformat_to_time converter error!\n");
345 g_static_mutex_lock ( &mutex );
347 tm_time = g_malloc0( sizeof(struct tm) );
349 /* we first check the return of strftime to allocate a buffer of the correct size */
350 result = strptime( time_str, "%Y-%m-%dT%H:%M:%S", tm_time );
351 if ( NULL == result ) {
352 /* we first check the return of strftime to allocate a buffer of the correct size */
353 result = strptime( time_str, "%Y-%m-%dT%H:%M:%SZ", tm_time );
354 if ( NULL == result ) {
355 /* we first check the return of strftime to allocate a buffer of the correct size */
356 result = strptime( time_str, "%Y-%m-%d %H:%M:%S", tm_time );
357 if ( NULL == result) {
358 result = strptime( time_str, "%Y-%m-%dT%H:%M", tm_time );
359 if ( NULL == result ) {
360 g_static_mutex_unlock ( &mutex );
361 gmyth_debug( "Dateline (ISO result): %s", result );
370 time_micros = mktime( tm_time );
372 time->tv_sec = time_micros; // + (gint)( time_val->tv_usec / G_USEC_PER_SEC );
374 gmyth_debug( "After mktime call... = %s", asctime(tm_time) );
376 g_static_mutex_unlock ( &mutex );
381 /** Converts a GString in the following format
382 * (e.g. 2006-07-20 09:56:41) to a time_t struct.
384 * @param time_str the string to be converted
385 * @return time_t the time converted value
388 gmyth_util_string_to_time_val ( const gchar* time_str )
390 GTimeVal *time = gmyth_util_string_to_time_val_fmt ( "%Y-%m-%d %H:%M:%S", time_str );
395 /** Decodes a long long variable from the string list
396 * format of the myhtprotocol.
398 * @param strlist the string list of mythprotocol values
399 * @param offset the list node offset of the long long variable
400 * @return gint64 the long long converted value
403 gmyth_util_decode_long_long(GMythStringList *strlist, guint offset)
406 gint64 ret_value = 0LL;
408 g_return_val_if_fail( strlist != NULL, ret_value );
410 if ( offset > gmyth_string_list_length( strlist ))
411 g_printerr( "[%s] Offset is greater than the Stringlist (offset = %d)!\n",
412 __FUNCTION__, offset );
414 g_return_val_if_fail( offset < gmyth_string_list_length( strlist ), ret_value );
416 gint l1 = gmyth_string_list_get_int( strlist, offset );
417 gint l2 = gmyth_string_list_get_int( strlist, offset + 1 );
419 ret_value = (l2 /*& 0xffffffffLL*/) | ( (gint64)l1 << 32 );
426 gmyth_util_file_exists (GMythBackendInfo *backend_info, const gchar* filename)
431 socket = gmyth_socket_new ();
432 res = gmyth_socket_connect_to_backend (socket, backend_info->hostname,
433 backend_info->port, TRUE);
436 GMythStringList *slist;
437 GMythProgramInfo *program = NULL;
439 program = gmyth_program_info_new();
440 program->pathname = g_string_new (filename);
442 slist = gmyth_string_list_new ();
443 gmyth_string_list_append_char_array (slist, "QUERY_CHECKFILE");
445 gmyth_program_info_to_string_list (program, slist);
447 gmyth_socket_sendreceive_stringlist (socket, slist);
449 res = (gmyth_string_list_get_int (slist, 0) == 1);
451 g_object_unref (program);
453 g_object_unref (slist);
455 gmyth_socket_close_connection (socket);
457 g_object_unref (socket);
462 gmyth_util_file_exists_and_get_remote_dir (GMythBackendInfo *backend_info,
463 const gchar* filename, gchar** current_dir)
470 socket = gmyth_socket_new ();
471 res = gmyth_socket_connect_to_backend (socket, backend_info->hostname,
472 backend_info->port, TRUE);
475 GMythStringList *slist;
476 GMythProgramInfo *program = NULL;
478 program = gmyth_program_info_new();
479 program->pathname = g_string_new (filename);
481 slist = gmyth_string_list_new ();
482 gmyth_string_list_append_char_array (slist, "QUERY_CHECKFILE");
484 gmyth_program_info_to_string_list (program, slist);
486 gmyth_socket_sendreceive_stringlist (socket, slist);
488 res = (gmyth_string_list_get_int (slist, 0) == 1);
490 if ( ( gmyth_string_list_length( slist ) > 1 ) &&
491 gmyth_string_list_get_char_array (slist, 1) != NULL )
492 *current_dir = g_strdup( gmyth_string_list_get_char_array (slist, 1) );
494 g_object_unref (program);
496 g_object_unref (slist);
498 gmyth_socket_close_connection (socket);
500 g_object_unref (socket);
505 gmyth_util_create_filename( const gint chan_id, const GTimeVal* start_time )
507 gchar* basename = NULL;
509 g_return_val_if_fail( start_time != NULL, NULL );
511 gchar *isodate = gmyth_util_time_to_isoformat_from_time_val_fmt ( "%Y%m%d%H%M%S",
514 basename = g_strdup_printf( "%d_%s", chan_id, isodate );
516 gmyth_debug ("Basename (from chan_id and start_time): %s", basename);
524 #if !GLIB_CHECK_VERSION (2, 10, 0)
526 /* Hacked from glib 2.10 <gtime.c> */
529 mktime_utc (struct tm *tm)
534 static const gint days_before[] =
536 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
541 if (tm->tm_mon < 0 || tm->tm_mon > 11)
544 retval = (tm->tm_year - 70) * 365;
545 retval += (tm->tm_year - 68) / 4;
546 retval += days_before[tm->tm_mon] + tm->tm_mday - 1;
548 if (tm->tm_year % 4 == 0 && tm->tm_mon < 2)
551 retval = ((((retval * 24) + tm->tm_hour) * 60) + tm->tm_min) * 60 + tm->tm_sec;
553 retval = timegm (tm);
554 #endif /* !HAVE_TIMEGM */
560 g_time_val_from_iso8601 (const gchar *iso_date,
566 g_return_val_if_fail (iso_date != NULL, FALSE);
567 g_return_val_if_fail (time_ != NULL, FALSE);
569 val = strtoul (iso_date, (char **)&iso_date, 10);
570 if (*iso_date == '-')
573 tm.tm_year = val - 1900;
575 tm.tm_mon = strtoul (iso_date, (char **)&iso_date, 10) - 1;
577 if (*iso_date++ != '-')
580 tm.tm_mday = strtoul (iso_date, (char **)&iso_date, 10);
585 tm.tm_mday = val % 100;
586 tm.tm_mon = (val % 10000) / 100 - 1;
587 tm.tm_year = val / 10000 - 1900;
590 if (*iso_date++ != 'T')
593 val = strtoul (iso_date, (char **)&iso_date, 10);
594 if (*iso_date == ':')
599 tm.tm_min = strtoul (iso_date, (char **)&iso_date, 10);
601 if (*iso_date++ != ':')
604 tm.tm_sec = strtoul (iso_date, (char **)&iso_date, 10);
609 tm.tm_sec = val % 100;
610 tm.tm_min = (val % 10000) / 100;
611 tm.tm_hour = val / 10000;
614 time_->tv_sec = mktime_utc (&tm);
617 if (*iso_date == '.')
618 time_->tv_usec = strtoul (iso_date + 1, (char **)&iso_date, 10);
620 if (*iso_date == '+' || *iso_date == '-')
622 gint sign = (*iso_date == '+') ? -1 : 1;
624 val = 60 * strtoul (iso_date + 1, (char **)&iso_date, 10);
626 if (*iso_date == ':')
627 val = 60 * val + strtoul (iso_date + 1, NULL, 10);
629 val = 60 * (val / 100) + (val % 100);
631 time_->tv_sec += (time_t) (val * sign);
639 g_time_val_to_iso8601 (GTimeVal *time_)
643 g_return_val_if_fail (time_->tv_usec >= 0 && time_->tv_usec < G_USEC_PER_SEC, NULL);
645 #define ISO_8601_LEN 21
646 #define ISO_8601_FORMAT "%Y-%m-%dT%H:%M:%SZ"
647 retval = g_new0 (gchar, ISO_8601_LEN + 1);
649 strftime (retval, ISO_8601_LEN,
651 gmtime (&(time_->tv_sec)));
657 /* Hacked from glib 2.10 <gdate.c> */
660 g_date_set_time_t (GDate *date,
665 g_return_if_fail (date != NULL);
667 #ifdef HAVE_LOCALTIME_R
668 localtime_r (&timet, &tm);
671 struct tm *ptm = localtime (&timet);
675 /* Happens at least in Microsoft's C library if you pass a
676 * negative time_t. Use 2000-01-01 as default date.
678 #ifndef G_DISABLE_CHECKS
679 g_return_if_fail_warning (G_LOG_DOMAIN, "g_date_set_time", "ptm != NULL");
687 memcpy ((void *) &tm, (void *) ptm, sizeof(struct tm));
691 date->julian = FALSE;
693 date->month = tm.tm_mon + 1;
694 date->day = tm.tm_mday;
695 date->year = tm.tm_year + 1900;
697 g_return_if_fail (g_date_valid_dmy (date->day, date->month, date->year));
704 g_date_set_time_val (GDate *date,
707 g_date_set_time_t (date, (time_t) timeval->tv_sec);