gmyth/gmyth/gmyth_util.c
author ali@juiblex.co.uk
Wed Dec 16 10:06:21 2009 +0000 (2009-12-16)
branchtrunk
changeset 951 7b0d87ef5e63
parent 950 6308269b026e
permissions -rw-r--r--
Add rules and upcoming lists to gmyth_ls
     1 /**
     2  * GMyth Library
     3  *
     4  * @file gmyth/gmyth_util.c
     5  * 
     6  * @brief <p> This component provides utility functions 
     7  * 	(dealing with dates, time, string formatting, etc.).
     8  * 
     9  * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
    10  * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
    11  * @author Rosfran Borges <rosfran.borges@indt.org.br>
    12  *
    13  * 
    14  * This program is free software; you can redistribute it and/or modify
    15  * it under the terms of the GNU Lesser General Public License as published by
    16  * the Free Software Foundation; either version 2 of the License, or
    17  * (at your option) any later version.
    18  *
    19  * This program is distributed in the hope that it will be useful,
    20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    22  * GNU General Public License for more details.
    23  *
    24  * You should have received a copy of the GNU Lesser General Public License
    25  * along with this program; if not, write to the Free Software
    26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    27  */
    28 
    29 #ifdef HAVE_CONFIG_H
    30 #include "config.h"
    31 #endif
    32 
    33 #define _XOPEN_SOURCE
    34 #define _XOPEN_SOURCE_EXTENDED
    35 #define __USE_MISC
    36 
    37 #include <glib.h>
    38 #include <glib/gprintf.h>
    39 #include <time.h>
    40 #include <sys/time.h>
    41 #include <sys/timex.h>
    42 
    43 #include "gmyth_socket.h"
    44 #include "gmyth_recorder.h"
    45 #include "gmyth_common.h"
    46 #include "gmyth_debug.h"
    47 
    48 #include "gmyth_util.h"
    49 
    50 #if !GLIB_CHECK_VERSION (2, 10, 0)
    51 gchar          *g_time_val_to_iso8601(GTimeVal * time_);
    52 gboolean        g_time_val_from_iso8601(const gchar * iso_date,
    53                                         GTimeVal * time_);
    54 void            g_date_set_time_val(GDate * date, GTimeVal * timeval);
    55 
    56 #endif
    57 
    58 /** Converts a time_t struct in a GString at ISO standard format 
    59  * (e.g. 2006-07-20T09:56:41).
    60  * 
    61  * The returned GString memory should be deallocated from 
    62  * the calling function.
    63  *
    64  * @param time_value the time value to be converted
    65  * @return GString* the converted isoformat string 
    66  */
    67 GString        *
    68 gmyth_util_time_to_isoformat(time_t time_value)
    69 {
    70     struct tm       tm_time;
    71     GString        *result;
    72 
    73     if (localtime_r(&time_value, &tm_time) == NULL) {
    74         gmyth_debug("gmyth_util_time_to_isoformat convertion error!\n");
    75         return NULL;
    76     }
    77 
    78     result = g_string_sized_new(20);
    79     g_string_printf(result, "%04d-%02d-%02dT%02d:%02d:%02d",
    80                     tm_time.tm_year + 1900, tm_time.tm_mon + 1,
    81                     tm_time.tm_mday, tm_time.tm_hour, tm_time.tm_min,
    82                     tm_time.tm_sec);
    83 
    84     gmyth_debug("Result (ISO 8601) = %s", result->str);
    85 
    86     return result;
    87 }
    88 
    89 /** Converts a time_t struct in a GString at ISO standard format 
    90  * (e.g. 2006-07-20T09:56:41).
    91  * 
    92  * The returned GString memory should be deallocated from 
    93  * the calling function.
    94  *
    95  * @param time_value the GTimeValue to be converted
    96  * @return GString* the converted isoformat string 
    97  */
    98 gchar*
    99 gmyth_util_time_to_isoformat_from_time_val_fmt(const gchar * fmt_string,
   100                                                const GTimeVal * time_val)
   101 {
   102     gchar          *result = NULL;
   103     struct tm      *tm_time = NULL;
   104     time_t          time;
   105 
   106     gint            buffer_len = 0;
   107 
   108     g_return_val_if_fail(fmt_string != NULL, NULL);
   109 
   110     g_return_val_if_fail(time_val != NULL, NULL);
   111 
   112     time = time_val->tv_sec;    // + (gint)( time_val->tv_usec /
   113     // G_USEC_PER_SEC );
   114 
   115     tm_time = g_malloc0(sizeof(struct tm));
   116 
   117     if (NULL == localtime_r(&time, tm_time)) {
   118         gmyth_debug("gmyth_util_time_to_isoformat convertion error!\n");
   119     } else {
   120         /*
   121          * we first check the return of strftime to allocate a buffer of
   122          * the correct size 
   123          */
   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                 gmyth_debug
   129                     ("gmyth_util_time_to_isoformat convertion error!\n");
   130                 return NULL;
   131             }
   132             strftime(result, buffer_len + 1, fmt_string, tm_time);
   133             gmyth_debug("Dateline (ISO result): %s", result);
   134         }
   135     }                           /* if */
   136 
   137     gmyth_debug("Result (strftime) = %s", result);
   138 
   139     // strptime( result, "%Y-%m-%dT%H:%M:%SZ", tm_time ); 
   140 
   141     // strftime( result, strlen(result), fmt_string, tm_time );
   142 
   143     g_free(tm_time);
   144 
   145     gmyth_debug("Result (ISO 8601) = %s", result);
   146 
   147     return result;
   148 }
   149 
   150 /** Converts a time_t struct in a GString at ISO standard format 
   151  * (e.g. 2006-07-20 09:56:41).
   152  * 
   153  * The returned GString memory should be deallocated from 
   154  * the calling function.
   155  *
   156  * @param time_value the GTimeValue to be converted
   157  * @return GString* the converted isoformat string 
   158  */
   159 gchar          *
   160 gmyth_util_time_to_isoformat_from_time_val(const GTimeVal * time)
   161 {
   162     gchar          *result =
   163         gmyth_util_time_to_isoformat_from_time_val_fmt("%Y-%m-%d %H:%M:%S",
   164                                                        time);
   165 
   166     // result[10] = ' ';
   167     // result[ strlen(result) - 1] = '\0';
   168 
   169     return result;
   170 }
   171 
   172 /** Converts a time_t struct in a GString at ISO standard format 2 
   173  * (e.g. 2006-07-20T09:56:41).
   174  * 
   175  * The returned GString memory should be deallocated from 
   176  * the calling function.
   177  *
   178  * @param time_value the GTimeValue to be converted
   179  * @return GString* the converted isoformat string 
   180  */
   181 gchar          *
   182 gmyth_util_time_to_mythformat_from_time_val(const GTimeVal * time)
   183 {
   184     gchar          *result =
   185         gmyth_util_time_to_isoformat_from_time_val_fmt("%Y-%m-%dT%H:%M:%S",
   186                                                        time);
   187 
   188     return result;
   189 }
   190 
   191 /** Converts a time_t struct in a GString at ISO standard format 
   192  * (e.g. 2006-07-20T09:56:41).
   193  * 
   194  * The returned GString memory should be deallocated from 
   195  * the calling function.
   196  *
   197  * @param time_value the GTimeValue to be converted
   198  * @return GString* the converted isoformat string 
   199  */
   200 gchar          *
   201 gmyth_util_time_to_string_only_date(const GTimeVal * time)
   202 {
   203     gchar          *result =
   204         gmyth_util_time_to_isoformat_from_time_val_fmt("%Y-%m-%d", time);
   205     // result[10] = ' ';
   206     // result[ strlen(result) - 1] = '\0';
   207     return result;
   208 }
   209 
   210 /** Converts a time_t struct in a GString at ISO standard format 
   211  * (e.g. 2006-07-20T09:56:41).
   212  * 
   213  * The returned GString memory should be deallocated from 
   214  * the calling function.
   215  *
   216  * @param time_value the GTimeValue to be converted
   217  * @return GString* the converted isoformat string 
   218  */
   219 gchar          *
   220 gmyth_util_time_to_string_only_time(const GTimeVal * time)
   221 {
   222     gchar          *result =
   223         gmyth_util_time_to_isoformat_from_time_val_fmt("%H:%M:%S", time);
   224     // result[10] = ' ';
   225     // result[ strlen(result) - 1] = '\0';
   226     return result;
   227 }
   228 
   229 /** Converts a time_t struct in a GString to the following 
   230  * format (e.g. 2006-07-20 09:56:41).
   231  * 
   232  * The returned GString memory should be deallocated from 
   233  * the calling function.
   234  *
   235  * @param time_value the time value to be converted
   236  * @return GString* the converted string 
   237  */
   238 GString        *
   239 gmyth_util_time_to_string(time_t time_value)
   240 {
   241     GString        *result = gmyth_util_time_to_isoformat(time_value);
   242 
   243     result->str[10] = ' ';
   244     result->str[strlen(result->str) - 1] = '\0';
   245 
   246     return result;
   247 }
   248 
   249 /** Converts a time_t struct in a GString to the following 
   250  * format (e.g. 2006-07-20 09:56:41).
   251  * 
   252  * The returned GString memory should be deallocated from 
   253  * the calling function.
   254  *
   255  * @param time_value the time value to be converted
   256  * @return GString* the converted string 
   257  */
   258 gchar*
   259 gmyth_util_time_to_string_from_time_val(const GTimeVal * time_val)
   260 {
   261     gchar *result =
   262         gmyth_util_time_to_isoformat_from_time_val_fmt("%Y-%m-%d %H:%M:%S",
   263                                                        time_val);
   264 
   265     // result[10] = ' ';
   266 
   267     return result;
   268 }
   269 
   270 /** Converts a GString in the following format 
   271  * (e.g. 2006-07-20 09:56:41) to a time_t struct.
   272  * 
   273  * @param time_str the string to be converted
   274  * @return time_t the time converted value
   275  */
   276 time_t
   277 gmyth_util_string_to_time(GString * time_str)
   278 {
   279     gint            year,
   280                     month,
   281                     day,
   282                     hour,
   283                     min,
   284                     sec;
   285 
   286     gmyth_debug("[%s] time_str = %s. [%s]", __FUNCTION__,
   287                 time_str !=
   288                 NULL ? time_str->str : "[time string is NULL!]",
   289                 time_str->str);
   290 
   291     if (sscanf(time_str->str, "%04d-%02d-%02d %02d:%02d:%02d",
   292                &year, &month, &day, &hour, &min, &sec) < 3) {
   293         gmyth_debug("GMythUtil: isoformat_to_time converter error!\n");
   294         return 0;
   295     }
   296 
   297     struct tm      *tm_time = g_malloc0(sizeof(struct tm));
   298 
   299     tm_time->tm_year = year - 1900;
   300     tm_time->tm_mon = month - 1;
   301     tm_time->tm_mday = day;
   302     tm_time->tm_hour = hour;
   303     tm_time->tm_min = min;
   304     tm_time->tm_sec = sec;
   305 
   306     return mktime(tm_time);
   307 }
   308 
   309 /** Converts a GString in the following format 
   310  * (e.g. 2006-07-20 09:56:41) to a time_t struct.
   311  * 
   312  * @param time_str the string to be converted
   313  * @return time_t the time converted value
   314  */
   315 struct tm      *
   316 gmyth_util_time_val_to_date(const GTimeVal * time)
   317 {
   318     struct tm      *date = g_malloc0(sizeof(struct tm));
   319     time_t          time_micros = time->tv_sec; // + (gint)( time->tv_usec 
   320                                                 // 
   321     // 
   322     // / G_USEC_PER_SEC );
   323 
   324     if (NULL == date) {
   325         gmyth_debug
   326             ("GMythUtil: GDate *gmyth_util_time_val_to_date (GTimeVal* time) - converter error!\n");
   327         return NULL;
   328     }
   329 
   330     if (NULL == localtime_r(&time_micros, date)) {
   331         gmyth_debug("gmyth_util_time_to_isoformat convertion error!\n");
   332         return NULL;
   333     }
   334 
   335     gmyth_debug("Converted from GTimeVal == %s to GDate", asctime(date));
   336 
   337     return date;
   338 }
   339 
   340 /** Converts a GString in the following format 
   341  * (e.g. 2006-07-20 09:56:41) to a time_t struct.
   342  * 
   343  * @param time_str the string to be converted
   344  * @return time_t the time converted value
   345  */
   346 GTimeVal       *
   347 gmyth_util_string_to_time_val_fmt(const gchar * fmt_string,
   348                                   const gchar * time_str)
   349 {
   350     GTimeVal       *time = g_new0(GTimeVal, 1);
   351     struct tm      *tm_time = NULL;
   352     time_t          time_micros;
   353     gchar          *result;
   354 
   355     gmyth_debug("[%s] time_str = %s. [%s]", time_str, time_str != NULL ?
   356                 time_str : "[time string is NULL!]", time_str);
   357 
   358     if (NULL == time_str) {
   359         gmyth_debug("GMythUtil: isoformat_to_time converter error!\n");
   360         return NULL;
   361     }
   362 
   363     tm_time = g_malloc0(sizeof(struct tm));
   364 
   365     /*
   366      * we first check the return of strftime to allocate a buffer of the
   367      * correct size 
   368      */
   369     result = strptime(time_str, "%Y-%m-%dT%H:%M:%S", tm_time);
   370     if (NULL == result) {
   371         /*
   372          * we first check the return of strftime to allocate a buffer of
   373          * the correct size 
   374          */
   375         result = strptime(time_str, "%Y-%m-%dT%H:%M:%SZ", tm_time);
   376         if (NULL == result) {
   377             /*
   378              * we first check the return of strftime to allocate a buffer
   379              * of the correct size 
   380              */
   381             result = strptime(time_str, "%Y-%m-%d %H:%M:%S", tm_time);
   382             if (NULL == result) {
   383                 result = strptime(time_str, "%Y-%m-%dT%H:%M", tm_time);
   384                 if (NULL == result) {
   385                     gmyth_debug("Dateline (ISO result): %s", result);
   386                     g_free(tm_time);
   387                     return NULL;
   388                     // goto done; 
   389                 }
   390             }
   391         }
   392     }
   393 
   394     time_micros = mktime(tm_time);
   395 
   396     time->tv_sec = time_micros; // + (gint)( time_val->tv_usec /
   397     // G_USEC_PER_SEC );
   398 
   399     gmyth_debug("After mktime call... = %s", asctime(tm_time));
   400 
   401     g_free(tm_time);
   402 
   403     return time;
   404 }
   405 
   406 /** Converts a GString in the following format 
   407  * (e.g. 2006-07-20 09:56:41) to a time_t struct.
   408  * 
   409  * @param time_str the string to be converted
   410  * @return time_t the time converted value
   411  */
   412 GTimeVal       *
   413 gmyth_util_string_to_time_val(const gchar * time_str)
   414 {
   415     GTimeVal       *time =
   416         gmyth_util_string_to_time_val_fmt("%Y-%m-%d %H:%M:%S", time_str);
   417 
   418     return time;
   419 }
   420 
   421 /** 
   422  * Checks if the given remote file exists.
   423  * 
   424  * @param backend_info The GMythBackendInfo instance.
   425  * @param filename The file name of the remote file.
   426  * 
   427  * @return <code>true</code>, if the remote file exists.
   428  */
   429 gboolean
   430 gmyth_util_file_exists(GMythBackendInfo * backend_info,
   431                        const gchar * filename)
   432 {
   433     GMythSocket    *socket;
   434     gboolean        res = FALSE;
   435 
   436     gmyth_debug("Check if file %s exists", filename);
   437 
   438     g_return_val_if_fail(backend_info != NULL, FALSE);
   439     g_return_val_if_fail(filename != NULL, FALSE);
   440 
   441     socket = gmyth_backend_info_get_connected_socket (backend_info);
   442     if (socket != NULL) {
   443         res = gmyth_util_file_exists_from_socket (socket, filename);
   444         g_object_unref(socket);
   445     }
   446     return res;
   447 }
   448 
   449 gboolean
   450 gmyth_util_file_exists_from_socket (GMythSocket *sock, 
   451                                     const gchar *filename)
   452 {
   453     gboolean res = FALSE;
   454     GString *path;
   455     GMythProgramInfo *program;
   456 
   457     program = gmyth_program_info_new();
   458     program->pathname = g_string_new(filename);
   459 
   460     path = gmyth_util_check_file_from_socket (sock, program);
   461 
   462     if (path) {
   463         res = TRUE;
   464         g_string_free(path, TRUE);
   465     }
   466 
   467     g_object_unref(program);
   468 
   469     return res;
   470 }
   471  
   472 GString *
   473 gmyth_util_check_file_from_socket (GMythSocket *sock,
   474                                    GMythProgramInfo *program)
   475 {
   476     GString *res;
   477     gint length;
   478     GMythStringList *slist;
   479 
   480     slist = gmyth_string_list_new();
   481     gmyth_string_list_append_char_array(slist, "QUERY_CHECKFILE");
   482     if (gmyth_socket_get_protocol_version(sock) >= 32)
   483 	gmyth_string_list_append_int(slist, 1);
   484     gmyth_program_info_to_string_list(program, slist);
   485 
   486     length = gmyth_socket_sendreceive_stringlist (sock, slist);
   487     if (length > 1 && gmyth_string_list_get_int(slist, 0) == 1)
   488         res = gmyth_string_list_get_string(slist, 1);
   489     else
   490         res = NULL;
   491 
   492     g_object_unref(slist);
   493 
   494     return res;
   495 }
   496  
   497 gboolean
   498 gmyth_util_get_backend_details (GMythSocket *sock, GMythBackendDetails **details)
   499 {
   500     gboolean res = FALSE;
   501     gint length = 0;
   502     GMythStringList *slist;
   503 
   504     slist = gmyth_string_list_new();
   505     gmyth_string_list_append_char_array(slist, "QUERY_FREE_SPACE");
   506 
   507     length = gmyth_socket_sendreceive_stringlist (sock, slist);
   508     if (length >= 8) {
   509         *details = g_new0 (GMythBackendDetails, 1);
   510         (*details)->total_space = gmyth_string_list_get_uint64 (slist, 4) * 1024;
   511         (*details)->used_space = gmyth_string_list_get_uint64 (slist, 6) * 1024;
   512         res = TRUE;
   513     }
   514 
   515     g_object_unref(slist);
   516 
   517     return res;
   518 }
   519 
   520 void
   521 gmyth_util_backend_details_free (GMythBackendDetails *details)
   522 {
   523     g_free (details);
   524 }
   525                      
   526 
   527 /** 
   528  * Checks if the given remote file exists, and gets its remote directory.
   529  * 
   530  * @param backend_info The GMythBackendInfo instance.
   531  * @param filename The file name of the remote file.
   532  * @param current_dir String pointer to the directory where the remote file is stored.
   533  * 
   534  * @return <code>true</code>, if the remote file exists.
   535  */
   536 gboolean
   537 gmyth_util_file_exists_and_get_remote_dir(GMythBackendInfo * backend_info,
   538                                           const gchar * filename,
   539                                           gchar ** current_dir)
   540 {
   541     GMythSocket    *socket;
   542     gboolean        res;
   543 
   544     *current_dir = NULL;
   545 
   546     socket = gmyth_socket_new();
   547     res = gmyth_socket_connect_to_backend(socket, backend_info->hostname,
   548                                           backend_info->port, TRUE);
   549 
   550     if (res == TRUE) {
   551         GMythProgramInfo *program;
   552 	GString *path;
   553 
   554         program = gmyth_program_info_new();
   555         program->pathname = g_string_new(filename);
   556 
   557         path = gmyth_util_check_file_from_socket (socket, program);
   558 
   559         res = !!path;
   560 
   561         if (path)
   562             *current_dir = g_string_free(path, FALSE);
   563 
   564         if (*current_dir != NULL)
   565             gmyth_debug("Current directory = %s.", (*current_dir != NULL)
   566                         ? *current_dir : "[directory not found]");
   567 
   568         g_object_unref(program);
   569 
   570         gmyth_socket_close_connection(socket);
   571     }
   572     g_object_unref(socket);
   573     return res;
   574 }
   575 
   576 /** 
   577  * Creates a file name to a possible existing remote file,
   578  * based on some fields of the LiveTV/recorded program info.
   579  * 
   580  * @param chan_id The channel ID number.
   581  * @param start_time The start time of the recording.
   582  * 
   583  * @return The string representing the file name.
   584  */
   585 gchar          *
   586 gmyth_util_create_filename(const gint chan_id, const GTimeVal * start_time)
   587 {
   588     gchar          *basename = NULL;
   589 
   590     g_return_val_if_fail(start_time != NULL, NULL);
   591 
   592     gchar          *isodate =
   593         gmyth_util_time_to_isoformat_from_time_val_fmt("%Y%m%d%H%M%S",
   594                                                        start_time);
   595 
   596     basename = g_strdup_printf("%d_%s", chan_id, isodate);
   597 
   598     gmyth_debug("Basename (from chan_id and start_time): %s", basename);
   599 
   600     if (isodate)
   601         g_free(isodate);
   602 
   603     return basename;
   604 }
   605 
   606 /** 
   607  * Gets the channel list.
   608  * 
   609  * @param backend_info The GMythBackendInfo instance.
   610  * 
   611  * @return a pointer to a GList with all the channels.
   612  */
   613 GList*
   614 gmyth_util_get_channel_list(GMythBackendInfo * backend_info)
   615 {
   616     GMythRecorder  *recorder;
   617     GList          *channel_list = NULL;
   618     gboolean        res = FALSE;
   619 
   620     gmyth_debug("Gets channel list.");
   621 
   622     g_return_val_if_fail(backend_info != NULL, FALSE);
   623 
   624     recorder =
   625         gmyth_recorder_new(1,
   626                            g_string_new(gmyth_backend_info_get_hostname
   627                                         (backend_info)),
   628                            gmyth_backend_info_get_port(backend_info));
   629     res = gmyth_recorder_setup(recorder);
   630 
   631     if (res == TRUE) {
   632         // GList* channel_list = gmyth_recorder_get_channel_list( recorder 
   633         // 
   634         // 
   635         // ); 
   636         gmyth_debug("Yeah, got channel list!!!");
   637         GList          *ch = NULL;
   638         GMythChannelInfo *channel_info = NULL;
   639 
   640         for (ch = gmyth_recorder_get_channel_list(recorder); ch != NULL;) {
   641             channel_info = g_malloc0(sizeof(GMythChannelInfo));
   642             channel_info->channel_ID = 0;
   643             channel_info->channel_num =
   644                 g_string_new(g_strdup((gchar *) ch->data));
   645             channel_info->channel_name = g_string_new("");
   646             gmyth_debug("Printing channel info... (%s)",
   647                         channel_info->channel_num->str);
   648             channel_list =
   649                 g_list_append(channel_list,
   650                               g_memdup(channel_info,
   651                                        sizeof(GMythChannelInfo)));
   652 
   653             ch = g_list_next(ch);
   654 
   655             if (channel_info != NULL)
   656                 g_free(channel_info);
   657         }
   658 
   659     } /* if */
   660     else {
   661         gmyth_debug("No, couldn't get the channel list!!!");
   662     }
   663 
   664     gmyth_debug("Got %d channels!!!", g_list_length(channel_list));
   665 
   666 
   667     g_object_unref(recorder);
   668 
   669     return channel_list;
   670 }
   671 
   672 /** 
   673  * Gets all the recordings from remote encoder.
   674  * 
   675  * @param backend_info The GMythBackendInfo instance.
   676  * 
   677  * @return The program info's listage.
   678  */
   679 GSList         *
   680 gmyth_util_get_all_recordings(GMythBackendInfo * backend_info)
   681 {
   682     GSList         *program_list = NULL;
   683     GMythSocket    *socket;
   684     gboolean        res;
   685 
   686     socket = gmyth_socket_new();
   687     res = gmyth_socket_connect_to_backend(socket, backend_info->hostname,
   688                                           backend_info->port, TRUE);
   689 
   690     if (res == TRUE) {
   691         GMythStringList *slist = gmyth_string_list_new();
   692         guint           pos = 0;
   693 
   694         gmyth_string_list_append_char_array(slist,
   695                                             "QUERY_RECORDINGS Play");
   696 
   697         gmyth_socket_sendreceive_stringlist(socket, slist);
   698 
   699         if (slist != NULL && (gmyth_string_list_length(slist) > 0)) {
   700             GMythProgramInfo *program = NULL;
   701 
   702             gmyth_debug("OK! Got the program list [size=%d].",
   703                         gmyth_string_list_length(slist));
   704 
   705             do {
   706                 program =
   707                     gmyth_program_info_from_string_list_from_pos(slist,
   708                                                                  pos);
   709 
   710                 if (program != NULL) {
   711                     pos += 41;
   712 
   713                     program_list = g_slist_append(program_list, program);
   714                 } else
   715                     break;
   716 
   717             }
   718             while (gmyth_string_list_length(slist) > pos);
   719 
   720         }
   721         /*
   722          * if 
   723          */
   724         g_object_unref(slist);
   725 
   726         gmyth_socket_close_connection(socket);
   727     }
   728     g_object_unref(socket);
   729 
   730     return program_list;
   731 }
   732 
   733 /** 
   734  * Checks if the given remote file exists, and gets its remote directory.
   735  * 
   736  * @param backend_info The GMythBackendInfo instance.
   737  * @param channel The channel name of the program info.
   738  * 
   739  * @return The requested program info.
   740  */
   741 GMythProgramInfo *
   742 gmyth_util_get_recording_from_channel(GMythBackendInfo * backend_info,
   743                                       const gchar * channel)
   744 {
   745     GSList         *program_list = NULL;
   746     GMythProgramInfo *program = NULL;
   747 
   748     program_list = gmyth_util_get_all_recordings(backend_info);
   749 
   750     if (program_list != NULL && g_slist_length(program_list) > 0) {
   751         GMythProgramInfo *program = NULL;
   752         guint           pos = 0;
   753 
   754         gmyth_debug("OK! Got the program list [size=%d].",
   755                     g_slist_length(program_list));
   756 
   757         while (pos < g_slist_length(program_list)) {
   758             program =
   759                 (GMythProgramInfo *) g_slist_nth_data(program_list, pos);
   760 
   761             if (program != NULL && program->channame != NULL &&
   762                 g_ascii_strncasecmp(program->channame->str, channel,
   763                                     strlen(channel)) == 0) {
   764                 break;
   765             }
   766 
   767             ++pos;
   768 
   769         }                       /* while */
   770 
   771     }
   772     /*
   773      * if 
   774      */
   775     return program;
   776 }
   777 
   778 GSList *
   779 gmyth_util_get_all_pending(GMythBackendInfo * backend_info,
   780                            gboolean * conflicts)
   781 {
   782     GSList         *program_list = NULL;
   783     GMythSocket    *socket;
   784     gboolean        res;
   785 
   786     socket = gmyth_socket_new();
   787     res = gmyth_socket_connect_to_backend(socket, backend_info->hostname,
   788                                           backend_info->port, TRUE);
   789 
   790     if (res) {
   791         GMythStringList *slist = gmyth_string_list_new();
   792         int              pos, lines, count;
   793 
   794         gmyth_string_list_append_char_array(slist, "QUERY_GETALLPENDING");
   795 
   796         gmyth_socket_sendreceive_stringlist(socket, slist);
   797 
   798         if (gmyth_string_list_length(slist) > 1) {
   799             GMythProgramInfo *program;
   800 
   801             *conflicts = gmyth_string_list_get_int(slist, 0);
   802             count = gmyth_string_list_get_int(slist, 1);
   803             lines = (gmyth_string_list_length(slist) - 2) / count;
   804 
   805             for(pos = 2; pos < 2 + count * lines; pos += lines) {
   806                 program =
   807                   gmyth_program_info_from_string_list_from_pos(slist, pos);
   808 
   809                 if (program)
   810                     program_list = g_slist_prepend(program_list, program);
   811             }
   812         }
   813         g_object_unref(slist);
   814 
   815         gmyth_socket_close_connection(socket);
   816     }
   817     g_object_unref(socket);
   818 
   819     return g_slist_reverse(program_list);
   820 }
   821 
   822 #if !GLIB_CHECK_VERSION (2, 10, 0)
   823 
   824 /*
   825  * Hacked from glib 2.10 <gtime.c> 
   826  */
   827 
   828 static          time_t
   829 mktime_utc(struct tm *tm)
   830 {
   831     time_t          retval;
   832 
   833 #ifndef HAVE_TIMEGM
   834     static const gint days_before[] = {
   835         0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
   836     };
   837 #endif
   838 
   839 #ifndef HAVE_TIMEGM
   840     if (tm->tm_mon < 0 || tm->tm_mon > 11)
   841         return (time_t) - 1;
   842 
   843     retval = (tm->tm_year - 70) * 365;
   844     retval += (tm->tm_year - 68) / 4;
   845     retval += days_before[tm->tm_mon] + tm->tm_mday - 1;
   846 
   847     if (tm->tm_year % 4 == 0 && tm->tm_mon < 2)
   848         retval -= 1;
   849 
   850     retval =
   851         ((((retval * 24) + tm->tm_hour) * 60) + tm->tm_min) * 60 +
   852         tm->tm_sec;
   853 #else
   854     retval = timegm(tm);
   855 #endif                          /* !HAVE_TIMEGM */
   856 
   857     return retval;
   858 }
   859 
   860 gboolean
   861 g_time_val_from_iso8601(const gchar * iso_date, GTimeVal * time_)
   862 {
   863     struct tm       tm;
   864     long            val;
   865 
   866     g_return_val_if_fail(iso_date != NULL, FALSE);
   867     g_return_val_if_fail(time_ != NULL, FALSE);
   868 
   869     val = strtoul(iso_date, (char **) &iso_date, 10);
   870     if (*iso_date == '-') {
   871         /*
   872          * YYYY-MM-DD 
   873          */
   874         tm.tm_year = val - 1900;
   875         iso_date++;
   876         tm.tm_mon = strtoul(iso_date, (char **) &iso_date, 10) - 1;
   877 
   878         if (*iso_date++ != '-')
   879             return FALSE;
   880 
   881         tm.tm_mday = strtoul(iso_date, (char **) &iso_date, 10);
   882     } else {
   883         /*
   884          * YYYYMMDD 
   885          */
   886         tm.tm_mday = val % 100;
   887         tm.tm_mon = (val % 10000) / 100 - 1;
   888         tm.tm_year = val / 10000 - 1900;
   889     }
   890 
   891     if (*iso_date++ != 'T')
   892         return FALSE;
   893 
   894     val = strtoul(iso_date, (char **) &iso_date, 10);
   895     if (*iso_date == ':') {
   896         /*
   897          * hh:mm:ss 
   898          */
   899         tm.tm_hour = val;
   900         iso_date++;
   901         tm.tm_min = strtoul(iso_date, (char **) &iso_date, 10);
   902 
   903         if (*iso_date++ != ':')
   904             return FALSE;
   905 
   906         tm.tm_sec = strtoul(iso_date, (char **) &iso_date, 10);
   907     } else {
   908         /*
   909          * hhmmss 
   910          */
   911         tm.tm_sec = val % 100;
   912         tm.tm_min = (val % 10000) / 100;
   913         tm.tm_hour = val / 10000;
   914     }
   915 
   916     time_->tv_sec = mktime_utc(&tm);
   917     time_->tv_usec = 1;
   918 
   919     if (*iso_date == '.')
   920         time_->tv_usec = strtoul(iso_date + 1, (char **) &iso_date, 10);
   921 
   922     if (*iso_date == '+' || *iso_date == '-') {
   923         gint            sign = (*iso_date == '+') ? -1 : 1;
   924 
   925         val = 60 * strtoul(iso_date + 1, (char **) &iso_date, 10);
   926 
   927         if (*iso_date == ':')
   928             val = 60 * val + strtoul(iso_date + 1, NULL, 10);
   929         else
   930             val = 60 * (val / 100) + (val % 100);
   931 
   932         time_->tv_sec += (time_t) (val * sign);
   933     }
   934 
   935     return TRUE;
   936 }
   937 
   938 
   939 gchar          *
   940 g_time_val_to_iso8601(GTimeVal * time_)
   941 {
   942     gchar          *retval;
   943 
   944     g_return_val_if_fail(time_->tv_usec >= 0
   945                          && time_->tv_usec < G_USEC_PER_SEC, NULL);
   946 
   947 #define ISO_8601_LEN    21
   948 #define ISO_8601_FORMAT "%Y-%m-%dT%H:%M:%SZ"
   949     retval = g_new0(gchar, ISO_8601_LEN + 1);
   950 
   951     strftime(retval, ISO_8601_LEN, ISO_8601_FORMAT,
   952              gmtime(&(time_->tv_sec)));
   953 
   954     return retval;
   955 }
   956 
   957 
   958 /*
   959  * Hacked from glib 2.10 <gdate.c> 
   960  */
   961 
   962 void
   963 g_date_set_time_t(GDate * date, time_t timet)
   964 {
   965     struct tm       tm;
   966 
   967     g_return_if_fail(date != NULL);
   968 
   969 #ifdef HAVE_LOCALTIME_R
   970     localtime_r(&timet, &tm);
   971 #else
   972     {
   973         struct tm      *ptm = localtime(&timet);
   974 
   975         if (ptm == NULL) {
   976             /*
   977              * Happens at least in Microsoft's C library if you pass a
   978              * negative time_t. Use 2000-01-01 as default date. 
   979              */
   980 #ifndef G_DISABLE_CHECKS
   981             g_return_if_fail_warning(G_LOG_DOMAIN, "g_date_set_time",
   982                                      "ptm != NULL");
   983 #endif
   984 
   985             tm.tm_mon = 0;
   986             tm.tm_mday = 1;
   987             tm.tm_year = 100;
   988         } else
   989             memcpy((void *) &tm, (void *) ptm, sizeof(struct tm));
   990     }
   991 #endif
   992 
   993     date->julian = FALSE;
   994 
   995     date->month = tm.tm_mon + 1;
   996     date->day = tm.tm_mday;
   997     date->year = tm.tm_year + 1900;
   998 
   999     g_return_if_fail(g_date_valid_dmy(date->day, date->month, date->year));
  1000 
  1001     date->dmy = TRUE;
  1002 }
  1003 
  1004 
  1005 void
  1006 g_date_set_time_val(GDate * date, GTimeVal * timeval)
  1007 {
  1008     g_date_set_time_t(date, (time_t) timeval->tv_sec);
  1009 }
  1010 
  1011 
  1012 
  1013 
  1014 #endif