1
# PiTiVi , Non-linear video editor
3
# pitivi/ui/webcam_managerdialog.py
5
# Copyright (c) 2008, Sarath Lakshman <sarathlakshman@slynux.org>
7
# This program is free software; you can redistribute it and/or
8
# modify it under the terms of the GNU Lesser General Public
9
# License as published by the Free Software Foundation; either
10
# version 2.1 of the License, or (at your option) any later version.
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
# Lesser General Public License for more details.
17
# You should have received a copy of the GNU Lesser General Public
18
# License along with this program; if not, write to the
19
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20
# Boston, MA 02111-1307, USA.
25
from pitivi.settings import ExportSettings
26
from pitivi.sourcelist import SourceList
27
from pitivi.bin import SmartCaptureBin, SinkBin
28
from pitivi.threads import CallbackThread
29
from pitivi.ui.glade import GladeWindow
31
class WebcamManagerDialog(GladeWindow):
33
Webcan capture dialog box
35
glade_file = "cam_capture.glade"
37
def __init__(self, pitivi):
38
gst.log("Creating new WebcamManager Dialog")
40
GladeWindow.__init__(self)
42
# Create gtk widget using glade model
43
self.draw_window = self.widgets["draw_window"]
44
self.draw_window.unset_flags(gtk.DOUBLE_BUFFERED)
45
self.draw_window.unset_flags(gtk.SENSITIVE)
46
self.record_btn = self.widgets["record_btn"]
47
self.close_btn = self.widgets["close_btn"]
49
self.close_btn.connect("clicked", self.close)
50
self.record_btn.connect("clicked", self.threaded_recording)
51
self.window.connect("destroy", self.close)
53
self.record_btn = self.record_btn.get_children()[0]
54
self.record_btn = self.record_btn.get_children()[0].get_children()[1]
55
self.record_btn.set_label("Start Recording")
57
self.sourcefactories = SourceList()
62
self._vdevcombo = self.widgets["videodev_combo"]
63
self._vdevcombo.set_active(0)
64
self._vdevcombo.set_model(gtk.ListStore(str, object))
65
self._vdevcombo.set_attributes(self._vdevcombo.child.get_cell_renderers()[0],
67
self._adevcombo = self.widgets["audiodev_combo"]
68
self._adevcombo.set_active(0)
69
self._adevcombo.set_model(gtk.ListStore(str, object))
70
self._adevcombo.set_attributes(self._adevcombo.child.get_cell_renderers()[0],
72
self._updateVideoCombo()
73
self._updateAudioCombo()
78
CallbackThread(self._setupPlayer).start()
81
self.window.show_all()
83
# Perform record in a seperate thread
84
def threaded_recording(self, w):
85
CallbackThread(self.do_recording, w).start()
88
# Record button action callback
89
def do_recording(self, w):
90
if self.record_btn.get_label() == "Start Recording":
91
gst.debug("recording started")
92
self.filepath = 'file://'+tempfile.mktemp(suffix=".ogg",
93
prefix="pitivi-webcam-capture-")
94
self.player.record(self.filepath, ExportSettings())
95
self.record_btn.set_label("Stop Recording")
96
self.player.set_state(gst.STATE_PLAYING)
101
gst.debug("recording stopped")
102
self.player.stopRecording()
103
# FIXME : use the generic way for adding a file
104
self.sourcefactories.addUris([self.filepath])
105
self.player.set_state(gst.STATE_PLAYING)
106
self.record_btn.set_label("Start Recording")
108
# For Setting up audio,video sinks
110
self.sink.connectSink(self.player, True, True)
111
bus = self.player.get_bus()
112
bus.add_signal_watch()
113
bus.enable_sync_message_emission()
114
bus.connect('sync-message::element', self.on_sync_message)
116
# Close the Webcamdialog
119
self.player.set_state(gst.STATE_NULL)
120
self.window.destroy()
122
# For draw_window syncs
123
def on_sync_message(self, bus, message):
124
if message.structure is None:
126
message_name = message.structure.get_name()
127
if message_name == 'prepare-xwindow-id':
128
# Assign the viewport
129
imagesink = message.src
130
imagesink.set_property('force-aspect-ratio', True)
132
imagesink.set_xwindow_id(self.draw_window.window.xid)
134
gst.warning("Couldn't set the XID on our video sink !")
136
def _setupPlayer(self):
137
gst.debug("Creating initial SmartCaptureBin")
139
probe = self.pitivi.deviceprobe
140
if probe is not None and len(probe.getAudioSourceDevices()):
141
adev = probe.getAudioSourceDevices()[0]
144
self._changeSelectedAudio(adev)
146
if len(probe.getVideoSourceDevices()):
147
vdev = probe.getVideoSourceDevices()[0]
150
self._changeSelectedVideo(vdev)
152
if probe is not None:
153
probe.connect("device-added", self._deviceAddedCb)
154
probe.connect("device-removed", self._deviceRemovedCb)
156
if hasattr(self, "player"):
157
self.player.set_state(gst.STATE_NULL)
158
self.player = SmartCaptureBin(audiodevice=adev,
161
# FIXME : check for state change failures
162
self.player.set_state(gst.STATE_PLAYING)
164
def _resetPlayer(self):
165
## call me in another thread !
166
gst.debug("Setting previous to NULL")
167
self.player.set_state(gst.STATE_NULL)
168
gst.debug("Creating new SmartCaptureBin(%r,%r)" % (self._audiodev, self._videodev))
169
self.player = SmartCaptureBin(audiodevice = self._audiodev,
170
videodevice = self._videodev)
171
gst.debug("Calling setSinks()")
173
gst.debug("Finally setting to PLAYING...")
174
res = self.player.set_state(gst.STATE_PLAYING)
175
gst.debug("... which returned %r" % res)
177
def _changeSelectedCombo(self, combo, device):
178
gst.debug("device %r" % device)
179
model = combo.get_model()
181
for name, dev in model:
185
combo.set_active(idx)
187
def _changeSelectedAudio(self, device):
188
self._audiodev = device
189
self._changeSelectedCombo(self._adevcombo, device)
191
def _changeSelectedVideo(self, device):
192
self._videodev = device
193
self._changeSelectedCombo(self._vdevcombo, device)
195
def _deviceAddedCb(self, probe, device):
196
gst.debug("device %r appeared" % device)
197
self._updateAudioCombo()
198
self._updateVideoCombo()
200
def _deviceRemovedCb(self, probe, device):
201
gst.debug("device %r went away" % device)
202
if self._audiodev == device:
203
devs = self.pitivi.deviceprobe.getAudioSourceDevices()
205
self._changeSelectedAudio(devs[0])
207
self._audiodev = None
208
elif self._videodev == device:
209
devs = self.pitivi.deviceprobe.getVideoSourceDevices()
211
self._changeSelectedVideo(devs[0])
213
self._videodev = None
214
self._updateAudioCombo()
215
self._updateVideoCombo()
217
def _updateCombo(self, combo, devices):
218
model = combo.get_model()
219
if len(devices) == len(model):
224
model.append([dev.name, dev])
226
def _updateAudioCombo(self):
227
self._updateCombo(self._adevcombo,
228
self.pitivi.deviceprobe.getAudioSourceDevices())
229
self._changeSelectedAudio(self._audiodev)
231
def _updateVideoCombo(self):
232
self._updateCombo(self._vdevcombo,
233
self.pitivi.deviceprobe.getVideoSourceDevices())
234
self._changeSelectedVideo(self._videodev)
236
def _adevComboChangedCb(self, widget):
237
# get the active device
238
row = widget.get_model()[widget.get_active()]
242
gst.debug("device %r" % dev)
243
if dev == self._audiodev:
245
self._changeSelectedAudio(dev)
246
if not hasattr(self, "player"):
248
CallbackThread(self._resetPlayer).start()
250
def _vdevComboChangedCb(self, widget):
251
row = widget.get_model()[widget.get_active()]
255
gst.debug("device %r" % dev)
256
if dev == self._videodev:
258
self._changeSelectedVideo(dev)
259
if not hasattr(self, "player"):
261
CallbackThread(self._resetPlayer).start()