Commit b7079b4b authored by Patricia Santana Cruz's avatar Patricia Santana Cruz Committed by David King

Add videos and picture sharing support, bug 522210

Integrated nautilus-sendto with Cheese in order to add support for sharing
videos and images with different technologies.
parent 47a62de6
......@@ -65,7 +65,8 @@ VALAFLAGS = \
--pkg libcanberra \
--pkg eogthumbnav \
--pkg cheese-thumbview \
--pkg cheese-common
--pkg cheese-common \
--pkg gdk-x11-3.0
lib_LTLIBRARIES = libcheese.la libcheese-gtk.la
......@@ -190,6 +191,7 @@ cheese_SOURCES = \
src/cheese-preferences.vala \
src/cheese-window.vala \
src/cheese-main.vala \
src/cheese-shareable-media.vala \
src/thumbview/cheese-thumb-view.c \
src/thumbview/cheese-thumbnail.c \
src/thumbview/eog-thumb-nav.c
......
......@@ -10,3 +10,7 @@ How to get your camera working:
To get your camera working with cheese, you will have to ensure that it works
with the Gstreamer Framework and Video4Linux2 (V4L2) or Video4Linux (V4L). To
test this, you can use the 'gstreamer-properties' tool.
Sharing images and videos:
In order to be able to share images and videos from Cheese, you will need to
install the 'nautilus-sendto' package first.
......@@ -5,7 +5,6 @@ TODO
* Drop MX table layout
* Add a 1px white border around previews
* Improve video recording, see bug #564957
* Add nautilus-sendto as a sharing possibility to the context menu of each item
* Upload videos to Youtube, bug #522210
* Use a GStreamer pipeline to encode images, bug #628226
* Save EXIF data to photos, bug #583650
......@@ -63,6 +63,14 @@
</object>
<accelerator key="O" modifiers="GDK_CONTROL_MASK"/>
</child>
<child>
<object class="GtkAction" id="share">
<property name="name">Share</property>
<property name="label" translatable="yes">Share…</property>
<signal name="activate" handler="cheese_main_window_on_share_files"/>
</object>
<accelerator key="H" modifiers="GDK_CONTROL_MASK"/>
</child>
<child>
<object class="GtkAction" id="save_as">
<property name="name">SaveAs</property>
......@@ -240,6 +248,8 @@
<menuitem action="effects_page_next"/>
<menuitem action="effects_page_prev"/>
<separator/>
<menuitem action="share"/>
<separator/>
<menuitem action="move_to_trash"/>
<menuitem action="move_all_to_trash"/>
<separator/>
......@@ -253,6 +263,8 @@
<popup name="thumbnail_popup" id="thumbnail_popup">
<menuitem action="open"/>
<separator/>
<menuitem action="share"/>
<separator/>
<menuitem action="save_as"/>
<separator/>
<menuitem action="move_to_trash"/>
......
/*
* Copyright © 2011 Patricia Santana Cruz <patriciasantanacruz@gmail.com>
*
* Licensed under the GNU General Public License Version 2
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* Class used for sharing images or videos with different technologies through
* nautilus-sendto.
*/
public class Cheese.ShareableMedia : GLib.Object {
private const string XID = "--xid=";
private uint num_children = 0;
Cheese.MainWindow window;
/**
* Create a new ShareableMedia instance.
*
* @param main_window the main window of the Cheese application
*/
public ShareableMedia (Cheese.MainWindow main_window)
{
window = main_window;
}
/**
* Callback to be called when the child exits.
*
* Cleans up the child process spawned by {@link ShareableMedia.share_files}
* and if that child is the last one, it will also set the cursor
* back to normal.
*
* @param pid the process id of the child process
* @param status the status information about the child process
*
* @see ShareableMedia.share_files
*/
void child_finished (Pid pid, int status)
{
/* Method for checking WIFEXITED(status) value, which returns true if the
* child terminated normally, that is, by calling exit(3) or _exit(2), or
* by returning from main().
*/
if (!Process.if_exited(status))
warning ("nautilus-sendto exited abnormally");
Process.close_pid(pid);
--num_children;
if (num_children == 0)
{
window.get_window ().set_cursor (
new Gdk.Cursor (Gdk.CursorType.LEFT_PTR));
}
}
/**
* Used for sharing one or more images and/or one or more videos through
* different technologies.
*
* It works asynchronously and will create a new child every time it is
* called. When the child exists, the {@link ShareableMedia.child_finished}
* callback is called.
*
* It will also set the cursor to busy to indicate to the user that
* there is some task that is being done.
*
* @param files a list of the files (videos and/or images that are going to
* be shared.
*
* @see ShareableMedia.child_finished.
*/
public void share_files (GLib.List<GLib.File> files)
{
string[] argv = {};
// Defined in cheese-window.vala.
argv += SENDTO_EXEC;
argv += XID + "%lu".printf (
Gdk.X11Window.get_xid (window.get_window ()));
files.foreach ((file) => argv += file.get_path ());
try
{
Pid child_pid;
if (Process.spawn_async ("/", argv, null,
SpawnFlags.SEARCH_PATH | SpawnFlags.DO_NOT_REAP_CHILD, null,
out child_pid))
{
ChildWatch.add (child_pid, child_finished);
++num_children;
/* Show a busy cursor if there are any children. It just needs
* to be done for the first child.
*/
if (num_children == 1)
{
window.get_window ().set_cursor (new Gdk.Cursor
(Gdk.CursorType.WATCH));
}
}
}
catch (SpawnError error)
{
window.get_window ().set_cursor (new Gdk.Cursor
(Gdk.CursorType.LEFT_PTR));
warning ("Unable to launch nautilus-sendto: %s\n", error.message);
}
}
}
......@@ -31,6 +31,7 @@ using CanberraGtk;
const int FULLSCREEN_TIMEOUT_INTERVAL = 5 * 1000;
const int EFFECTS_PER_PAGE = 9;
const string SENDTO_EXEC = "nautilus-sendto";
public class Cheese.MainWindow : Gtk.Window
{
......@@ -85,6 +86,8 @@ public class Cheese.MainWindow : Gtk.Window
private Gtk.Action countdown_action;
private Gtk.Action effects_page_prev_action;
private Gtk.Action effects_page_next_action;
private Gtk.Action share_action;
private Gtk.ActionGroup main_actions;
private bool is_fullscreen;
private bool is_wide_mode;
......@@ -106,6 +109,8 @@ public class Cheese.MainWindow : Gtk.Window
private Cheese.Effect selected_effect;
private Cheese.ShareableMedia shareable_media;
/**
* Destroy the main window, and shutdown the application, when quitting.
*
......@@ -158,7 +163,12 @@ public class Cheese.MainWindow : Gtk.Window
{
if (event.button == 3)
{
thumbnail_popup.popup (null, thumb_view, null, event.button, event.time);
thumbnail_popup.popup (null, thumb_view, null, event.button, event.time);
// Check whether nautilus-sendto is installed or not. In case it is, set
// the "Share" action to sensitive, if it is not, set it to insensitive.
bool nautilus_sendto_installed = Environment.find_program_in_path(SENDTO_EXEC) != null;
share_action.set_sensitive (nautilus_sendto_installed);
}
}
else
......@@ -340,6 +350,20 @@ public class Cheese.MainWindow : Gtk.Window
}
}
/**
* Share the selected file(s) in the thumbview.
*
* A dialog is shown to the user, where the technology for sharing the
* image or video can be selected.
*
* @param action the action that emitted the signal
*/
[CCode (instance_pos = -1)]
public void on_share_files (Gtk.Action action)
{
shareable_media.share_files (thumb_view.get_selected_images_list ());
}
/**
* Save the selected file in the thumbview to an alternate storage location.
*
......@@ -1370,6 +1394,7 @@ public class Cheese.MainWindow : Gtk.Window
buttons_area = gtk_builder.get_object ("buttons_area") as Gtk.Box;
thumbnail_popup = gtk_builder.get_object ("thumbnail_popup") as Gtk.Menu;
main_actions = gtk_builder.get_object ("main_actions") as Gtk.ActionGroup;
take_photo_action = gtk_builder.get_object ("take_photo") as Gtk.Action;
take_video_action = gtk_builder.get_object ("take_video") as Gtk.Action;
take_burst_action = gtk_builder.get_object ("take_burst") as Gtk.Action;
......@@ -1382,6 +1407,10 @@ public class Cheese.MainWindow : Gtk.Window
fullscreen_action = gtk_builder.get_object ("fullscreen") as Gtk.ToggleAction;
effects_page_next_action = gtk_builder.get_object ("effects_page_next") as Gtk.Action;
effects_page_prev_action = gtk_builder.get_object ("effects_page_prev") as Gtk.Action;
share_action = gtk_builder.get_object ("share") as Gtk.Action;
shareable_media = new Cheese.ShareableMedia (this);
main_actions.pre_activate.connect(on_action_pre_activated);
/* Array contains all 'buttons', for easier manipulation
* IMPORTANT: IF ANOTHER BUTTON IS ADDED UNDER THE VIEWPORT, ADD IT TO THIS ARRAY */
......@@ -1456,6 +1485,24 @@ public class Cheese.MainWindow : Gtk.Window
fullscreen_action.active = true;
}
/**
* Decide which actions will be sensitive or insensitive.
*
* @param action the action that emitted the signal.
*/
public void on_action_pre_activated (Gtk.Action action)
{
if (strcmp (action.get_name(), "edit_action") == 0)
{
if (thumb_view.get_selected_images_list () != null)
{
bool nautilus_sendto_installed = Environment.find_program_in_path(SENDTO_EXEC) != null;
share_action.set_sensitive (nautilus_sendto_installed);
} else
share_action.set_sensitive (false);
}
}
/**
* Setup the camera listed in GSettings.
*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment