#ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include "gmyth_backendinfo.h" #include "gmyth_file_transfer.h" #include "gmyth_livetv.h" #include "gmyth_util.h" #include "gmyth_common.h" typedef struct { GMythBackendInfo *b_info; char *filename; char *channel; } cat_options_t; static cat_options_t * _cat_options_new() { cat_options_t *options = g_new0(cat_options_t, 1); options->b_info = gmyth_backend_info_new(); return options; } static void _cat_options_free(cat_options_t * options) { g_return_if_fail(options != NULL); if (options->b_info) g_object_unref(options->b_info); g_free(options->filename); g_free(options->channel); } static gboolean _parse_args(int argc, char *argv[], cat_options_t * options) { GError *error = NULL; GOptionContext *context; gchar *host_ip = NULL; gint host_port = 0; gchar *filename = NULL; gchar *channel = NULL; GOptionEntry entries[] = { {"hostname", 'h', 0, G_OPTION_ARG_STRING, &host_ip, "Mythtv backend hostname or " "IP address", "IP_ADDRESS"}, {"port", 'p', 0, G_OPTION_ARG_INT, &host_port, "Mythtv backend port", "PORT"}, {"filename", 'f', 0, G_OPTION_ARG_STRING, &filename, "Recorded file name available " "in the Mythtv backend", "FILE"}, {"channel", 'c', 0, G_OPTION_ARG_STRING, &channel, "Mythtv channel number", "CHANNEL"}, {NULL} }; g_return_val_if_fail(options != NULL, FALSE); context = g_option_context_new("- loads a mythtv backend recorded file and prints " "it on the standard output\n"); g_option_context_add_main_entries(context, entries, NULL); g_option_context_parse(context, &argc, &argv, &error); g_option_context_set_help_enabled(context, TRUE); g_option_context_free(context); if ((!host_ip) || (host_port == 0)) { g_free(host_ip); g_free(filename); g_free(channel); return FALSE; } gmyth_backend_info_set_hostname(options->b_info, host_ip); gmyth_backend_info_set_port(options->b_info, host_port); if (filename) options->filename = g_strdup(filename); if (channel) options->channel = g_strdup(channel); g_free(host_ip); g_free(filename); g_free(channel); return TRUE; } static gboolean _cat_recorded_file(cat_options_t * options) { GArray *array = NULL; GMythFileTransfer *transfer; guint64 size = 0, total = 0; g_return_val_if_fail(options != NULL, FALSE); g_return_val_if_fail(options->b_info != NULL, FALSE); g_return_val_if_fail(options->filename != NULL, FALSE); if (!gmyth_util_file_exists(options->b_info, options->filename)) { g_printerr("File %s was not found in the mythtv server\n", options->filename); return FALSE; } transfer = gmyth_file_transfer_new(options->b_info); if (!gmyth_file_transfer_open(transfer, options->filename)) { g_printerr("File %s could not be opened\n", options->filename); return FALSE; } size = gmyth_file_transfer_get_filesize(transfer); fprintf(stderr, "Size:%d\n", size); array = g_array_new(FALSE, TRUE, sizeof(gchar)); while (total != size) { GMythFileReadResult res; res = gmyth_file_transfer_read(transfer, (GByteArray *) array, (size - total) > 64000 ? 64000 : (size - total), FALSE); if ((res != GMYTH_FILE_READ_OK) && (res != GMYTH_FILE_READ_EOF)) { g_array_free(array, TRUE); g_printerr("Error while reading the file: aborting!!\n"); break; } fwrite(array->data, array->len, 1, stdout); fflush(stdout); total += array->len; fprintf(stderr, "%d\n", total); g_array_remove_range(array, 0, array->len); //usleep(300000); } gmyth_file_transfer_close(transfer); g_array_free(array, TRUE); g_object_unref(transfer); return TRUE; } static gboolean _cat_channel(cat_options_t * options) { GMythLiveTV *livetv = NULL; GMythFile *gmyth_file = NULL; GArray *array = NULL; gint file_transf_ret; g_return_val_if_fail(options != NULL, FALSE); g_return_val_if_fail(options->b_info != NULL, FALSE); g_return_val_if_fail(options->channel != NULL, FALSE); livetv = gmyth_livetv_new(options->b_info); if (gmyth_livetv_channel_name_setup(livetv, options->channel) == FALSE) { g_printerr("Could not setup remote livetv"); g_object_unref(livetv); return FALSE; } gmyth_file = GMYTH_FILE(gmyth_livetv_create_file_transfer(livetv)); if (gmyth_file == NULL) { g_printerr("Could not open livetv recording file for transfer"); g_object_unref(livetv); return FALSE; } if (!gmyth_file_transfer_open(GMYTH_FILE_TRANSFER(gmyth_file), livetv->uri != NULL ? gmyth_uri_get_path(livetv->uri) : livetv->proginfo->pathname->str)) { g_printerr("Couldn't open MythTV. FileTransfer is NULL!\n"); return FALSE; } array = g_array_new(FALSE, TRUE, sizeof(gchar)); while (((file_transf_ret = gmyth_file_transfer_read (GMYTH_FILE_TRANSFER(gmyth_file), (GByteArray *) array, 64000, TRUE)) == GMYTH_FILE_READ_OK) || file_transf_ret == GMYTH_FILE_READ_NEXT_PROG_CHAIN) { fwrite(array->data, array->len, 1, stdout); fflush(stdout); g_array_remove_range(array, 0, array->len); g_main_context_iteration(g_main_context_default(), FALSE); } g_array_free(array, TRUE); g_object_unref(gmyth_file); g_object_unref(livetv); return TRUE; } int main(int argc, char *argv[]) { gboolean res = FALSE; cat_options_t *options; g_type_init(); if (!g_thread_supported()) g_thread_init(NULL); options = _cat_options_new(); res = _parse_args(argc, argv, options); if (!res) { g_printerr("Argument invalid. Type --help\n"); return 1; } if (options->filename) res = _cat_recorded_file(options); else if (options->channel) res = _cat_channel(options); else g_printerr("Argument invalid. You must specify --filename or --channel.\n" "Type --help for more information.\n"); _cat_options_free(options); return 0; }