diff options
Diffstat (limited to 'screencast_activity.py')
-rw-r--r-- | screencast_activity.py | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/screencast_activity.py b/screencast_activity.py new file mode 100644 index 0000000..edffd2e --- /dev/null +++ b/screencast_activity.py @@ -0,0 +1,206 @@ +# Copyright 2008 Chris Ball. +# +# 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, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +"""Screencast Activity: An activity for producing XO tutorials.""" +from gettext import gettext as _ +from dbus.service import method, signal as dbus_signal +import fcntl +import gobject +import gtk +import logging +import os +import popen2 +import re +import shutil +import signal + +from sugar.activity import activity +from sugar.activity.activity import ActivityToolbox, \ + get_bundle_path, get_bundle_name +from sugar.graphics.alert import NotifyAlert +from sugar.graphics.combobox import ComboBox + +SERVICE = "org.laptop.Screencast" +IFACE = SERVICE +PATH = "/org/laptop/Screencast" + +OUTFILE = "/tmp/recordmydesktop.ogv" + +class ScreencastActivity(activity.Activity): + """Screencast Activity as specified in activity.info""" + def __init__(self, handle): + """Set up the Screencast activity.""" + super(ScreencastActivity, self).__init__(handle) + self._logger = logging.getLogger('screencast-activity') + + from sugar.graphics.menuitem import MenuItem + from sugar.graphics.icon import Icon + + # Main layout. Record button, stop button, label. + hbox = gtk.HBox() + vbox = gtk.VBox() + + # Toolbar. + toolbox = ActivityToolbox(self) + activity_toolbar = toolbox.get_activity_toolbar() + activity_toolbar.remove(activity_toolbar.share) + activity_toolbar.share = None + activity_toolbar.remove(activity_toolbar.keep) + activity_toolbar.keep = None + self.set_toolbox(toolbox) + toolbox.show() + + # Recording buttons. + self.record = gtk.Button("Record") + self.record.connect("clicked", self.record_cb) + self.record.set_size_request(150, 150) + recimage = gtk.Image() + recimage.set_from_icon_name("media-record", -1) + self.record.set_image(recimage) + self.stop = gtk.Button("Stop") + self.stop.connect("clicked", self.stop_cb) + self.stop.set_size_request(150, 150) + self.stop.set_sensitive(False) + stopimage = gtk.Image() + stopimage.set_from_icon_name("media-playback-stop", -1) + self.stop.set_image(stopimage) + + # Record sound checkbox and quality selector + hbox2 = gtk.HBox(spacing=50) + self.audiocheckbox = gtk.CheckButton(label="record sound") + self.audiocheckbox.set_active(True) + hbox2.add(self.audiocheckbox) + self.qualitycombo = ComboBox() + self.qualitycombo.append_item("0", "high quality video") + self.qualitycombo.append_item("1", "medium quality video") + self.qualitycombo.append_item("2", "low quality video") + self.qualitycombo.set_active(2) + + hbox2.add(self.qualitycombo) + options = gtk.Alignment(0.5, 0, 0, 0) + options.add(hbox2) + + # Status label. + self.status = gtk.Label(_("Status: Stopped")) + hbox.pack_start(self.record, expand=False, padding=40) + hbox.pack_start(self.stop, expand=False, padding=40) + + valign = gtk.Alignment(0.5, 0.4, 0, 0) + valign.add(vbox) + vbox.pack_end(self.status, expand=True, padding=40) + vbox.pack_end(hbox, expand=True, fill=False) + vbox.pack_end(options, expand=True, padding=40) + + self.set_canvas(valign) + self.show_all() + + def write_file (self, file_path): + print "Saving file to %s" % file_path + self.metadata['mime_type'] = 'video/ogg' + #try: + # shutil.copy(OUTFILE, file_path) + + #except IOError, e: + # print "unable to save to outfile: %s" % e + + + # FIXME: This fails in /tmp. + # that comment by probably cjb + # I have no idea why it was saving to filepath + #added copy-to-journal in check_status_cb + #error msgs are OK probably just no video processed + #Tony Forster + + #try: + + # os.remove(OUTFILE) + #except OSError, e: + # print "unable to remove outfile: %s" % e + + def can_close(self): + if self.status.get_text().startswith("Status: Stopped"): + return True + else: + self.alert("You need to finish operation before quitting.", self.status.get_text()) + + def alert(self, title, text=None): + alert = NotifyAlert(timeout=10) + alert.props.title = title + alert.props.msg = text + self.add_alert(alert) + alert.connect('response', self.alert_cancel_cb) + alert.show() + + def alert_cancel_cb(self, alert, response_id): + self.remove_alert(alert) + + def record_cb(self, record): + self.stop.set_sensitive(True) + self.record.set_sensitive(False) + self.audiocheckbox.set_sensitive(False) + self.qualitycombo.set_sensitive(False) + execargs = ["./recordmydesktop", "--no-frame", "--overwrite"] + if not self.audiocheckbox.get_active(): + execargs.append("--no-sound") + if self.qualitycombo.get_active()==0: + execargs.append("-v_quality") # in later versions seems to be --v_quality instead + execargs.append("0") + elif self.qualitycombo.get_active()==1: + execargs.append("-v_quality") # in later versions seems to be --v_quality instead + execargs.append("31") + execargs.append("-o") + execargs.append(OUTFILE) + print execargs + self.childp = popen2.Popen3(execargs, "t", 0) + flags = fcntl.fcntl(self.childp.childerr, fcntl.F_GETFL) + fcntl.fcntl(self.childp.childerr, fcntl.F_SETFL, flags|os.O_NONBLOCK) + self.timed_id = gobject.timeout_add(1000, self.check_status_cb) + self.status.set_text("Status: Recording") + + def stop_cb(self, stop): + print "Stop button clicked" + exitret = os.waitpid(self.childp.pid, os.WNOHANG) + if exitret[0] == 0: + os.kill(self.childp.pid, signal.SIGTERM) + self.stop.set_sensitive(False) + + def check_status_cb(self): + if self.childp.pid: + exitret = os.waitpid(self.childp.pid, os.WNOHANG) + if exitret[0] != 0: + print "no more record process" + # The recording process exited + self.status.set_text("Status: Stopped") + self.record.set_sensitive(True) + self.audiocheckbox.set_sensitive(True) + self.qualitycombo.set_sensitive(True) + if self._jobject.metadata['title_set_by_user'] == '1': + title = self.metadata['title'] + else: + title = "My Screencast" + os.system("copy-to-journal /tmp/recordmydesktop.ogv -m video/ogg -t \"%s\""% title) + return False + else: + # Maybe we have new stderr. + while True: + try: + err_line = self.childp.childerr.readline() + print err_line + if err_line.startswith("STATE:ENCODING"): + self.status.set_text("Status: Encoding, please wait") + except: + break + return True |