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.
26
from pitivi.settings import ExportSettings
27
from sourcelist import SourceList
28
from pitivi.bin import SmartCaptureBin, SinkBin
29
from pitivi.threads import CallbackThread
30
from glade import GladeWindow
32
class WebcamManagerDialog(GladeWindow):
34
Webcan capture dialog box
36
glade_file = "cam_capture.glade"
38
def __init__(self, pitivi):
39
gst.log("Creating new WebcamManager Dialog")
41
GladeWindow.__init__(self)
43
# Create gtk widget using glade model
44
self.draw_window = self.widgets["draw_window"]
45
self.draw_window.unset_flags(gtk.DOUBLE_BUFFERED)
46
self.draw_window.unset_flags(gtk.SENSITIVE)
47
self.record_btn = self.widgets["record_btn"]
48
self.close_btn = self.widgets["close_btn"]
50
self.close_btn.connect("clicked", self.close)
51
self.record_btn.connect("clicked", self.threaded_recording)
52
self.window.connect("destroy", self.close)
54
self.record_btn = self.record_btn.get_children()[0]
55
self.record_btn = self.record_btn.get_children()[0].get_children()[1]
56
self.record_btn.set_label("Start Recording")
58
self.sourcefactories = SourceList()
63
self._vdevcombo = self.widgets["videodev_combo"]
64
self._vdevcombo.set_active(0)
65
self._vdevcombo.set_model(gtk.ListStore(str, object))
66
self._vdevcombo.set_attributes(self._vdevcombo.child.get_cell_renderers()[0],
68
self._adevcombo = self.widgets["audiodev_combo"]
69
self._adevcombo.set_active(0)
70
self._adevcombo.set_model(gtk.ListStore(str, object))
71
self._adevcombo.set_attributes(self._adevcombo.child.get_cell_renderers()[0],
73
self.__updateVideoCombo()
74
self.__updateAudioCombo()
79
CallbackThread(self.__setupPlayer).start()
82
self.window.show_all()
84
# Perform record in a seperate thread
85
def threaded_recording(self, w):
86
CallbackThread(self.do_recording, w).start()
89
# Record button action callback
90
def do_recording(self, w):
91
if self.record_btn.get_label() == "Start Recording":
92
gst.debug("recording started")
93
self.filepath = 'file://'+tempfile.mktemp(suffix=".ogg",
94
prefix="pitivi-webcam-capture-")
95
self.player.record(self.filepath, ExportSettings())
96
self.record_btn.set_label("Stop Recording")
97
self.player.set_state(gst.STATE_PLAYING)
102
gst.debug("recording stopped")
103
self.player.stopRecording()
104
# FIXME : use the generic way for adding a file
105
self.sourcefactories.addFiles([self.filepath])
106
self.player.set_state(gst.STATE_PLAYING)
107
self.record_btn.set_label("Start Recording")
109
# For Setting up audio,video sinks
111
self.sink.connectSink(self.player, True, True)
112
bus = self.player.get_bus()
113
bus.add_signal_watch()
114
bus.enable_sync_message_emission()
115
bus.connect('sync-message::element', self.on_sync_message)
117
# Close the Webcamdialog
120
self.player.set_state(gst.STATE_NULL)
121
self.window.destroy()
123
# For draw_window syncs
124
def on_sync_message(self, bus, message):
125
if message.structure is None:
127
message_name = message.structure.get_name()
128
if message_name == 'prepare-xwindow-id':
129
# Assign the viewport
130
imagesink = message.src
131
imagesink.set_property('force-aspect-ratio', True)
133
imagesink.set_xwindow_id(self.draw_window.window.xid)
135
gst.warning("Couldn't set the XID on our video sink !")
137
def __setupPlayer(self):
138
gst.debug("Creating initial SmartCaptureBin")
140
probe = self.pitivi.deviceprobe
141
if len(probe.getAudioSourceDevices()):
142
adev = probe.getAudioSourceDevices()[0]
145
self.__changeSelectedAudio(adev)
147
if len(probe.getVideoSourceDevices()):
148
vdev = probe.getVideoSourceDevices()[0]
151
self.__changeSelectedVideo(vdev)
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.displayname, 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()