diff -r 000000000000 -r 81b1f3006eb2 branches/gmyth-0.1b/src/gmyth_recorder.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/branches/gmyth-0.1b/src/gmyth_recorder.c Tue Feb 06 00:33:35 2007 +0000
@@ -0,0 +1,654 @@
+/**
+ * GMyth Library
+ *
+ * @file gmyth/gmyth_remote_encoder.c
+ *
+ * @brief
GMythRecorder class defines functions for playing live tv.
+ *
+ * The remote encoder is used by gmyth_tvplayer to setup livetv.
+ *
+ * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
+ * @author Hallyson Luiz de Morais Melo
+ *
+ *//*
+ *
+ * This program 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 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 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 "gmyth_recorder.h"
+
+#include
+
+#include "gmyth_stringlist.h"
+#include "gmyth_util.h"
+#include "gmyth_debug.h"
+
+#define GMYTHTV_RECORDER_HEADER "QUERY_RECORDER"
+
+static void gmyth_recorder_class_init (GMythRecorderClass *klass);
+static void gmyth_recorder_init (GMythRecorder *object);
+
+static void gmyth_recorder_dispose (GObject *object);
+static void gmyth_recorder_finalize (GObject *object);
+
+G_DEFINE_TYPE(GMythRecorder, gmyth_recorder, G_TYPE_OBJECT)
+
+static void
+gmyth_recorder_class_init (GMythRecorderClass *klass)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = (GObjectClass *) klass;
+
+ gobject_class->dispose = gmyth_recorder_dispose;
+ gobject_class->finalize = gmyth_recorder_finalize;
+}
+
+static void
+gmyth_recorder_init (GMythRecorder *gmyth_remote_encoder)
+{
+}
+
+static void
+gmyth_recorder_dispose (GObject *object)
+{
+ // GMythRecorder *gmyth_remote_encoder = GMYTH_RECORDER(object);
+
+ G_OBJECT_CLASS (gmyth_recorder_parent_class)->dispose (object);
+}
+
+
+static void
+gmyth_recorder_finalize (GObject *object)
+{
+ g_signal_handlers_destroy (object);
+
+ GMythRecorder *recorder = GMYTH_RECORDER(object);
+
+ gmyth_debug ("[%s] Closing control socket", __FUNCTION__);
+ gmyth_socket_close_connection(recorder->myth_socket);
+ g_object_unref (recorder->myth_socket);
+
+ G_OBJECT_CLASS (gmyth_recorder_parent_class)->finalize (object);
+}
+
+/** Creates a new instance of GMythRecorder.
+ *
+ * @return a new instance of GMythRecorder.
+ */
+GMythRecorder*
+gmyth_recorder_new (int num, GString *hostname, gshort port)
+{
+ GMythRecorder *encoder = GMYTH_RECORDER ( g_object_new (
+ GMYTH_RECORDER_TYPE, FALSE ));
+
+ encoder->recorder_num = num;
+ encoder->hostname = g_string_new (hostname->str);
+ encoder->port = port;
+
+ return encoder;
+}
+
+/** Configures the remote encoder instance connecting it to Mythtv backend.
+ *
+ * @param recorder the GMythRecorder instance.
+ * @return TRUE if successfull, FALSE if any error happens.
+ */
+gboolean
+gmyth_recorder_setup (GMythRecorder *recorder)
+{
+ assert (recorder);
+ gmyth_debug ("[%s] Creating socket and connecting to backend", __FUNCTION__);
+
+ if (recorder->myth_socket == NULL) {
+
+ recorder->myth_socket = gmyth_socket_new ();
+
+ if (!gmyth_socket_connect_to_backend ( recorder->myth_socket, recorder->hostname->str,
+ recorder->port, TRUE ) ) {
+ g_warning ("GMythRemoteEncoder: Connection to backend failed");
+ return FALSE;
+ }
+
+ } else {
+ g_warning("Remote encoder socket already created\n");
+ }
+
+ return TRUE;
+}
+
+/** Sends the SPAWN_LIVETV command through Mythtv protocol. This command
+ * requests the backend to start capturing TV content.
+ *
+ * @param recorder The GMythRecorder instance.
+ * @param tvchain_id The tvchain unique id.
+ * @return true if success, false if any error happens.
+ */
+gboolean
+gmyth_recorder_spawntv (GMythRecorder *recorder, GString *tvchain_id)
+{
+ GMythStringList *str_list;
+ GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
+
+ gmyth_debug ("[%s] Spawntv with tvchain_id = %s", __FUNCTION__, tvchain_id->str);
+
+ str_list = gmyth_string_list_new ();
+
+ g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
+
+ gmyth_string_list_append_string (str_list, tmp_str);
+ gmyth_string_list_append_string (str_list, g_string_new ("SPAWN_LIVETV"));
+ gmyth_string_list_append_string (str_list, tvchain_id);
+ gmyth_string_list_append_int (str_list, 0); // PIP = FALSE (0)
+
+ gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
+
+ g_string_free (tmp_str, TRUE);
+
+ tmp_str = gmyth_string_list_get_string (str_list, 0);
+ if (tmp_str == NULL) {
+ g_warning ("[%s] Spawntv request returned %s", __FUNCTION__, tmp_str->str);
+ return FALSE;
+ }
+
+ if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) {
+ g_warning ("[%s] Spawntv request returned %s", __FUNCTION__, tmp_str->str);
+ g_object_unref (str_list);
+ return FALSE;
+ }
+
+ g_object_unref (str_list);
+ return TRUE;
+
+}
+
+/**
+ * Sends the SPAWN_LIVETV command through Mythtv protocol. This command
+ * requests the backend to start capturing TV content, but it doesn't need
+ * the TV chain ID.
+ *
+ * @param recorder The GMythRecorder instance.
+ * @return true if success, false if any error happens.
+ */
+gboolean
+gmyth_recorder_spawntv_no_tvchain (GMythRecorder *recorder)
+{
+ GMythStringList *str_list;
+ GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
+
+ gmyth_debug ("[%s] Spawntv, no TV chain!", __FUNCTION__);
+
+ str_list = gmyth_string_list_new ();
+
+ g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
+
+ gmyth_string_list_append_string (str_list, tmp_str);
+ gmyth_string_list_append_string (str_list, g_string_new ("SPAWN_LIVETV"));
+
+ gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
+
+ g_string_free (tmp_str, TRUE);
+
+ tmp_str = gmyth_string_list_get_string (str_list, 0);
+ if (tmp_str == NULL) {
+ g_warning ("[%s] Spawntv request returned %s", __FUNCTION__, tmp_str->str);
+ return FALSE;
+ }
+
+ if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) {
+ g_warning ("[%s] Spawntv request returned %s", __FUNCTION__, tmp_str->str);
+ g_object_unref (str_list);
+ return FALSE;
+ }
+
+ g_object_unref (str_list);
+ return TRUE;
+
+}
+
+/** Sends the command STOP_LIVETV to Mythtv backend.
+ *
+ * @param recorder the GMythRecorder instance.
+ * @return true if success, false if any error happens.
+ */
+gboolean
+gmyth_recorder_stop_livetv (GMythRecorder *recorder)
+{
+ GMythStringList *str_list;
+ GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
+
+ gmyth_debug ("[%s]", __FUNCTION__);
+
+ str_list = gmyth_string_list_new ();
+
+ g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
+ gmyth_string_list_append_char_array( str_list, "STOP_LIVETV" );
+
+ gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
+
+ g_string_free (tmp_str, TRUE);
+
+ tmp_str = gmyth_string_list_get_string (str_list, 0);
+ if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) {
+ g_warning ("[%s] Stop livetv request returned %s", __FUNCTION__, tmp_str->str);
+ g_object_unref (str_list);
+ return FALSE;
+ }
+
+ g_object_unref (str_list);
+ return TRUE;
+
+}
+
+/** Sends the FRONTEND_READY command through Mythtv protocol. This command
+ * advertises the backend to start capturing TV content.
+ *
+ * @param recorder The GMythRecorder instance.
+ * @return TRUE if success, FALSE if any error happens.
+ */
+gboolean
+gmyth_recorder_send_frontend_ready_command (GMythRecorder *recorder)
+{
+ GMythStringList *str_list;
+ GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
+
+ gmyth_debug ( "[%s] FRONTEND_READY with recorder id = %d", __FUNCTION__, recorder->recorder_num );
+
+ str_list = gmyth_string_list_new ();
+
+ g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
+
+ gmyth_string_list_append_string (str_list, tmp_str);
+ gmyth_string_list_append_string (str_list, g_string_new ("FRONTEND_READY"));
+
+ gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
+
+ g_string_free (tmp_str, TRUE);
+
+ tmp_str = gmyth_string_list_get_string (str_list, 0);
+ if (tmp_str == NULL) {
+ g_warning ("[%s] FRONTEND_READY command request couldn't returns, reason: %s", __FUNCTION__, tmp_str->str);
+ return FALSE;
+ }
+
+ if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) {
+ g_warning ("[%s] FRONTEND_READY request returned %s", __FUNCTION__, tmp_str->str);
+ g_object_unref (str_list);
+ return FALSE;
+ }
+
+ g_object_unref (str_list);
+ return TRUE;
+
+}
+
+/** Send a CHECK_CHANNEL command request to the backend, in order to find if a
+ * certain channel actually exists.
+ *
+ * @param recorder The GMythRecorder instance.
+ * @param channel The new channel to be checked (string format).
+ * @return true if success, false if any error happens.
+ */
+gboolean
+gmyth_recorder_check_channel_name (GMythRecorder *recorder, gchar* channel)
+{
+ GMythStringList *str_list;
+ GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
+
+ gmyth_debug ("[%s] CHECK_CHANNEL with channel = %s", __FUNCTION__, channel);
+
+ str_list = gmyth_string_list_new ();
+
+ g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
+
+ gmyth_string_list_append_string (str_list, tmp_str);
+ gmyth_string_list_append_string (str_list, g_string_new ("CHECK_CHANNEL"));
+ gmyth_string_list_append_char_array (str_list, channel);
+
+ gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
+
+ g_string_free (tmp_str, TRUE);
+
+ tmp_str = gmyth_string_list_get_string (str_list, 0);
+ if (tmp_str == NULL) {
+ g_warning ("[%s] CHECK_CHANNEL request returned %s", __FUNCTION__, tmp_str->str);
+ return FALSE;
+ }
+
+ if (g_ascii_strncasecmp (tmp_str->str, "ok", 2) == 0 || g_ascii_strncasecmp (tmp_str->str, "0", 1) == 0 ) {
+ g_warning ("[%s] CHECK_CHANNEL request returned %s", __FUNCTION__, tmp_str->str);
+ g_object_unref (str_list);
+ return FALSE;
+ }
+
+ g_object_unref (str_list);
+ return TRUE;
+
+}
+
+/** Send a CHECK_CHANNEL command request to the backend, in order to find if a
+ * certain channel actually exists.
+ *
+ * @param recorder The GMythRecorder instance.
+ * @param channel The new channel to be checked (decimal integer value).
+ * @return true if success, false if any error happens.
+ */
+gboolean
+gmyth_recorder_check_channel (GMythRecorder *recorder, gint channel)
+{
+ return gmyth_recorder_check_channel_name( recorder, g_strdup_printf( "%d", channel ) );
+}
+
+/** Send a SET_CHANNEL command request to the backend, to start streaming on another
+ * TV content channel.
+ *
+ * @param recorder The GMythRecorder instance.
+ * @param channel The new channel to be loaded.
+ * @return true if success, false if any error happens.
+ */
+gboolean
+gmyth_recorder_set_channel (GMythRecorder *recorder, gint channel)
+{
+ GMythStringList *str_list;
+ GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
+
+ gmyth_debug ("[%s] SET_CHANNEL with channel = %d", __FUNCTION__, channel);
+
+ str_list = gmyth_string_list_new ();
+
+ g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
+
+ gmyth_string_list_append_string (str_list, tmp_str);
+ gmyth_string_list_append_string (str_list, g_string_new ("SET_CHANNEL"));
+ gmyth_string_list_append_int (str_list, channel);
+
+ gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
+
+ g_string_free (tmp_str, TRUE);
+
+ tmp_str = gmyth_string_list_get_string (str_list, 0);
+ if (tmp_str == NULL) {
+ g_warning ("[%s] SET_CHANNEL request returned %s", __FUNCTION__, tmp_str->str);
+ return FALSE;
+ }
+
+ if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) {
+ g_warning ("[%s] SET_CHANNEL request returned %s", __FUNCTION__, tmp_str->str);
+ g_object_unref (str_list);
+ return FALSE;
+ }
+
+ g_object_unref (str_list);
+ return TRUE;
+
+}
+
+/** Send a SET_CHANNEL command request to the backend, to start streaming on another
+ * TV content channel.
+ *
+ * @param recorder The GMythRecorder instance.
+ * @param channel The new channel to be loaded.
+ * @return true if success, false if any error happens.
+ */
+gboolean
+gmyth_recorder_set_channel_name (GMythRecorder *recorder, const gchar* channel)
+{
+ GMythStringList *str_list;
+ GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
+
+ gmyth_debug ("[%s] SET_CHANNEL with channel name = %s", __FUNCTION__, channel);
+
+ str_list = gmyth_string_list_new ();
+
+ g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
+
+ gmyth_string_list_append_string (str_list, tmp_str);
+ gmyth_string_list_append_string (str_list, g_string_new ("SET_CHANNEL"));
+ gmyth_string_list_append_char_array (str_list, channel);
+
+ gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
+
+ g_string_free (tmp_str, TRUE);
+
+ tmp_str = gmyth_string_list_get_string (str_list, 0);
+ if (tmp_str == NULL) {
+ g_warning ("[%s] SET_CHANNEL name request returned %s", __FUNCTION__, tmp_str->str );
+ return FALSE;
+ }
+
+ if (g_ascii_strncasecmp (tmp_str->str, "ok", 2) || g_ascii_strtoull( tmp_str->str, NULL, 10 ) == 0 ) {
+ g_warning ("[%s] SET_CHANNEL name request returned %s", __FUNCTION__, tmp_str->str);
+ g_object_unref (str_list);
+ return FALSE;
+ }
+
+ g_object_unref (str_list);
+ return TRUE;
+
+}
+
+/**
+ * Changes the channel of the actual Recorder.
+ *
+ * CHANNEL_DIRECTION_UP - Go up one channel in the listing
+ *
+ * CHANNEL_DIRECTION_DOWN - Go down one channel in the listing
+ *
+ * CHANNEL_DIRECTION_FAVORITE - Go to the next favorite channel
+ *
+ * CHANNEL_DIRECTION_SAME - Stay
+ *
+ * @param recorder The GMythRecorder instance.
+ * @param direction The new channel direction where to move to.
+ * @return true if success, false if any error happens.
+ */
+gboolean
+gmyth_recorder_change_channel (GMythRecorder *recorder, const GMythRecorderChannelChangeDirection direction)
+{
+ GMythStringList *str_list;
+ GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
+
+ gmyth_debug ("[%s] CHANGE_CHANNEL to the channel direction = %u", __FUNCTION__, direction);
+
+ str_list = gmyth_string_list_new ();
+
+ g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
+
+ gmyth_string_list_append_string (str_list, tmp_str);
+ gmyth_string_list_append_string (str_list, g_string_new ("CHANGE_CHANNEL"));
+ gmyth_string_list_append_int (str_list, direction);
+
+ gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
+
+ g_string_free (tmp_str, TRUE);
+
+ tmp_str = gmyth_string_list_get_string (str_list, 0);
+ if (tmp_str == NULL) {
+ g_warning ("[%s] CHANGE_CHANNEL name request returned %s", __FUNCTION__, tmp_str->str );
+ return FALSE;
+ }
+
+ if (g_ascii_strncasecmp (tmp_str->str, "ok", 2) || g_ascii_strtoull( tmp_str->str, NULL, 10 ) == 0 ) {
+ g_warning ("[%s] CHANGE_CHANNEL name request returned %s", __FUNCTION__, tmp_str->str);
+ g_object_unref (str_list);
+ return FALSE;
+ }
+
+ g_object_unref (str_list);
+ return TRUE;
+
+}
+
+/** Send a PAUSE command request to the backend, to pause streaming on another
+ * TV content channel.
+ *
+ * @param recorder The GMythRecorder instance.
+ * @return true if success, false if any error happens.
+ */
+gboolean
+gmyth_recorder_pause_recording ( GMythRecorder *recorder )
+{
+ GMythStringList *str_list;
+ GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
+
+ gmyth_debug ("[%s] PAUSE", __FUNCTION__);
+
+ str_list = gmyth_string_list_new ();
+
+ g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
+
+ gmyth_string_list_append_string (str_list, tmp_str);
+ gmyth_string_list_append_string (str_list, g_string_new ("PAUSE"));
+
+ gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
+
+ g_string_free (tmp_str, TRUE);
+
+ tmp_str = gmyth_string_list_get_string (str_list, 0);
+ if (tmp_str == NULL) {
+ g_warning ("[%s] PAUSE name request returned %s", __FUNCTION__, tmp_str->str);
+ return FALSE;
+ }
+
+ if (g_ascii_strncasecmp (tmp_str->str, "ok", 2)) {
+ g_warning ("[%s] PAUSE name request returned %s", __FUNCTION__, tmp_str->str);
+ g_object_unref (str_list);
+ return FALSE;
+ }
+
+ g_object_unref (str_list);
+ return TRUE;
+
+}
+
+/**
+ * Requests the actual program info from the MythTV backend server.
+ *
+ * @param recorder The GMythRecorder instance.
+ * @return The actual program info.
+ */
+GMythProgramInfo *
+gmyth_recorder_get_current_program_info ( GMythRecorder *recorder )
+{
+ GMythStringList *str_list;
+ GMythProgramInfo *program_info = gmyth_program_info_new();
+ GString *tmp_str = g_string_new( GMYTHTV_RECORDER_HEADER );
+
+ str_list = gmyth_string_list_new ();
+
+ g_string_append_printf ( tmp_str, " %d", recorder->recorder_num );
+
+ gmyth_string_list_append_string (str_list, tmp_str);
+
+ if ( recorder->myth_socket->mythtv_version >= 26 )
+ gmyth_string_list_append_string (str_list, g_string_new ("GET_CURRENT_RECORDING"));
+ else
+ gmyth_string_list_append_string (str_list, g_string_new ("GET_PROGRAM_INFO"));
+
+ gmyth_socket_sendreceive_stringlist (recorder->myth_socket, str_list);
+
+ g_string_free (tmp_str, TRUE);
+
+ if (str_list == NULL) {
+ g_warning ("[%s] GET_PROGRAM_INFO request returned. Error getting program info, string list equals to NULL!", __FUNCTION__);
+ return FALSE;
+ }
+
+ program_info = gmyth_program_info_from_string_list( str_list );
+
+ if ( NULL == program_info ) {
+ g_warning ("[%s] GET_PROGRAM_INFO request returned. Error getting program info, it is equals to NULL!!!", __FUNCTION__);
+ g_object_unref (program_info);
+ return NULL;
+ }
+
+ g_object_unref (str_list);
+ return program_info;
+
+}
+
+gint64
+gmyth_recorder_get_file_position ( GMythRecorder *recorder )
+{
+ gint64 pos = 0;
+ GString *query = g_string_new( GMYTHTV_RECORDER_HEADER );
+
+ GMythStringList *str_list = gmyth_string_list_new ();
+
+ g_string_append_printf( query, " %d", recorder->recorder_num );
+
+ gmyth_string_list_append_string (str_list, query);
+ gmyth_string_list_append_char_array( str_list, "GET_FILE_POSITION" );
+
+ gmyth_socket_sendreceive_stringlist ( recorder->myth_socket, str_list );
+
+ if ( str_list != NULL && gmyth_string_list_length(str_list) > 0 )
+ {
+ GString *str = NULL;
+ if ( ( str = gmyth_string_list_get_string( str_list, 0 ) ) != NULL && strstr ( str->str, "bad" ) == NULL )
+ pos = gmyth_util_decode_long_long( str_list, 0 );
+ }
+
+#ifndef GMYTHTV_ENABLE_DEBUG
+ g_print( "[%s] Got file position = %lld\n", __FUNCTION__, pos );
+#endif
+ if (str_list!=NULL)
+ g_object_unref (str_list);
+
+ return pos;
+
+}
+
+gboolean
+gmyth_recorder_is_recording ( GMythRecorder *recorder )
+{
+ gboolean ret = TRUE;
+
+ g_return_val_if_fail( recorder != NULL, FALSE );
+
+ GMythStringList *str_list = gmyth_string_list_new ();
+ GString *message = g_string_new ("");
+
+ g_string_printf( message, "%s %d", GMYTHTV_RECORDER_HEADER, recorder->recorder_num);
+ gmyth_string_list_append_string (str_list, message);
+ gmyth_string_list_append_string (str_list, g_string_new ("IS_RECORDING"));
+
+ gmyth_socket_sendreceive_stringlist ( recorder->myth_socket, str_list );
+
+ if ( str_list != NULL && gmyth_string_list_length(str_list) > 0 )
+ {
+ GString *str = NULL;
+ if ( ( str = gmyth_string_list_get_string( str_list, 0 ) ) != NULL && strcmp( str->str, "bad" )!= 0 )
+ {
+ gint is_rec = gmyth_string_list_get_int( str_list, 0 );
+ if ( is_rec != 0 )
+ ret = TRUE;
+ else
+ ret = FALSE;
+ }
+ }
+ gmyth_debug( "%s, stream is %s being recorded!\n", ret ? "YES" : "NO", ret ? "" : "NOT" );
+ //g_static_mutex_unlock (&mutex);
+
+ if ( str_list != NULL )
+ g_object_unref (str_list);
+
+ return ret;
+
+}