| 2404 g_object_unref(sg); |
2397 g_object_unref(sg); |
| 2405 |
2398 |
| 2406 return ret; |
2399 return ret; |
| 2407 } |
2400 } |
| 2408 |
2401 |
| 2409 #ifdef USE_VV |
|
| 2410 static GList* |
|
| 2411 get_devices(const gchar *plugin) |
|
| 2412 { |
|
| 2413 GObjectClass *klass; |
|
| 2414 GstPropertyProbe *probe; |
|
| 2415 const GParamSpec *pspec; |
|
| 2416 GstElement *element = gst_element_factory_make(plugin, NULL); |
|
| 2417 GstElementFactory *factory; |
|
| 2418 const gchar *longname = NULL; |
|
| 2419 GList *ret = NULL; |
|
| 2420 |
|
| 2421 if (element == NULL) |
|
| 2422 return NULL; |
|
| 2423 |
|
| 2424 factory = gst_element_get_factory(element); |
|
| 2425 |
|
| 2426 longname = gst_element_factory_get_longname(factory); |
|
| 2427 klass = G_OBJECT_GET_CLASS(element); |
|
| 2428 |
|
| 2429 if (!g_object_class_find_property(klass, "device") || |
|
| 2430 !GST_IS_PROPERTY_PROBE(element) || |
|
| 2431 !(probe = GST_PROPERTY_PROBE(element)) || |
|
| 2432 !(pspec = gst_property_probe_get_property(probe, |
|
| 2433 "device"))) { |
|
| 2434 purple_debug_info("media", |
|
| 2435 "Found source '%s' (%s) - no device\n", |
|
| 2436 longname, GST_PLUGIN_FEATURE (factory)->name); |
|
| 2437 } else { |
|
| 2438 gint n; |
|
| 2439 gchar *name; |
|
| 2440 GValueArray *array; |
|
| 2441 |
|
| 2442 purple_debug_info("media", "Found devices\n"); |
|
| 2443 |
|
| 2444 /* Set autoprobe[-fps] to FALSE to avoid delays when probing. */ |
|
| 2445 if (g_object_class_find_property (klass, "autoprobe")) { |
|
| 2446 g_object_set(G_OBJECT (element), |
|
| 2447 "autoprobe", FALSE, NULL); |
|
| 2448 if (g_object_class_find_property(klass, |
|
| 2449 "autoprobe-fps")) { |
|
| 2450 g_object_set(G_OBJECT(element), |
|
| 2451 "autoprobe-fps", FALSE, NULL); |
|
| 2452 } |
|
| 2453 } |
|
| 2454 |
|
| 2455 array = gst_property_probe_probe_and_get_values(probe, pspec); |
|
| 2456 if (array != NULL) { |
|
| 2457 for (n = 0 ; n < array->n_values ; n++) { |
|
| 2458 GValue *device = g_value_array_get_nth( |
|
| 2459 array, n); |
|
| 2460 |
|
| 2461 ret = g_list_append(ret, |
|
| 2462 g_value_dup_string(device)); |
|
| 2463 |
|
| 2464 g_object_set(G_OBJECT(element), "device", |
|
| 2465 g_value_get_string(device), |
|
| 2466 NULL); |
|
| 2467 g_object_get(G_OBJECT(element), |
|
| 2468 "device-name", &name, NULL); |
|
| 2469 purple_debug_info("media", "Found source '%s'" |
|
| 2470 " (%s) - device '%s' (%s)\n", |
|
| 2471 longname, GST_PLUGIN_FEATURE( |
|
| 2472 factory)->name, name, |
|
| 2473 g_value_get_string(device)); |
|
| 2474 g_free(name); |
|
| 2475 } |
|
| 2476 g_value_array_free(array); |
|
| 2477 } |
|
| 2478 |
|
| 2479 /* Restore autoprobe[-fps] to TRUE. */ |
|
| 2480 if (g_object_class_find_property(klass, "autoprobe")) { |
|
| 2481 g_object_set(G_OBJECT(element), |
|
| 2482 "autoprobe", TRUE, NULL); |
|
| 2483 if (g_object_class_find_property(klass, |
|
| 2484 "autoprobe-fps")) { |
|
| 2485 g_object_set(G_OBJECT(element), |
|
| 2486 "autoprobe-fps", TRUE, NULL); |
|
| 2487 } |
|
| 2488 } |
|
| 2489 } |
|
| 2490 |
|
| 2491 gst_object_unref(element); |
|
| 2492 return ret; |
|
| 2493 } |
|
| 2494 |
|
| 2495 /* get a GList of pairs name / device */ |
|
| 2496 static GList * |
|
| 2497 get_device_items(const gchar *plugin) |
|
| 2498 { |
|
| 2499 GList *ret = NULL; |
|
| 2500 GList *devices = get_devices(plugin); |
|
| 2501 GstElement *element = gst_element_factory_make(plugin, NULL); |
|
| 2502 |
|
| 2503 if (element == NULL) |
|
| 2504 return NULL; |
|
| 2505 |
|
| 2506 for(; devices ; devices = g_list_delete_link(devices, devices)) { |
|
| 2507 gchar *name; |
|
| 2508 g_object_set(G_OBJECT(element), "device", devices->data, NULL); |
|
| 2509 g_object_get(G_OBJECT(element), "device-name", &name, NULL); |
|
| 2510 ret = g_list_append(ret, name); |
|
| 2511 ret = g_list_append(ret, devices->data); |
|
| 2512 } |
|
| 2513 |
|
| 2514 gst_object_unref(element); |
|
| 2515 return ret; |
|
| 2516 } |
|
| 2517 |
|
| 2518 /* |
|
| 2519 * Test functions to run video preview |
|
| 2520 */ |
|
| 2521 static gboolean |
|
| 2522 preview_video_bus_call(GstBus *bus, GstMessage *msg, gpointer pipeline) |
|
| 2523 { |
|
| 2524 switch(GST_MESSAGE_TYPE(msg)) { |
|
| 2525 case GST_MESSAGE_EOS: |
|
| 2526 purple_debug_info("preview-video", "End of Stream\n"); |
|
| 2527 break; |
|
| 2528 case GST_MESSAGE_ERROR: { |
|
| 2529 gchar *debug = NULL; |
|
| 2530 GError *err = NULL; |
|
| 2531 |
|
| 2532 gst_message_parse_error(msg, &err, &debug); |
|
| 2533 |
|
| 2534 purple_debug_error("preview-video", "Error: %s\n", err->message); |
|
| 2535 g_error_free(err); |
|
| 2536 |
|
| 2537 if (debug) { |
|
| 2538 purple_debug_error("preview-video", "details: %s\n", debug); |
|
| 2539 g_free (debug); |
|
| 2540 } |
|
| 2541 break; |
|
| 2542 } |
|
| 2543 default: |
|
| 2544 return TRUE; |
|
| 2545 } |
|
| 2546 |
|
| 2547 gst_element_set_state(pipeline, GST_STATE_NULL); |
|
| 2548 gst_object_unref(GST_PIPELINE(pipeline)); |
|
| 2549 return FALSE; |
|
| 2550 } |
|
| 2551 |
|
| 2552 static void |
|
| 2553 preview_button_clicked(GtkWidget *widget, gpointer *data) |
|
| 2554 { |
|
| 2555 const char *plugin = purple_prefs_get_string("/purple/media/video/plugin"); |
|
| 2556 const char *device = purple_prefs_get_string("/purple/media/video/device"); |
|
| 2557 GstBus *bus; |
|
| 2558 |
|
| 2559 /* create a preview window... */ |
|
| 2560 GstElement *pipeline = NULL; |
|
| 2561 GError *p_err = NULL; |
|
| 2562 |
|
| 2563 gchar *test_pipeline_str = NULL; |
|
| 2564 |
|
| 2565 if (strlen(device) > 0) |
|
| 2566 test_pipeline_str = g_strdup_printf("%s device=\"%s\" !" \ |
|
| 2567 " ffmpegcolorspace !" \ |
|
| 2568 " autovideosink", |
|
| 2569 plugin, device); |
|
| 2570 else |
|
| 2571 test_pipeline_str = g_strdup_printf("%s ! ffmpegcolorspace !" \ |
|
| 2572 " autovideosink", plugin); |
|
| 2573 |
|
| 2574 pipeline = gst_parse_launch (test_pipeline_str, &p_err); |
|
| 2575 |
|
| 2576 g_free(test_pipeline_str); |
|
| 2577 |
|
| 2578 if (pipeline == NULL) { |
|
| 2579 purple_debug_error("gtkprefs", |
|
| 2580 "Error starting preview: %s\n", p_err->message); |
|
| 2581 g_error_free(p_err); |
|
| 2582 return; |
|
| 2583 } |
|
| 2584 |
|
| 2585 bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline)); |
|
| 2586 gst_bus_add_watch(bus, preview_video_bus_call, pipeline); |
|
| 2587 gst_object_unref(bus); |
|
| 2588 |
|
| 2589 gst_element_set_state(pipeline, GST_STATE_PLAYING); |
|
| 2590 } |
|
| 2591 |
|
| 2592 static void |
|
| 2593 media_plugin_changed_cb(const gchar *name, PurplePrefType type, |
|
| 2594 gconstpointer value, gpointer data) |
|
| 2595 { |
|
| 2596 GtkWidget *hbox = data; |
|
| 2597 GtkWidget *dd = NULL; |
|
| 2598 GtkWidget *preview_button = NULL; |
|
| 2599 const char *plugin = value; |
|
| 2600 const char *device = purple_prefs_get_string("/purple/media/video/device"); |
|
| 2601 GList *video_items = get_device_items(plugin); |
|
| 2602 GList *list; |
|
| 2603 |
|
| 2604 if (video_items == NULL) { |
|
| 2605 video_items = g_list_prepend(video_items, g_strdup("")); |
|
| 2606 video_items = g_list_prepend(video_items, g_strdup("Default")); |
|
| 2607 } |
|
| 2608 |
|
| 2609 if (g_list_find(video_items, device) == NULL) |
|
| 2610 { |
|
| 2611 purple_prefs_set_string("/purple/media/video/device", |
|
| 2612 g_list_next(video_items)->data); |
|
| 2613 } |
|
| 2614 |
|
| 2615 list = gtk_container_get_children(GTK_CONTAINER(hbox)); |
|
| 2616 |
|
| 2617 while (list) { |
|
| 2618 gtk_widget_destroy(list->data); |
|
| 2619 list = g_list_delete_link(list, list); |
|
| 2620 } |
|
| 2621 |
|
| 2622 dd = pidgin_prefs_dropdown_from_list(hbox, _("_Device:"), PURPLE_PREF_STRING, |
|
| 2623 "/purple/media/video/device", |
|
| 2624 video_items); |
|
| 2625 |
|
| 2626 gtk_misc_set_alignment(GTK_MISC(dd), 0, 0.5); |
|
| 2627 |
|
| 2628 preview_button = gtk_button_new_with_mnemonic(_("_Preview")); |
|
| 2629 g_signal_connect(G_OBJECT(preview_button), "clicked", |
|
| 2630 G_CALLBACK(preview_button_clicked), NULL); |
|
| 2631 |
|
| 2632 gtk_container_add(GTK_CONTAINER(hbox), preview_button); |
|
| 2633 |
|
| 2634 gtk_widget_show_all(hbox); |
|
| 2635 } |
|
| 2636 |
|
| 2637 static GtkWidget * |
|
| 2638 media_page() |
|
| 2639 { |
|
| 2640 GtkWidget *ret; |
|
| 2641 GtkWidget *vbox; |
|
| 2642 GtkWidget *hbox; |
|
| 2643 GtkWidget *dd; |
|
| 2644 GtkWidget *preview_button; |
|
| 2645 GtkWidget *sw; |
|
| 2646 GtkSizeGroup *sg, *sg2; |
|
| 2647 const char *plugin = purple_prefs_get_string("/purple/media/video/plugin"); |
|
| 2648 const char *device = purple_prefs_get_string("/purple/media/video/device"); |
|
| 2649 GList *video_items = get_device_items(plugin); |
|
| 2650 GList *audio_items = get_device_items("alsasrc"); |
|
| 2651 |
|
| 2652 if (video_items == NULL) { |
|
| 2653 video_items = g_list_prepend(video_items, ""); |
|
| 2654 video_items = g_list_prepend(video_items, "Default"); |
|
| 2655 } |
|
| 2656 |
|
| 2657 if (g_list_find(video_items, device) == NULL) |
|
| 2658 { |
|
| 2659 purple_prefs_set_string("/purple/media/video/device", |
|
| 2660 g_list_next(video_items)->data); |
|
| 2661 } |
|
| 2662 |
|
| 2663 ret = gtk_vbox_new(FALSE, PIDGIN_HIG_CAT_SPACE); |
|
| 2664 gtk_container_set_border_width (GTK_CONTAINER (ret), PIDGIN_HIG_BORDER); |
|
| 2665 |
|
| 2666 sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); |
|
| 2667 sg2 = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); |
|
| 2668 |
|
| 2669 vbox = pidgin_make_frame (ret, _("Video Input")); |
|
| 2670 gtk_size_group_add_widget(sg2, vbox); |
|
| 2671 |
|
| 2672 hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); |
|
| 2673 dd = pidgin_prefs_dropdown(vbox, _("_Plugin:"), PURPLE_PREF_STRING, |
|
| 2674 "/purple/media/video/plugin", |
|
| 2675 _("Default"), "gconfvideosrc", |
|
| 2676 _("Video4Linux"), "v4lsrc", |
|
| 2677 _("Video4Linux2"), "v4l2src", |
|
| 2678 _("Video Test Source"), "videotestsrc", |
|
| 2679 NULL); |
|
| 2680 |
|
| 2681 gtk_size_group_add_widget(sg, dd); |
|
| 2682 gtk_misc_set_alignment(GTK_MISC(dd), 0, 0.5); |
|
| 2683 |
|
| 2684 hbox = gtk_hbox_new(FALSE, PIDGIN_HIG_BOX_SPACE); |
|
| 2685 dd = pidgin_prefs_dropdown_from_list(hbox, _("Device:"), PURPLE_PREF_STRING, |
|
| 2686 "/purple/media/video/device", |
|
| 2687 video_items); |
|
| 2688 |
|
| 2689 purple_prefs_connect_callback(prefs, "/purple/media/video/plugin", |
|
| 2690 media_plugin_changed_cb, hbox); |
|
| 2691 |
|
| 2692 g_signal_connect_swapped(hbox, "destroy", |
|
| 2693 G_CALLBACK(purple_prefs_disconnect_by_handle), hbox); |
|
| 2694 |
|
| 2695 gtk_size_group_add_widget(sg, dd); |
|
| 2696 gtk_misc_set_alignment(GTK_MISC(dd), 0, 0.5); |
|
| 2697 |
|
| 2698 preview_button = gtk_button_new_with_mnemonic(_("_Preview")); |
|
| 2699 g_signal_connect(G_OBJECT(preview_button), "clicked", |
|
| 2700 G_CALLBACK(preview_button_clicked), NULL); |
|
| 2701 |
|
| 2702 gtk_container_add(GTK_CONTAINER(hbox), preview_button); |
|
| 2703 gtk_container_add(GTK_CONTAINER(vbox), hbox); |
|
| 2704 |
|
| 2705 vbox = pidgin_make_frame (ret, _("Audio Input")); |
|
| 2706 gtk_size_group_add_widget(sg2, vbox); |
|
| 2707 dd = pidgin_prefs_dropdown_from_list(vbox, _("Device:"), PURPLE_PREF_STRING, |
|
| 2708 "/purple/media/audio/device", |
|
| 2709 audio_items); |
|
| 2710 |
|
| 2711 gtk_size_group_add_widget(sg, dd); |
|
| 2712 gtk_misc_set_alignment(GTK_MISC(dd), 0, 0.5); |
|
| 2713 |
|
| 2714 gtk_widget_show_all(ret); |
|
| 2715 |
|
| 2716 return ret; |
|
| 2717 } |
|
| 2718 |
|
| 2719 #endif /* USE_VV */ |
|
| 2720 |
2402 |
| 2721 static void |
2403 static void |
| 2722 set_idle_away(PurpleSavedStatus *status) |
2404 set_idle_away(PurpleSavedStatus *status) |
| 2723 { |
2405 { |
| 2724 purple_prefs_set_int("/purple/savedstatus/idleaway", purple_savedstatus_get_creation_time(status)); |
2406 purple_prefs_set_int("/purple/savedstatus/idleaway", purple_savedstatus_get_creation_time(status)); |