15
15
* You should have received a copy of the GNU General Public License
16
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
* $Id: bacon-video-widget-xine.c 5344 2008-04-08 13:17:29Z hadess $
19
* $Id: bacon-video-widget-xine.c 5617 2008-08-30 12:02:54Z hadess $
21
21
* the xine engine in a widget - implementation
48
49
#define XINE_ENABLE_EXPERIMENTAL_FEATURES
52
/* gnome keyring and vfs */
53
#include <libgnomevfs/gnome-vfs.h>
54
#include <gnome-keyring.h>
55
#endif /* !HAVE_GTK_ONLY */
58
53
#include "bacon-video-widget.h"
59
54
#include "bacon-video-widget-common.h"
468
466
} else if (g_ascii_strcasecmp (autoplug_list[i], "DVD") == 0) {
469
467
bvw->priv->can_dvd = TRUE;
470
468
} else if (g_ascii_strcasecmp (autoplug_list[i], "DVB") == 0) {
473
path = g_build_filename (g_get_home_dir (),
474
".xine", "channels.conf", NULL);
475
if (g_file_test (path, G_FILE_TEST_IS_REGULAR) != FALSE)
476
bvw->priv->can_dvb = TRUE;
469
bvw->priv->can_dvb = TRUE;
617
609
if (bvw->priv->auto_resize != FALSE
618
610
&& bvw->priv->logo_mode == FALSE
619
&& bvw->priv->fullscreen_mode == FALSE)
611
&& bvw->priv->fullscreen_mode == FALSE
612
&& bvw->priv->window_resized == FALSE)
621
614
signal_data *data;
616
bvw->priv->window_resized = TRUE;
623
618
data = g_new0 (signal_data, 1);
624
619
data->signal = RATIO_ASYNC;
625
620
g_async_queue_push (bvw->priv->queue, data);
835
830
entry.num_value = 0;
836
831
xine_config_update_entry (bvw->priv->xine, &entry);
833
/* Don't save the last viewed channel for DVB */
834
bvw_config_helper_num (bvw->priv->xine,
835
"media.dvb.remember_channel", 1, &entry);
837
xine_config_update_entry (bvw->priv->xine, &entry);
838
839
if (bvw->priv->gc == NULL) {
839
840
g_warning ("GConf not available, broken installation?");
1257
1258
setup_config_stream (bvw);
1258
1259
bvw->priv->ev_queue = xine_event_new_queue (bvw->priv->stream);
1261
/* Set the zoom that might have been recorded */
1262
if (bvw->priv->zoom != 0)
1263
bacon_video_widget_set_zoom (bvw, bvw->priv->zoom);
1260
1265
/* Setup xine events */
1261
1266
xine_event_create_listener_thread (bvw->priv->ev_queue,
1262
1267
xine_event, (void *) bvw);
1351
1356
case XINE_MSG_NO_ERROR:
1353
1358
case XINE_MSG_GENERAL_WARNING:
1359
g_message ("general warning: %s", data->messages);
1360
if (data->messages != NULL && strcmp (data->messages, "DVB Signal Lost. Please check connections.") == 0) {
1361
num = BVW_ERROR_INVALID_DEVICE;
1362
message = g_strdup (_("The TV adapter could not tune into the channel. Please check your hardware setup, and channel configuration."));
1355
1365
case XINE_MSG_UNKNOWN_HOST:
1356
1366
num = BVW_ERROR_UNKNOWN_HOST;
1357
1367
message = g_strdup (_("The server you are trying to connect to is not known."));
1572
1582
/* Steal messages from the async queue, if there's an error,
1573
1583
* to use as the error message rather than the crappy errors from
1574
1584
* xine_open() */
1575
while ((data = g_async_queue_try_pop (bvw->priv->queue)) != NULL)
1577
if (data->signal == ERROR_ASYNC || data->signal == MESSAGE_ASYNC)
1579
if (save_data != NULL)
1585
while ((data = g_async_queue_try_pop (bvw->priv->queue)) != NULL) {
1586
if (data->signal == ERROR_ASYNC || data->signal == MESSAGE_ASYNC) {
1587
if (save_data != NULL) {
1581
1588
g_free (save_data->msg);
1582
1589
g_free (save_data);
2249
2255
bacon_video_widget_get_subtitled (const char *mrl, const char *subtitle_uri)
2251
g_return_val_if_fail (g_str_has_prefix (subtitle_uri, "file://"), NULL);
2252
return g_strdup_printf ("%s#subtitle:%s", mrl, subtitle_uri + strlen ("file://"));
2258
char *local_path, *local_uri, *retval;
2260
file = g_file_new_for_uri (subtitle_uri);
2261
local_path = g_file_get_path (file);
2262
g_object_unref (file);
2264
if (local_path == NULL)
2267
local_uri = g_filename_to_uri (local_path, NULL, NULL);
2268
g_free (local_path);
2269
if (local_uri == NULL)
2272
retval = g_strdup_printf ("%s#subtitle:%s", mrl, local_uri + strlen ("file://"));
2353
#ifndef HAVE_GTK_ONLY
2354
/* Return a new MRL with a username and password embedded into it from the GNOME keychain.
2355
* This function should be called right before sending a URL to xine-lib. */
2357
add_auth_to_uri (const char* mrl)
2359
if (g_str_has_prefix (mrl, "http:") != FALSE) {
2361
const char *host, *scheme, *user;
2363
GnomeKeyringResult result;
2366
uri = gnome_vfs_uri_new (mrl);
2370
host = gnome_vfs_uri_get_host_name (uri);
2371
user = gnome_vfs_uri_get_user_name (uri);
2372
port = gnome_vfs_uri_get_host_port (uri);
2373
scheme = gnome_vfs_uri_get_scheme (uri);
2375
result = gnome_keyring_find_network_password_sync (user, NULL,
2380
if (result == GNOME_KEYRING_RESULT_OK && items != NULL) {
2382
GnomeKeyringNetworkPasswordData *pwd_data;
2384
pwd_data = items->data;
2386
gnome_vfs_uri_set_user_name (uri, pwd_data->user);
2387
gnome_vfs_uri_set_password (uri, pwd_data->password);
2389
parsed_uri = gnome_vfs_uri_to_string (uri, GNOME_VFS_URI_HIDE_NONE);
2391
gnome_keyring_network_password_list_free (items);
2392
gnome_vfs_uri_unref (uri);
2396
gnome_vfs_uri_unref (uri);
2402
#endif /* !HAVE_GTK_ONLY */
2405
2377
bacon_video_widget_open_with_subtitle (BaconVideoWidget *bvw, const char *mrl,
2406
2378
const char *subtitle_uri, GError **error)
2425
2397
/* Handle "icyx://" URLs from Orban/Coding Technologies AAC/aacPlus Player */
2426
2398
bvw->com->mrl = g_strdup_printf ("http:%s", mrl + 5);
2428
bvw->com->mrl = g_strdup (mrl);
2403
file = g_file_new_for_commandline_arg (mrl);
2404
path = g_file_get_path (file);
2406
bvw->com->mrl = g_filename_to_uri (path, NULL, NULL);
2409
bvw->com->mrl = g_strdup (mrl);
2411
g_object_unref (file);
2431
2414
if (g_str_has_prefix (mrl, "fd://") != FALSE) {
2448
2431
err = xine_open (bvw->priv->stream, bvw->com->mrl);
2451
#ifndef HAVE_GTK_ONLY
2452
/* If xine-lib reported a permission error, try to fetch credentials from the keychain and
2453
* try xine_open again. This only applies to HTTP for now */
2454
if (err == 0 && g_str_has_prefix (mrl, "http:") != FALSE) {
2455
xine_error (bvw, error);
2457
if (error != NULL && *error != NULL && g_error_matches (*error, BVW_ERROR, BVW_ERROR_FILE_PERMISSION)) {
2460
authed_mrl = add_auth_to_uri (bvw->com->mrl);
2461
if (authed_mrl != NULL) {
2462
g_clear_error (error);
2463
xine_close (bvw->priv->stream);
2464
err = xine_open (bvw->priv->stream, authed_mrl);
2465
g_free (authed_mrl);
2469
#endif /* !HAVE_GTK_ONLY */
2470
2434
xine_plugins_garbage_collector (bvw->priv->xine);
2472
2436
if (err == 0) {
3460
3431
XINE_STREAM_INFO_SEEKABLE);
3463
BaconVideoWidgetCanPlayStatus
3464
bacon_video_widget_can_play (BaconVideoWidget *bvw, TotemDiscMediaType type)
3468
case MEDIA_TYPE_DVD:
3469
if (bvw->priv->can_dvd != FALSE)
3470
return BVW_CAN_PLAY_SUCCESS;
3472
case MEDIA_TYPE_VCD:
3473
if (bvw->priv->can_vcd != FALSE)
3474
return BVW_CAN_PLAY_SUCCESS;
3476
case MEDIA_TYPE_DVB:
3477
if (bvw->priv->can_dvb != FALSE) {
3480
path = g_build_filename (g_get_home_dir (),
3484
if (g_file_test (path, G_FILE_TEST_IS_REGULAR) == FALSE) {
3486
return BVW_CAN_PLAY_MISSING_CHANNELS;
3489
return BVW_CAN_PLAY_SUCCESS;
3492
case MEDIA_TYPE_CDDA:
3494
return BVW_CAN_PLAY_UNSUPPORTED;
3497
return BVW_CAN_PLAY_MISSING_PLUGINS;
3501
bacon_video_widget_strdupnv (const char **mrls, int num_mrls)
3435
bacon_video_widget_strdupnv (const char **mrls, guint num_mrls)
3523
3458
g_return_val_if_fail (bvw != NULL, NULL);
3524
3459
g_return_val_if_fail (BACON_IS_VIDEO_WIDGET (bvw), NULL);
3525
3460
g_return_val_if_fail (bvw->priv->xine != NULL, NULL);
3526
//FIXME enable when we use devices for DVB
3527
//g_return_val_if_fail (device != NULL, NULL);
3529
entry_name = plugin_id = NULL;
3531
if (type == MEDIA_TYPE_DVD) {
3461
g_return_val_if_fail (device != NULL, NULL);
3464
case MEDIA_TYPE_DVD:
3465
if (bvw->priv->can_dvd == FALSE) {
3466
g_set_error (error, BVW_ERROR, BVW_ERROR_NO_PLUGIN_FOR_FILE,
3467
"XXX Do not use XXX");
3532
3470
plugin_id = "DVD";
3533
3471
entry_name = "media.dvd.device";
3534
} else if (type == MEDIA_TYPE_VCD) {
3473
case MEDIA_TYPE_VCD:
3474
if (bvw->priv->can_vcd == FALSE) {
3475
g_set_error (error, BVW_ERROR, BVW_ERROR_NO_PLUGIN_FOR_FILE,
3476
"XXX Do not use XXX");
3535
3479
plugin_id = "VCD";
3536
3480
entry_name = "media.vcd.device";
3537
} else if (type == MEDIA_TYPE_DVB) {
3482
case MEDIA_TYPE_DVB:
3483
if (bvw->priv->can_dvb == FALSE) {
3484
g_set_error (error, BVW_ERROR, BVW_ERROR_NO_PLUGIN_FOR_FILE,
3485
"XXX Do not use XXX");
3490
path = g_strdup_printf ("/dev/dvb/adapter%s/frontend0", device);
3491
if (g_file_test (path, G_FILE_TEST_EXISTS) == FALSE) {
3493
g_set_error (error, BVW_ERROR, BVW_ERROR_INVALID_DEVICE,
3494
"XXX Do not use XXX");
3499
path = g_build_filename (g_get_home_dir (),
3503
if (g_file_test (path, G_FILE_TEST_IS_REGULAR) == FALSE) {
3505
g_set_error (error, BVW_ERROR, BVW_ERROR_FILE_NOT_FOUND,
3506
"XXX Do not use XXX");
3538
3511
plugin_id = "DVB";
3512
entry_name = "media.dvb.adapter";
3514
case MEDIA_TYPE_CDDA:
3515
g_set_error (error, BVW_ERROR, BVW_ERROR_UNVALID_LOCATION,
3516
"XXX Do not use XXX");
3519
g_assert_not_reached ();
3541
if (entry_name != NULL) {
3522
if (type != MEDIA_TYPE_DVB) {
3542
3523
xine_cfg_entry_t entry;
3543
3524
bvw_config_helper_string (bvw->priv->xine,
3545
3526
device, &entry);
3546
3527
entry.str_value = (char *) device;
3547
3528
xine_config_update_entry (bvw->priv->xine, &entry);
3530
xine_cfg_entry_t entry;
3531
bvw_config_helper_string (bvw->priv->xine,
3534
entry.num_value = atoi (device);
3535
xine_config_update_entry (bvw->priv->xine, &entry);
3550
3538
mrls = xine_get_autoplay_mrls (bvw->priv->xine, plugin_id, &num_mrls);
3563
3551
} else if (type == MEDIA_TYPE_DVB) {
3564
3552
/* No channels.conf, and we couldn't find it */
3565
if (g_str_has_prefix (mrls[0], "Sorry") != FALSE)
3567
/* The first channel can be the last channel played,
3568
* or a copy of the first one, ignore it */
3569
return bacon_video_widget_strdupnv (mrls++, num_mrls - 1);
3553
if (g_str_has_prefix (mrls[0], "Sorry, No valid channels.conf found") != FALSE) {
3554
g_set_error (error, BVW_ERROR, BVW_ERROR_FILE_NOT_FOUND,
3555
"XXX Do not use XXX");
3557
} else if (g_str_has_prefix (mrls[0], "Sorry, No DVB input device found.") != FALSE) {
3558
g_set_error (error, BVW_ERROR, BVW_ERROR_DEVICE_BUSY,
3559
"XXX Do not use XXX");
3572
return bacon_video_widget_strdupnv (mrls, num_mrls);
3564
return bacon_video_widget_strdupnv ((const char **) mrls, num_mrls);
3737
3729
g_return_if_fail (bvw->priv->xine != NULL);
3738
3730
g_return_if_fail (zoom >= 0 && zoom <= 400);
3740
if (bvw->priv->stream == NULL)
3732
if (bvw->priv->stream == NULL) {
3733
/* No stream yet, remember the zoom level */
3734
bvw->priv->zoom = zoom;
3743
3738
xine_set_param (bvw->priv->stream,
3744
3739
XINE_PARAM_VO_ZOOM_X, zoom);