pitivi r1292 - in trunk/pitivi: . ui
- From: edwardrv svn gnome org
- To: svn-commits-list gnome org
- Subject: pitivi r1292 - in trunk/pitivi: . ui
- Date: Sat, 27 Sep 2008 17:40:28 +0000 (UTC)
Author: edwardrv
Date: Sat Sep 27 17:40:27 2008
New Revision: 1292
URL: http://svn.gnome.org/viewvc/pitivi?rev=1292&view=rev
Log:
UI : Allow selection of input devices for capture
Modified:
trunk/pitivi/bin.py
trunk/pitivi/ui/cam_capture.glade
trunk/pitivi/ui/mainwindow.py
trunk/pitivi/ui/webcam_managerdialog.py
Modified: trunk/pitivi/bin.py
==============================================================================
--- trunk/pitivi/bin.py (original)
+++ trunk/pitivi/bin.py Sat Sep 27 17:40:27 2008
@@ -565,32 +565,39 @@
SmartBin derivative for capturing streams.
"""
- # FIXME : THESE ARE HARDCODED PLUGINS !!!
- # We should use a system allowing you to see all available usable
- # input HW device + plugin and use that instead
-
- def __init__(self):
+ def __init__(self, audiodevice=None, videodevice=None):
gst.log("Creating new smartcapturebin")
- self.videosrc = gst.element_factory_make("v4l2src", "webcam-vsrc")
- self.audiosrc = gst.element_factory_make("alsasrc", "webcam-asrc")
-
- SmartBin.__init__(self, "smartcapturebin", has_video=True, has_audio=True,
+ self.__audiodev = audiodevice
+ self.__videodev = videodevice
+ self.videosrc = None
+ self.audiosrc = None
+
+ SmartBin.__init__(self, "smartcapturebin",
+ has_video=bool(videodevice),
+ has_audio=bool(audiodevice),
width=640, height=490)
def _addSource(self):
- self.q1 = gst.element_factory_make("queue", "webcam-firstvqueue")
- self.q1.props.max_size_time = 10 * gst.SECOND
- self.q2 = gst.element_factory_make("queue", "webcam-firstaqueue")
- self.q2.props.max_size_time = 30 * gst.SECOND
- self.q2.props.max_size_buffers = 0
- self.q2.props.max_size_bytes = 0
- self.add(self.videosrc, self.audiosrc, self.q1, self.q2)
+ if self.__audiodev:
+ self.audiosrc = self.__audiodev.makeAudioBin()
+ self.q2 = gst.element_factory_make("queue", "webcam-firstaqueue")
+ self.q2.props.max_size_time = 30 * gst.SECOND
+ self.q2.props.max_size_buffers = 0
+ self.q2.props.max_size_bytes = 0
+ self.add(self.audiosrc, self.q2)
+ if self.__videodev:
+ self.videosrc = self.__videodev.makeVideoBin()
+ self.q1 = gst.element_factory_make("queue", "webcam-firstvqueue")
+ self.q1.props.max_size_time = 10 * gst.SECOND
+ self.add(self.videosrc, self.q1)
def _connectSource(self):
self.debug("connecting sources")
- gst.element_link_many(self.videosrc, self.q1, self.vtee)
- gst.element_link_many(self.audiosrc, self.q2, self.atee)
+ if self.videosrc:
+ gst.element_link_many(self.videosrc, self.q1, self.vtee)
+ if self.audiosrc:
+ gst.element_link_many(self.audiosrc, self.q2, self.atee)
self.debug("finished connecting sources")
def _asyncReset(self, uri, setting):
@@ -608,10 +615,12 @@
#
# This is fixed in gst-plugins-base cvs 0.10.20.1
self.debug("Setting sources to NULL again to reset their timestamps !")
- self.videosrc.set_state(gst.STATE_NULL)
- self.videosrc.set_state(gst.STATE_READY)
- self.audiosrc.set_state(gst.STATE_NULL)
- self.audiosrc.set_state(gst.STATE_READY)
+ if self.videosrc:
+ self.videosrc.set_state(gst.STATE_NULL)
+ self.videosrc.set_state(gst.STATE_READY)
+ if self.audiosrc:
+ self.audiosrc.set_state(gst.STATE_NULL)
+ self.audiosrc.set_state(gst.STATE_READY)
SmartBin.record(self, uri, settings)
Modified: trunk/pitivi/ui/cam_capture.glade
==============================================================================
--- trunk/pitivi/ui/cam_capture.glade (original)
+++ trunk/pitivi/ui/cam_capture.glade Sat Sep 27 17:40:27 2008
@@ -1,221 +1,134 @@
-<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
-<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
-
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
+<!--Generated with glade3 3.4.5 on Sat Sep 27 15:43:58 2008 -->
<glade-interface>
-
-<widget class="GtkDialog" id="cam_capture">
- <property name="width_request">530</property>
- <property name="height_request">500</property>
- <property name="visible">True</property>
- <property name="title" translatable="yes">Record from Webcam</property>
- <property name="type">GTK_WINDOW_TOPLEVEL</property>
- <property name="window_position">GTK_WIN_POS_NONE</property>
- <property name="modal">False</property>
- <property name="resizable">True</property>
- <property name="destroy_with_parent">False</property>
- <property name="decorated">True</property>
- <property name="skip_taskbar_hint">False</property>
- <property name="skip_pager_hint">False</property>
- <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
- <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
- <property name="focus_on_map">True</property>
- <property name="urgency_hint">False</property>
- <property name="has_separator">True</property>
-
- <child internal-child="vbox">
- <widget class="GtkVBox" id="dialog-vbox1">
- <property name="visible">True</property>
- <property name="homogeneous">False</property>
- <property name="spacing">0</property>
-
- <child internal-child="action_area">
- <widget class="GtkHButtonBox" id="dialog-action_area1">
- <property name="visible">True</property>
- <property name="layout_style">GTK_BUTTONBOX_END</property>
-
- <child>
- <widget class="GtkButton" id="record_btn">
- <property name="visible">True</property>
- <property name="can_default">True</property>
- <property name="can_focus">True</property>
- <property name="relief">GTK_RELIEF_NORMAL</property>
- <property name="focus_on_click">True</property>
- <property name="response_id">0</property>
-
- <child>
- <widget class="GtkAlignment" id="btn_record">
- <property name="visible">True</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xscale">0</property>
- <property name="yscale">0</property>
- <property name="top_padding">0</property>
- <property name="bottom_padding">0</property>
- <property name="left_padding">0</property>
- <property name="right_padding">0</property>
-
- <child>
- <widget class="GtkHBox" id="hbox2">
- <property name="visible">True</property>
- <property name="homogeneous">False</property>
- <property name="spacing">2</property>
-
- <child>
- <widget class="GtkImage" id="image2">
- <property name="visible">True</property>
- <property name="stock">gtk-media-record</property>
- <property name="icon_size">4</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkLabel" id="lbl">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Start Recording</property>
- <property name="use_underline">True</property>
- <property name="use_markup">False</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
- <property name="width_chars">-1</property>
- <property name="single_line_mode">False</property>
- <property name="angle">0</property>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- </child>
- </widget>
- </child>
-
- <child>
- <widget class="GtkButton" id="close_btn">
- <property name="visible">True</property>
- <property name="can_default">True</property>
- <property name="can_focus">True</property>
- <property name="relief">GTK_RELIEF_NORMAL</property>
- <property name="focus_on_click">True</property>
- <property name="response_id">0</property>
-
- <child>
- <widget class="GtkAlignment" id="alignment3">
- <property name="visible">True</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xscale">0</property>
- <property name="yscale">0</property>
- <property name="top_padding">0</property>
- <property name="bottom_padding">0</property>
- <property name="left_padding">0</property>
- <property name="right_padding">0</property>
-
- <child>
- <widget class="GtkHBox" id="hbox3">
- <property name="visible">True</property>
- <property name="homogeneous">False</property>
- <property name="spacing">2</property>
-
- <child>
- <widget class="GtkImage" id="image3">
- <property name="visible">True</property>
- <property name="stock">gtk-close</property>
- <property name="icon_size">4</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkLabel" id="label3">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Close</property>
- <property name="use_underline">True</property>
- <property name="use_markup">False</property>
- <property name="justify">GTK_JUSTIFY_LEFT</property>
- <property name="wrap">False</property>
- <property name="selectable">False</property>
- <property name="xalign">0.5</property>
- <property name="yalign">0.5</property>
- <property name="xpad">0</property>
- <property name="ypad">0</property>
- <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
- <property name="width_chars">-1</property>
- <property name="single_line_mode">False</property>
- <property name="angle">0</property>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- </child>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="pack_type">GTK_PACK_END</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkDrawingArea" id="draw_window">
- <property name="visible">True</property>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">True</property>
- <property name="fill">True</property>
- </packing>
- </child>
-
- <child>
- <widget class="GtkStatusbar" id="statusbar1">
- <property name="visible">True</property>
- <property name="has_resize_grip">True</property>
- </widget>
- <packing>
- <property name="padding">0</property>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="pack_type">GTK_PACK_END</property>
- </packing>
- </child>
- </widget>
- </child>
-</widget>
-
+ <widget class="GtkDialog" id="cam_capture">
+ <property name="border_width">5</property>
+ <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+ <property name="has_separator">False</property>
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <widget class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <child>
+ <widget class="GtkDrawingArea" id="draw_window">
+ <property name="width_request">320</property>
+ <property name="height_request">240</property>
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="padding">5</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkTable" id="table1">
+ <property name="visible">True</property>
+ <property name="n_rows">2</property>
+ <property name="n_columns">2</property>
+ <property name="column_spacing">2</property>
+ <property name="row_spacing">2</property>
+ <child>
+ <widget class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="xpad">5</property>
+ <property name="label" translatable="yes">Audio Capture Device :</property>
+ </widget>
+ <packing>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="xalign">0</property>
+ <property name="xpad">5</property>
+ <property name="label" translatable="yes">Video Capture Device :</property>
+ </widget>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkComboBox" id="audiodev_combo">
+ <property name="visible">True</property>
+ <property name="active">0</property>
+ <property name="items" translatable="yes">No device available</property>
+ <signal name="changed" handler="_adevComboChangedCb"/>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkComboBox" id="videodev_combo">
+ <property name="visible">True</property>
+ <property name="active">0</property>
+ <property name="items" translatable="yes">No device available </property>
+ <signal name="changed" handler="_vdevComboChangedCb"/>
+ </widget>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">5</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+ <child>
+ <widget class="GtkButton" id="record_btn">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="label" translatable="yes">gtk-media-record</property>
+ <property name="use_stock">True</property>
+ <property name="response_id">0</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkButton" id="close_btn">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="label" translatable="yes">gtk-close</property>
+ <property name="use_stock">True</property>
+ <property name="response_id">0</property>
+ </widget>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
</glade-interface>
Modified: trunk/pitivi/ui/mainwindow.py
==============================================================================
--- trunk/pitivi/ui/mainwindow.py (original)
+++ trunk/pitivi/ui/mainwindow.py Sat Sep 27 17:40:27 2008
@@ -452,8 +452,8 @@
# Import from Webcam callback
def _ImportWebcam(self,unused_action):
- WebcamManagerDialog()
-
+ w = WebcamManagerDialog(instance.PiTiVi)
+ w.show()
# Capture network stream callback
def _ImportNetstream(self,unused_action):
Modified: trunk/pitivi/ui/webcam_managerdialog.py
==============================================================================
--- trunk/pitivi/ui/webcam_managerdialog.py (original)
+++ trunk/pitivi/ui/webcam_managerdialog.py Sat Sep 27 17:40:27 2008
@@ -42,6 +42,8 @@
# Create gtk widget using glade model
self.draw_window = self.widgets["draw_window"]
+ self.draw_window.unset_flags(gtk.DOUBLE_BUFFERED)
+ self.draw_window.unset_flags(gtk.SENSITIVE)
self.record_btn = self.widgets["record_btn"]
self.close_btn = self.widgets["close_btn"]
@@ -55,14 +57,26 @@
self.sourcefactories = SourceFactoriesWidget()
- gst.debug("SmartCaptureBin player created")
- self.player = SmartCaptureBin()
- self.setSinks()
+ self._audiodev = None
+ self._videodev = None
+
+ self._vdevcombo = self.widgets["videodev_combo"]
+ self._vdevcombo.set_active(0)
+ self._vdevcombo.set_model(gtk.ListStore(str, object))
+ self._vdevcombo.set_attributes(self._vdevcombo.child.get_cell_renderers()[0],
+ text=0)
+ self._adevcombo = self.widgets["audiodev_combo"]
+ self._adevcombo.set_active(0)
+ self._adevcombo.set_model(gtk.ListStore(str, object))
+ self._adevcombo.set_attributes(self._adevcombo.child.get_cell_renderers()[0],
+ text=0)
+ self.__updateVideoCombo()
+ self.__updateAudioCombo()
self.filepath = None
- # Not a good idea to do this at this point
- self.player.set_state(gst.STATE_PLAYING)
+ self.sink = SinkBin()
+ CallbackThread(self.__setupPlayer).start()
def show_all(self):
self.window.show_all()
@@ -76,7 +90,8 @@
def do_recording(self, w):
if self.record_btn.get_label() == "Start Recording":
gst.debug("recording started")
- self.filepath = 'file://'+tempfile.mktemp()+'.ogg'
+ self.filepath = 'file://'+tempfile.mktemp(suffix=".ogg",
+ prefix="pitivi-webcam-capture-")
self.player.record(self.filepath, ExportSettings())
self.record_btn.set_label("Stop Recording")
self.player.set_state(gst.STATE_PLAYING)
@@ -86,14 +101,14 @@
else:
gst.debug("recording stopped")
self.player.stopRecording()
+ # FIXME : use the generic way for adding a file
self.sourcefactories.sourcelist.addFiles([self.filepath])
self.player.set_state(gst.STATE_PLAYING)
self.record_btn.set_label("Start Recording")
# For Setting up audio,video sinks
def setSinks(self):
- sink = SinkBin()
- sink.connectSink(self.player, True, True)
+ self.sink.connectSink(self.player, True, True)
bus = self.player.get_bus()
bus.add_signal_watch()
bus.enable_sync_message_emission()
@@ -116,5 +131,131 @@
try:
imagesink.set_xwindow_id(self.draw_window.window.xid)
except:
- print "OH OH"
+ gst.warning("Couldn't set the XID on our video sink !")
+
+ def __setupPlayer(self):
+ gst.debug("Creating initial SmartCaptureBin")
+ # figure out adev
+ probe = self.pitivi.deviceprobe
+ if len(probe.getAudioSourceDevices()):
+ adev = probe.getAudioSourceDevices()[0]
+ else:
+ adev = None
+ self.__changeSelectedAudio(adev)
+
+ if len(probe.getVideoSourceDevices()):
+ vdev = probe.getVideoSourceDevices()[0]
+ else:
+ vdev = None
+ self.__changeSelectedVideo(vdev)
+
+ probe.connect("device-added", self.__deviceAddedCb)
+ probe.connect("device-removed", self.__deviceRemovedCb)
+
+ if hasattr(self, "player"):
+ self.player.set_state(gst.STATE_NULL)
+ self.player = SmartCaptureBin(audiodevice=adev,
+ videodevice=vdev)
+ self.setSinks()
+ # FIXME : check for state change failures
+ self.player.set_state(gst.STATE_PLAYING)
+
+ def __resetPlayer(self):
+ ## call me in another thread !
+ gst.debug("Setting previous to NULL")
+ self.player.set_state(gst.STATE_NULL)
+ gst.debug("Creating new SmartCaptureBin(%r,%r)" % (self._audiodev, self._videodev))
+ self.player = SmartCaptureBin(audiodevice = self._audiodev,
+ videodevice = self._videodev)
+ gst.debug("Calling setSinks()")
+ self.setSinks()
+ gst.debug("Finally setting to PLAYING...")
+ res = self.player.set_state(gst.STATE_PLAYING)
+ gst.debug("... which returned %r" % res)
+
+ def __changeSelectedCombo(self, combo, device):
+ gst.debug("device %r" % device)
+ model = combo.get_model()
+ idx = 0
+ for name, dev in model:
+ if dev == device:
+ break
+ idx += 1
+ combo.set_active(idx)
+
+ def __changeSelectedAudio(self, device):
+ self._audiodev = device
+ self.__changeSelectedCombo(self._adevcombo, device)
+
+ def __changeSelectedVideo(self, device):
+ self._videodev = device
+ self.__changeSelectedCombo(self._vdevcombo, device)
+
+ def __deviceAddedCb(self, probe, device):
+ gst.debug("device %r appeared" % device)
+ self.__updateAudioCombo()
+ self.__updateVideoCombo()
+
+ def __deviceRemovedCb(self, probe, device):
+ gst.debug("device %r went away" % device)
+ if self._audiodev == device:
+ devs = self.pitivi.deviceprobe.getAudioSourceDevices()
+ if len(devs):
+ self.__changeSelectedAudio(devs[0])
+ else:
+ self._audiodev = None
+ elif self._videodev == device:
+ devs = self.pitivi.deviceprobe.getVideoSourceDevices()
+ if len(devs):
+ self.__changeSelectedVideo(devs[0])
+ else:
+ self._videodev = None
+ self.__updateAudioCombo()
+ self.__updateVideoCombo()
+
+ def __updateCombo(self, combo, devices):
+ model = combo.get_model()
+ if len(devices) == len(model):
+ # nothing changed
+ return
+ model.clear()
+ for dev in devices:
+ model.append([dev.displayname, dev])
+
+ def __updateAudioCombo(self):
+ self.__updateCombo(self._adevcombo,
+ self.pitivi.deviceprobe.getAudioSourceDevices())
+ self.__changeSelectedAudio(self._audiodev)
+
+ def __updateVideoCombo(self):
+ self.__updateCombo(self._vdevcombo,
+ self.pitivi.deviceprobe.getVideoSourceDevices())
+ self.__changeSelectedVideo(self._videodev)
+
+ def _adevComboChangedCb(self, widget):
+ # get the active device
+ row = widget.get_model()[widget.get_active()]
+ if len(row) < 2:
+ return
+ dev = row[1]
+ gst.debug("device %r" % dev)
+ if dev == self._audiodev:
+ return
+ self.__changeSelectedAudio(dev)
+ if not hasattr(self, "player"):
+ return
+ CallbackThread(self.__resetPlayer).start()
+
+ def _vdevComboChangedCb(self, widget):
+ row = widget.get_model()[widget.get_active()]
+ if len(row) < 2:
+ return
+ dev = row[1]
+ gst.debug("device %r" % dev)
+ if dev == self._videodev:
+ return
+ self.__changeSelectedVideo(dev)
+ if not hasattr(self, "player"):
+ return
+ CallbackThread(self.__resetPlayer).start()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]