Merge lp:~bkerensa/ubuntu/raring/kazam/new-upstream into lp:ubuntu/raring/kazam

Proposed by Benjamin Kerensa
Status: Merged
Merge reported by: Charlie_Smotherman
Merged at revision: not available
Proposed branch: lp:~bkerensa/ubuntu/raring/kazam/new-upstream
Merge into: lp:ubuntu/raring/kazam
Diff against target: 61072 lines (+48637/-8979)
195 files modified
AUTHORS (+4/-0)
NEWS (+36/-0)
README (+62/-37)
TODO (+11/-5)
bin/kazam (+83/-16)
build/lib.linux-x86_64-2.7/kazam/__init__.py (+1/-0)
build/lib.linux-x86_64-2.7/kazam/app.py (+748/-0)
build/lib.linux-x86_64-2.7/kazam/backend/__init__.py (+1/-0)
build/lib.linux-x86_64-2.7/kazam/backend/config.py (+128/-0)
build/lib.linux-x86_64-2.7/kazam/backend/constants.py (+152/-0)
build/lib.linux-x86_64-2.7/kazam/backend/export.py (+194/-0)
build/lib.linux-x86_64-2.7/kazam/backend/ffmpeg.py (+132/-0)
build/lib.linux-x86_64-2.7/kazam/backend/grabber.py (+166/-0)
build/lib.linux-x86_64-2.7/kazam/backend/gstreamer.py (+416/-0)
build/lib.linux-x86_64-2.7/kazam/backend/prefs.py (+232/-0)
build/lib.linux-x86_64-2.7/kazam/frontend/__init__.py (+1/-0)
build/lib.linux-x86_64-2.7/kazam/frontend/about_dialog.py (+70/-0)
build/lib.linux-x86_64-2.7/kazam/frontend/combobox.py (+116/-0)
build/lib.linux-x86_64-2.7/kazam/frontend/done_recording.py (+159/-0)
build/lib.linux-x86_64-2.7/kazam/frontend/export.py (+269/-0)
build/lib.linux-x86_64-2.7/kazam/frontend/indicator.py (+311/-0)
build/lib.linux-x86_64-2.7/kazam/frontend/main_menu.py (+88/-0)
build/lib.linux-x86_64-2.7/kazam/frontend/preferences.py (+375/-0)
build/lib.linux-x86_64-2.7/kazam/frontend/save_dialog.py (+62/-0)
build/lib.linux-x86_64-2.7/kazam/frontend/widgets.py (+60/-0)
build/lib.linux-x86_64-2.7/kazam/frontend/window_area.py (+202/-0)
build/lib.linux-x86_64-2.7/kazam/frontend/window_countdown.py (+140/-0)
build/lib.linux-x86_64-2.7/kazam/frontend/window_region.py (+200/-0)
build/lib.linux-x86_64-2.7/kazam/frontend/window_select.py (+181/-0)
build/lib.linux-x86_64-2.7/kazam/instant.py (+142/-0)
build/lib.linux-x86_64-2.7/kazam/pulseaudio/__init__.py (+1/-0)
build/lib.linux-x86_64-2.7/kazam/pulseaudio/ctypes_pulseaudio.py (+197/-0)
build/lib.linux-x86_64-2.7/kazam/pulseaudio/error_handling.py (+27/-0)
build/lib.linux-x86_64-2.7/kazam/pulseaudio/pulseaudio.py (+345/-0)
build/lib.linux-x86_64-2.7/kazam/utils.py (+47/-0)
build/lib.linux-x86_64-2.7/kazam/version.py (+5/-0)
build/scripts-2.7/kazam (+144/-0)
build/share/applications/kazam.desktop (+134/-0)
data/icons/dark/all-screens.svg (+81/-0)
data/icons/dark/area.svg (+81/-0)
data/icons/dark/fullscreen.svg (+81/-0)
data/icons/dark/photo.svg (+81/-0)
data/icons/dark/screencast-2-dark.svg (+98/-0)
data/icons/dark/screencast.svg (+81/-0)
data/icons/dark/screenshot-1.svg (+90/-0)
data/icons/dark/screenshot-2.svg (+90/-0)
data/icons/dark/sound.svg (+82/-0)
data/icons/dark/video.svg (+81/-0)
data/icons/dark/window.svg (+81/-0)
data/icons/light/all-screens.svg (+81/-0)
data/icons/light/area.svg (+81/-0)
data/icons/light/fullscreen.svg (+81/-0)
data/icons/light/photo.svg (+81/-0)
data/icons/light/screencast.svg (+81/-0)
data/icons/light/screenshot-1.svg (+90/-0)
data/icons/light/screenshot-2.svg (+90/-0)
data/icons/light/sound.svg (+82/-0)
data/icons/light/video.svg (+81/-0)
data/icons/light/window.svg (+81/-0)
data/ui/kazam.ui (+337/-0)
data/ui/preferences.ui (+607/-0)
debian/changelog (+5/-6)
debian/files (+1/-0)
debian/kazam.debhelper.log (+44/-0)
debian/kazam.postinst.debhelper (+7/-0)
debian/kazam.prerm.debhelper (+12/-0)
debian/kazam.substvars (+3/-0)
debian/kazam/DEBIAN/control (+16/-0)
debian/kazam/DEBIAN/md5sums (+138/-0)
debian/kazam/DEBIAN/postinst (+9/-0)
debian/kazam/DEBIAN/prerm (+14/-0)
debian/kazam/usr/bin/kazam (+144/-0)
debian/kazam/usr/share/applications/kazam.desktop (+134/-0)
debian/kazam/usr/share/doc/kazam/TODO (+14/-0)
debian/kazam/usr/share/doc/kazam/copyright (+36/-0)
debian/kazam/usr/share/kazam/icons/128.svg (+2059/-0)
debian/kazam/usr/share/kazam/icons/16.svg (+1568/-0)
debian/kazam/usr/share/kazam/icons/22.svg (+1500/-0)
debian/kazam/usr/share/kazam/icons/24.svg (+1557/-0)
debian/kazam/usr/share/kazam/icons/300.svg (+4801/-0)
debian/kazam/usr/share/kazam/icons/32.svg (+1567/-0)
debian/kazam/usr/share/kazam/icons/48.svg (+1560/-0)
debian/kazam/usr/share/kazam/icons/96.svg (+1878/-0)
debian/kazam/usr/share/kazam/icons/text-black.svg (+75/-0)
debian/kazam/usr/share/kazam/icons/text-bling.svg (+904/-0)
debian/kazam/usr/share/kazam/icons/text-white.svg (+65/-0)
debian/kazam/usr/share/kazam/ui/authenticate.ui (+234/-0)
debian/kazam/usr/share/kazam/ui/done-recording.ui (+190/-0)
debian/kazam/usr/share/kazam/ui/export.ui (+344/-0)
debian/kazam/usr/share/kazam/ui/kazam.ui (+337/-0)
debian/kazam/usr/share/kazam/ui/preferences.ui (+607/-0)
debian/kazam/usr/share/kazam/ui/start.ui (+178/-0)
debian/kazam/usr/share/pyshared/kazam-1.3.99_0ubuntu1.egg-info (+171/-0)
debian/kazam/usr/share/pyshared/kazam/__init__.py (+1/-0)
debian/kazam/usr/share/pyshared/kazam/app.py (+748/-0)
debian/kazam/usr/share/pyshared/kazam/backend/__init__.py (+1/-0)
debian/kazam/usr/share/pyshared/kazam/backend/config.py (+128/-0)
debian/kazam/usr/share/pyshared/kazam/backend/constants.py (+152/-0)
debian/kazam/usr/share/pyshared/kazam/backend/export.py (+194/-0)
debian/kazam/usr/share/pyshared/kazam/backend/ffmpeg.py (+132/-0)
debian/kazam/usr/share/pyshared/kazam/backend/grabber.py (+166/-0)
debian/kazam/usr/share/pyshared/kazam/backend/gstreamer.py (+416/-0)
debian/kazam/usr/share/pyshared/kazam/backend/prefs.py (+232/-0)
debian/kazam/usr/share/pyshared/kazam/frontend/__init__.py (+1/-0)
debian/kazam/usr/share/pyshared/kazam/frontend/about_dialog.py (+70/-0)
debian/kazam/usr/share/pyshared/kazam/frontend/combobox.py (+116/-0)
debian/kazam/usr/share/pyshared/kazam/frontend/done_recording.py (+159/-0)
debian/kazam/usr/share/pyshared/kazam/frontend/export.py (+269/-0)
debian/kazam/usr/share/pyshared/kazam/frontend/indicator.py (+311/-0)
debian/kazam/usr/share/pyshared/kazam/frontend/main_menu.py (+88/-0)
debian/kazam/usr/share/pyshared/kazam/frontend/preferences.py (+375/-0)
debian/kazam/usr/share/pyshared/kazam/frontend/save_dialog.py (+62/-0)
debian/kazam/usr/share/pyshared/kazam/frontend/widgets.py (+60/-0)
debian/kazam/usr/share/pyshared/kazam/frontend/window_area.py (+202/-0)
debian/kazam/usr/share/pyshared/kazam/frontend/window_countdown.py (+140/-0)
debian/kazam/usr/share/pyshared/kazam/frontend/window_region.py (+200/-0)
debian/kazam/usr/share/pyshared/kazam/frontend/window_select.py (+181/-0)
debian/kazam/usr/share/pyshared/kazam/instant.py (+142/-0)
debian/kazam/usr/share/pyshared/kazam/pulseaudio/__init__.py (+1/-0)
debian/kazam/usr/share/pyshared/kazam/pulseaudio/ctypes_pulseaudio.py (+197/-0)
debian/kazam/usr/share/pyshared/kazam/pulseaudio/error_handling.py (+27/-0)
debian/kazam/usr/share/pyshared/kazam/pulseaudio/pulseaudio.py (+345/-0)
debian/kazam/usr/share/pyshared/kazam/utils.py (+47/-0)
debian/kazam/usr/share/pyshared/kazam/version.py (+5/-0)
kazam/app.py (+621/-567)
kazam/backend/config.py (+29/-12)
kazam/backend/constants.py (+96/-3)
kazam/backend/grabber.py (+166/-0)
kazam/backend/gstreamer.py (+274/-219)
kazam/backend/prefs.py (+232/-0)
kazam/frontend/combobox.py (+20/-7)
kazam/frontend/done_recording.py (+8/-8)
kazam/frontend/indicator.py (+184/-56)
kazam/frontend/main_menu.py (+11/-0)
kazam/frontend/preferences.py (+375/-0)
kazam/frontend/save_dialog.py (+15/-34)
kazam/frontend/widgets.py (+60/-0)
kazam/frontend/window_area.py (+202/-0)
kazam/frontend/window_countdown.py (+29/-15)
kazam/frontend/window_select.py (+181/-0)
kazam/instant.py (+142/-0)
kazam/pulseaudio/ctypes_pulseaudio.py (+4/-4)
kazam/pulseaudio/pulseaudio.py (+40/-28)
kazam/tests/__init__.py (+1/-0)
kazam/tests/test_app.py (+53/-0)
kazam/utils.py (+14/-0)
kazam/version.py (+4/-3)
po/POTFILES.in (+12/-7)
po/ar.po (+290/-226)
po/bg.po (+274/-210)
po/bn.po (+241/-212)
po/ca.po (+278/-214)
po/cs.po (+285/-219)
po/da.po (+287/-0)
po/de.po (+280/-217)
po/el.po (+243/-211)
po/en_AU.po (+285/-0)
po/en_CA.po (+253/-221)
po/en_GB.po (+255/-221)
po/eo.po (+198/-212)
po/es.po (+281/-216)
po/eu.po (+266/-0)
po/fi.po (+271/-213)
po/fo.po (+252/-0)
po/fr.po (+287/-222)
po/gl.po (+247/-215)
po/hr.po (+317/-0)
po/hu.po (+286/-222)
po/id.po (+249/-218)
po/is.po (+241/-212)
po/it.po (+278/-216)
po/kazam.pot (+239/-178)
po/ko.po (+239/-0)
po/lt.po (+285/-0)
po/lv.po (+286/-222)
po/ml.po (+221/-217)
po/ms.po (+254/-220)
po/nl.po (+290/-226)
po/oc.po (+239/-0)
po/pl.po (+271/-216)
po/pt.po (+245/-213)
po/pt_BR.po (+280/-214)
po/pt_PT.po (+210/-211)
po/ro.po (+284/-221)
po/ru.po (+282/-218)
po/sk.po (+245/-213)
po/sl.po (+274/-210)
po/sr.po (+228/-222)
po/sv.po (+247/-213)
po/te.po (+317/-0)
po/tr.po (+284/-220)
po/uk.po (+288/-222)
po/zh_CN.po (+286/-222)
po/zh_TW.po (+236/-169)
setup.py (+8/-8)
To merge this branch: bzr merge lp:~bkerensa/ubuntu/raring/kazam/new-upstream
Reviewer Review Type Date Requested Status
Charlie_Smotherman (community) Needs Fixing
Ubuntu branches Pending
Review via email: mp+134426@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Charlie_Smotherman (cjsmo) wrote :

bzr branch lp:ubuntu/kazam
...
bzr merge lp:~bkerensa/ubuntu/raring/kazam/new-upstream
...
bzr builddeb -S -- -sa -us -uc
Building using working tree
Building package in normal mode
Looking for a way to retrieve the upstream tarball
Using apt to look for the upstream tarball.
apt could not find the needed tarball.
Trying to use get-packaged-orig-source to retrieve needed tarball.
dh --with python2 get-packaged-orig-source
dh: Unknown sequence get-packaged-orig-source (choose from: binary binary-arch binary-indep build build-arch build-indep clean install install-arch install-indep)
make: *** [get-packaged-orig-source] Error 255
Trying to run get-packaged-orig-source rule failed
Trying to use get-orig-source to retrieve needed tarball (deprecated).
dh --with python2 get-orig-source
dh: Unknown sequence get-orig-source (choose from: binary binary-arch binary-indep build build-arch build-indep clean install install-arch install-indep)
make: *** [get-orig-source] Error 255
Trying to run get-orig-source rule failed
Using uscan to look for the upstream tarball.
uscan warning: In /tmp/tmprFZq6l no matching hrefs for version 1.3.1 in watch line
  http://launchpad.net/kazam/+download .*/kazam-([0-9.]+)\.tar\.gz
uscan could not find the needed tarball.
bzr: ERROR: Unable to find the needed upstream tarball for package kazam, version 1.3.1.

Please fix debian/watch :)

review: Needs Fixing
Revision history for this message
Bryce Harrington (bryce) wrote :

Set status back to Needs Review once the requested fix is made.

Revision history for this message
Benjamin Kerensa (bkerensa) wrote :

> Set status back to Needs Review once the requested fix is made.

Any advice on a fix... I am not too familiar with watch file formats so I'm not sure where to begin to fix this but I definately want to fix it and get this into quantal.

Thanks

Revision history for this message
Charlie_Smotherman (cjsmo) wrote :

Had to make some additional changes to the packaging so I went ahead and fixed the watchfile while I was there :) Uploaded to raring. If you would like to get kazam 1.3.4 into quantal please have a look at

https://wiki.ubuntu.com/StableReleaseUpdates
https://wiki.ubuntu.com/UbuntuBackports

Thank you for your contribution to Ubuntu

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'AUTHORS'
2--- AUTHORS 2012-02-09 21:56:49 +0000
3+++ AUTHORS 2012-11-15 10:17:01 +0000
4@@ -9,4 +9,8 @@
5 K.Vishnoo Charan Reddy - Artwork, Bughelp, Design
6 Gary Lasker - Coding
7 David Klasinc - Coding
8+Georgi Karavasilev - Design, Testing
9+Alan Pope - Testing
10+Mattew Paul Thomas - Design, Testing
11+Ken VanDine - Packaging
12
13
14=== added file 'NEWS'
15--- NEWS 1970-01-01 00:00:00 +0000
16+++ NEWS 2012-11-15 10:17:01 +0000
17@@ -0,0 +1,36 @@
18+Kazam 1.3.4 - NCC-2893 (Stargazer Edition)
19+
20+- Instant mode, to capture screenshots from command line, use
21+ the following switches:
22+ -f / --fullscreen capture full screen
23+ -w / --window capture currently active window
24+ -a / --area capture a preselected screen area
25+ -g / --godmode disable sounds, use automatic file saving and
26+ capture full screen & active window at the same
27+ time
28+
29+- New area and window selection screens.
30+- Unity Launcher quicklist added.
31+
32+Kazam 1.3.1 - NCC-2893 (Stargazer Edition)
33+------------------------------------------
34+
35+- GStreamer 1.0 support, Kazam will no longer work with older versions
36+ of GStreamer. This includes 0.11 (1.0 alpha/beta/rc) version. Some
37+ encoders were changed in transition from beta to final release which
38+ messed up a lot of things.
39+
40+- Completely new GUI. Designed by https://launchpad.net/~kokoto-java with
41+ the omnipresent guiding hand of https://launchpad.net/~mpt
42+
43+- Support for taking still screen captures, also known as screenshots.
44+
45+- Support for automatic file saving. You can set the prefix filename
46+ separately for screenshots and screencasts.
47+
48+- Support for selecting a single window to screencast. Screenshots are
49+ still limited to full screen and/or area selection.
50+
51+- Theme-able shutter sounds. Right now you can choose between Canon 7D
52+ and Nikon D80. ;)
53+
54
55=== modified file 'README'
56--- README 2012-04-25 16:49:23 +0000
57+++ README 2012-11-15 10:17:01 +0000
58@@ -1,5 +1,5 @@
59
60- Kazam Screencaster v1.0.6 "NCC-1701D"
61+ Kazam Screencaster v1.3.1 "NCC-2893"
62
63
64 Introduction
65@@ -18,15 +18,25 @@
66
67 Kazam is always available from Launchpad under https://launchpad.net/kazam
68
69-Right now there are only unstable versions available, the project is still
70-in development and a stable release is planned for Ubuntu 12.04.
71-
72-
73-Installation
74-------------
75-
76-For Ubuntu, the best way to install is to add a PPA repository and then
77-use apt-get command or Software Centre.
78+Latest stable release is 1.0.6.
79+Latest unstable release is 1.3.1 - Stargazer edition
80+
81+
82+Installation - stable release
83+-----------------------------
84+
85+If you are using Ubuntu 12.04 or 12.10 then stable version (1.0.x)
86+is available from universe repository. You can find it in Ubuntu Softare
87+Center or install it from the terminal with the following command:
88+
89+$ sudo apt-get install kazam
90+
91+For Ubuntu 11.10 - Oneiric Ocelot, the best way to install Kazam is to add
92+a PPA repository and then use apt-get command or Software Centre.
93+
94+$ sudo add-apt-repository ppa:kazam-team/stable-series
95+$ sudo apt-get update
96+$ sudo apt-get install kazam
97
98 For distribution independent installation you will have to get the latest
99 tarball release from Launchpad:
100@@ -43,6 +53,9 @@
101 # python setup.py install
102
103
104+Installation - development version
105+----------------------------------
106+
107 If you want bleeding edge, development version then you will have to get
108 source code from Launchpad by running the following command:
109
110@@ -57,6 +70,39 @@
111 path is /usr/local.
112
113
114+Running Kazam
115+-------------
116+
117+If you want to run Kazam from the source tree, there are a few limitations
118+that you have to take into account. Right now Ubuntu App indicator will not
119+allow setting custom icons. Every icon has to be taken from currently
120+installed icon theme. See https://bugs.launchpad.net/kazam/+bug/657857 for
121+more information.
122+
123+To run Kazam simply execute te following commands in the source tree:
124+
125+$ cd bin
126+$ ./kazam
127+
128+If you already have Kazam installed then Kazam icon will show in the
129+indicator, if not, the only way to get to the menu is to click on one
130+of the icons in the indicator and then move around with the cursor keys.
131+
132+Keyboard shortcuts
133+------------------
134+
135+If you have keybinder3.0 from the unstable PPA installed, then you can
136+use these keyboard shortcuts for controlling Kazam:
137+
138+SUPER-CTRL-Q - Quit
139+SUPER-CTRL-W - Show/Hide main window
140+SUPER-CTRL-R - Start Recording
141+SUPER-CTRL-F - Finish Recording
142+
143+Keyboard shortcuts will work if you installed Kazam 1.3.1 from a PPA,
144+keybinder 3.0 is now a dependency and will be installed automatically.
145+
146+
147 Known Issues
148 ------------
149
150@@ -67,30 +113,14 @@
151 - Placing Region selector outside of screen borders will produce unknown
152 results and you will probably end up with no video.
153
154-- Two warnings appear during the normal usage:
155-
156-/usr/lib/python2.7/dist-packages/gobject/constants.py:24: Warning:
157-g_boxed_type_register_static: assertion `g_type_from_name (name) == 0' failed
158-
159-This happens when Gtk.GObject was imported before importing gst in python
160-and is still being investigated. So far it appears to be mostly harmless.
161-
162-Second warning comes from Gtk.FileChooser():
163-
164-kazam:5144): Gtk-WARNING **: Unable to retrieve the file info for <file>
165-Error stating file <file> : No such file or directory
166-
167-This happens when you confirm file save in the dialog box. This is an error
168-in Gtk.FileChooser and in Precise Pangolin it is fixed.
169-
170 - Trouble with recording from certain Monitor sources. I noticed this with
171 Logitech G110 USB Keyboard that can play audio. Pulse Audio will see two
172 devices: USP PnP Stereo Device and Monitor of USB PnP Stereo Device. When
173 recording from the monitor, volume controls for both devices will affect
174 the volume in the final recording.
175
176-- I have no idea where to put Mute/Unmute button, so you'll have to check
177-that in pavucontrol or sound settings. :)
178+- I have no idea where to put Mute/Unmute button, so right now every audio
179+source you select is automatically unmuted.
180
181 - It was reported that sound is disappearing after couple of minutes into
182 the recording. I wasn't able to reproduce this bug and any more info is
183@@ -100,10 +130,9 @@
184 Recording Tips
185 --------------
186
187-Framerates above 20fps are unlikely to work because of software and hardware
188-limitations. If you increase framerate and in resulting video
189-framerate actually drops, that is because encoder can't keep up with
190-the framerate.
191+Framerates above 20fps are unlikely to work well because of software and
192+hardware limitations. If you increase framerate and framerate in
193+resulting video drops, that is because encoder can't keep up.
194
195 Always do a sound check. Especially if you are recording a live commentary
196 with background sound. I got the best results when I used earphones to listen
197@@ -117,9 +146,5 @@
198 If you encounter a bug or any kind of unexpected behavior please try to
199 reproduce it while you run Kazam from standard terminal with --debug option.
200 Use Launchpad to report bugs (https://bugs.launchpad.net/kazam/+filebug) and
201-include generated output. It will also be helpful if you can attach generated
202-'dot' file. You will find this file in /tmp/kazam_debug.dot.
203-
204-If you have graphviz package installed there is also /tmp/kazam_pipeline.png
205-file and you can inspect GStreamer pipeline if everything checks out ok.
206+include generated output.
207
208
209=== modified file 'TODO'
210--- TODO 2012-02-29 20:43:50 +0000
211+++ TODO 2012-11-15 10:17:01 +0000
212@@ -1,8 +1,14 @@
213 TODO
214 ----
215-Short term:
216- - Make a list of new features
217-
218-Long(er) term:
219- - Implement new features ;)
220+
221+Whishlist (by BigWhale) and reasons why is something still on a whishlist
222+
223+- Frame marking the capture area while recording is in progress
224+ A transparent window with no input mask is required on screen. However,
225+ for that to work, Gdk.cairo_region_create_from_surface() is required. For
226+ some reason, this fuction still isn't introspected. See:
227+
228+ http://askubuntu.com/questions/97789/creating-a-gtk-window-with-input-shape-mask-in-python
229+
230+ (This is still an issue ... :'( )
231
232
233=== modified file 'bin/kazam'
234--- bin/kazam 2012-02-29 20:43:50 +0000
235+++ bin/kazam 2012-11-15 10:17:01 +0000
236@@ -30,25 +30,36 @@
237
238 if __name__ == "__main__":
239
240- log = logging.getLogger()
241- log.name = "Kazam"
242+ logger = logging.getLogger()
243+ logger.name = "Kazam"
244 handler = logging.StreamHandler()
245- formatter = logging.Formatter('%(levelname)s %(name)-10s - %(message)s')
246+ formatter = logging.Formatter('%(levelname)s %(name)s - %(message)s')
247 handler.setFormatter(formatter)
248- log.addHandler(handler)
249+ logger.addHandler(handler)
250+ logger.setLevel(logging.INFO)
251
252- log.info("Logger intialized.")
253+ logger.info("Logger intialized.")
254
255 if os.path.exists("../data"):
256- log.info("Running locally, AppIndicator icons might be missing.")
257+ logger.info("Running locally, AppIndicator icons might be missing.")
258 datadir = "../data"
259 sys.path.insert(0, "..")
260 else:
261 # A bit more flexible setting of datadir, it works
262 # when base install path is not /usr
263 curpath = os.path.abspath(__file__)
264+ curpath = os.path.realpath(curpath)
265 datadir = curpath.split('bin/')[0] + "share/kazam/"
266
267+ try:
268+ import platform
269+ dist = platform.linux_distribution()
270+ logger.info("Running on: {0} {1}".format(dist[0], dist[1]))
271+ except:
272+ # Fallback to the almighty Ubuntu 12.10 ;)
273+ dist = ('Ubuntu', '12.10', 'quantal')
274+ logger.warning("Failed to correctly detect operating system.")
275+
276 from kazam.version import *
277 version = "%(prog)s {0} '{1}'".format(VERSION, CODENAME)
278 parser = ArgumentParser(description = "Screen recording program.")
279@@ -62,16 +73,72 @@
280 action = "version",
281 version = version)
282
283+ parser.add_argument("-t", "--test",
284+ action = "store_true",
285+ help = "generate test video signal",
286+ default = False)
287+
288+ parser.add_argument("-n", "--nosound",
289+ action = "store_true",
290+ help = "disable PulseAudio",
291+ default = False)
292+
293+ parser.add_argument("-s", "--silent",
294+ action = "store_true",
295+ help = "silent start",
296+ default = False)
297+
298+ parser.add_argument("-f", "--fullscreen",
299+ action = "store_true",
300+ help = "instant screenshot of full screen",
301+ default = False)
302+
303+ parser.add_argument("-a", "--area",
304+ action = "store_true",
305+ help = "instant screenshot of preselected screen area",
306+ default = False)
307+
308+ parser.add_argument("-w", "--window",
309+ action = "store_true",
310+ help = "instant screenshot of active window",
311+ default = False)
312+
313+ parser.add_argument("-p", "--preferences",
314+ action = "store_true",
315+ help = "show preferences window",
316+ default = False)
317+
318+ parser.add_argument("-g", "--godmode",
319+ action = "store_true",
320+ help = "god mode of capture",
321+ default = False)
322+
323 args = parser.parse_args()
324 if args.debug:
325- log.setLevel(logging.DEBUG)
326- else:
327- log.setLevel(logging.INFO)
328-
329- from kazam.app import KazamApp
330-
331- log.debug("Starting ...")
332- appWindow = KazamApp(datadir, args.debug)
333- appWindow.show_all()
334+ logger.setLevel(logging.DEBUG)
335+ else:
336+ logger.setLevel(logging.INFO)
337+
338+ logger.debug("Starting ...")
339+
340+ if args.fullscreen:
341+ from kazam.instant import InstantApp
342+ app = InstantApp(datadir, dist, args.debug, 1) # MODE_ALL
343+ elif args.area:
344+ from kazam.instant import InstantApp
345+ app = InstantApp(datadir, dist, args.debug, 2) # MODE_AREA
346+ elif args.window:
347+ from kazam.instant import InstantApp
348+ app = InstantApp(datadir, dist, args.debug, 4) # MODE_ACTIVE
349+ elif args.godmode:
350+ from kazam.instant import InstantApp
351+ app = InstantApp(datadir, dist, args.debug, 666) # MODE_ACTIVE
352+ elif args.preferences:
353+ from kazam.instant import InstantApp
354+ app = InstantApp(datadir, dist, args.debug, 0, preferences=True)
355+ else:
356+ from kazam.app import KazamApp
357+ appWindow = KazamApp(datadir, dist, args.debug, args.test, args.nosound, args.silent)
358+
359 Gtk.main()
360- log.debug("Finishing ...")
361+ logger.debug("Finishing ...")
362
363=== added directory 'build'
364=== added directory 'build/lib.linux-x86_64-2.7'
365=== added directory 'build/lib.linux-x86_64-2.7/kazam'
366=== added file 'build/lib.linux-x86_64-2.7/kazam/__init__.py'
367--- build/lib.linux-x86_64-2.7/kazam/__init__.py 1970-01-01 00:00:00 +0000
368+++ build/lib.linux-x86_64-2.7/kazam/__init__.py 2012-11-15 10:17:01 +0000
369@@ -0,0 +1,1 @@
370+
371
372=== added file 'build/lib.linux-x86_64-2.7/kazam/app.py'
373--- build/lib.linux-x86_64-2.7/kazam/app.py 1970-01-01 00:00:00 +0000
374+++ build/lib.linux-x86_64-2.7/kazam/app.py 2012-11-15 10:17:01 +0000
375@@ -0,0 +1,748 @@
376+# -*- coding: utf-8 -*-
377+#
378+# app.py
379+#
380+# Copyright 2012 David Klasinc <bigwhale@lubica.net>
381+# Copyright 2010 Andrew <andrew@karmic-desktop>
382+#
383+# This program is free software; you can redistribute it and/or modify
384+# it under the terms of the GNU General Public License as published by
385+# the Free Software Foundation; either version 3 of the License, or
386+# (at your option) any later version.
387+#
388+# This program is distributed in the hope that it will be useful,
389+# but WITHOUT ANY WARRANTY; without even the implied warranty of
390+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
391+# GNU General Public License for more details.
392+#
393+# You should have received a copy of the GNU General Public License
394+# along with this program; if not, write to the Free Software
395+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
396+# MA 02110-1301, USA.
397+
398+import os
399+import sys
400+import locale
401+import shutil
402+import gettext
403+import logging
404+
405+from subprocess import Popen
406+from gi.repository import Gtk, Gdk, GObject
407+from gettext import gettext as _
408+
409+from kazam.utils import *
410+from kazam.backend.prefs import *
411+from kazam.backend.constants import *
412+from kazam.backend.grabber import Grabber
413+from kazam.frontend.main_menu import MainMenu
414+from kazam.frontend.window_area import AreaWindow
415+from kazam.backend.gstreamer import Screencast
416+from kazam.frontend.preferences import Preferences
417+from kazam.frontend.about_dialog import AboutDialog
418+from kazam.frontend.indicator import KazamIndicator
419+from kazam.frontend.window_select import SelectWindow
420+from kazam.frontend.done_recording import DoneRecording
421+from kazam.frontend.window_countdown import CountdownWindow
422+
423+logger = logging.getLogger("Main")
424+
425+#
426+# Detect GStreamer version and bail out if lower than 1.0 and no GI
427+#
428+try:
429+ from gi.repository import Gst
430+ gst_gi = Gst.version()
431+ if not gst_gi[0]:
432+ logger.critical("Gstreamer 1.0 or higher requred, bailing out.")
433+ gst_gi = None
434+ sys.exit(0)
435+ else:
436+ logger.debug("Gstreamer version detected: {0}.{1}.{2}.{3}".format(gst_gi[0],
437+ gst_gi[1],
438+ gst_gi[2],
439+ gst_gi[3]))
440+except ImportError:
441+ logger.critical("Gstreamer 1.0 or higher requred, bailing out.")
442+ sys.exit(0)
443+
444+class KazamApp(GObject.GObject):
445+
446+ def __init__(self, datadir, dist, debug, test, sound, silent):
447+ GObject.GObject.__init__(self)
448+ logger.debug("Setting variables.")
449+
450+ prefs.datadir = datadir
451+ prefs.get_sound_files()
452+
453+ self.startup = True
454+ prefs.debug = debug
455+ prefs.test = test
456+ prefs.dist = dist
457+ prefs.silent = silent
458+ prefs.sound = not sound # Parameter is called nosound and if true, then we don't have sound.
459+ # Tricky parameters are tricky!
460+
461+ self.setup_translations()
462+
463+ if prefs.sound:
464+ try:
465+ from kazam.pulseaudio.pulseaudio import pulseaudio_q
466+ prefs.sound = True
467+ except:
468+ logger.warning("Pulse Audio Failed to load. Sound recording disabled.")
469+ prefs.sound = False
470+
471+ self.icons = Gtk.IconTheme.get_default()
472+ self.icons.append_search_path(os.path.join(prefs.datadir,"icons", "48x48", "apps"))
473+ self.icons.append_search_path(os.path.join(prefs.datadir,"icons", "16x16", "apps"))
474+
475+ try:
476+ from gi.repository import Unity, Dbusmenu
477+ launcher = Unity.LauncherEntry.get_for_desktop_id("kazam.desktop")
478+ ql = Dbusmenu.Menuitem.new()
479+ ql_item1 = Dbusmenu.Menuitem.new()
480+ ql_item1.property_set(Dbusmenu.MENUITEM_PROP_LABEL, _("Record screencast"))
481+ ql_item1.property_set_bool(Dbusmenu.MENUITEM_PROP_VISIBLE, True)
482+ ql_item1.connect("item-activated", self.cb_ql_screencast)
483+ ql.child_append(ql_item1)
484+ ql_item2 = Dbusmenu.Menuitem.new()
485+ ql_item2.property_set(Dbusmenu.MENUITEM_PROP_LABEL, _("Take screenshot"))
486+ ql_item2.property_set_bool(Dbusmenu.MENUITEM_PROP_VISIBLE, True)
487+ ql_item2.connect("item-activated", self.cb_ql_screenshot)
488+ ql.child_append(ql_item2)
489+ ql_item3 = Dbusmenu.Menuitem.new()
490+ ql_item3.property_set(Dbusmenu.MENUITEM_PROP_LABEL, _("Preferences"))
491+ ql_item3.property_set_bool(Dbusmenu.MENUITEM_PROP_VISIBLE, True)
492+ ql_item3.connect("item-activated", self.cb_ql_preferences)
493+ ql.child_append(ql_item3)
494+ launcher.set_property("quicklist", ql)
495+ except ImportError:
496+ logger.warning("Unity and Dbusmenu not found. Skipping launcher integration.")
497+
498+ # Initialize all the variables
499+
500+ self.main_x = 0
501+ self.main_y = 0
502+ self.countdown = None
503+ self.tempfile = ""
504+ self.recorder = None
505+ self.area_window = None
506+ self.old_vid_path = None
507+ self.old_pic_path = None
508+ self.in_countdown = False
509+ self.recording_paused = False
510+ self.recording = False
511+ self.main_mode = 0
512+ self.record_mode = 0
513+ self.last_mode = None
514+
515+ if prefs.sound:
516+ prefs.pa_q = pulseaudio_q()
517+ prefs.pa_q.start()
518+
519+ self.mainmenu = MainMenu()
520+
521+ logger.debug("Connecting indicator signals.")
522+ logger.debug("Starting in silent mode: {0}".format(prefs.silent))
523+ self.indicator = KazamIndicator(prefs.silent)
524+ self.indicator.connect("indicator-quit-request", self.cb_quit_request)
525+ self.indicator.connect("indicator-show-request", self.cb_show_request)
526+ self.indicator.connect("indicator-start-request", self.cb_start_request)
527+ self.indicator.connect("indicator-stop-request", self.cb_stop_request)
528+ self.indicator.connect("indicator-pause-request", self.cb_pause_request)
529+ self.indicator.connect("indicator-unpause-request", self.cb_unpause_request)
530+ self.indicator.connect("indicator-about-request", self.cb_about_request)
531+
532+ self.mainmenu.connect("file-quit", self.cb_quit_request)
533+ self.mainmenu.connect("file-preferences", self.cb_preferences_request)
534+ self.mainmenu.connect("help-about", self.cb_help_about)
535+
536+ #
537+ # Setup UI
538+ #
539+ logger.debug("Main Window UI setup.")
540+
541+ self.builder = Gtk.Builder()
542+ self.builder.add_from_file(os.path.join(prefs.datadir, "ui", "kazam.ui"))
543+ self.builder.connect_signals(self)
544+ for w in self.builder.get_objects():
545+ if issubclass(type(w), Gtk.Buildable):
546+ name = Gtk.Buildable.get_name(w)
547+ setattr(self, name, w)
548+ else:
549+ logger.debug("Unable to get name for '%s'" % w)
550+
551+ # Main Menu
552+ self.MainGrid.attach(self.mainmenu.menubar, 0, 0, 1, 1)
553+
554+ self.context = self.toolbar_main.get_style_context()
555+ self.context.add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR)
556+
557+ self.btn_cast = Gtk.RadioToolButton(group=None)
558+ self.btn_cast.set_label(_("Screencast"))
559+ self.btn_cast.set_tooltip_text(_("Record a video of your desktop."))
560+ img1 = Gtk.Image.new_from_file(os.path.join(prefs.datadir, "icons", "light", "screencast.png"))
561+ self.btn_cast.set_icon_widget(img1)
562+ self.btn_cast.set_active(True)
563+ self.btn_cast.set_name("MAIN_SCREENCAST")
564+ self.btn_cast.connect("toggled", self.cb_main_toggled)
565+
566+ self.btn_shot = Gtk.RadioToolButton(group=self.btn_cast)
567+ self.btn_shot.set_label(_("Screenshot"))
568+ self.btn_shot.set_tooltip_text(_("Record a picture of your desktop."))
569+ img2 = Gtk.Image.new_from_file(os.path.join(prefs.datadir, "icons", "light", "screenshot-1.png"))
570+ self.btn_shot.set_icon_widget(img2)
571+ self.btn_shot.set_name("MAIN_SCREENSHOT")
572+ self.btn_shot.connect("toggled", self.cb_main_toggled)
573+
574+ self.sep_1 = Gtk.SeparatorToolItem()
575+ self.sep_1.set_draw(False)
576+ self.sep_1.set_expand(True)
577+ self.toolbar_main.insert(self.sep_1, -1)
578+ self.toolbar_main.insert(self.btn_cast, -1)
579+ self.toolbar_main.insert(self.btn_shot, -1)
580+ self.toolbar_main.insert(self.sep_1, -1)
581+
582+ # Auxiliary toolbar
583+ self.btn_full = Gtk.RadioToolButton(group=None)
584+ self.btn_full.set_label(_("Fullscreen"))
585+ self.btn_full.set_tooltip_text(_("Capture contents of the current screen."))
586+ img3 = Gtk.Image.new_from_file(os.path.join(prefs.datadir, "icons", "dark", "fullscreen.png"))
587+ self.btn_full.set_icon_widget(img3)
588+ self.btn_full.set_active(True)
589+ self.btn_full.set_name("MODE_FULL")
590+ self.btn_full.connect("toggled", self.cb_record_mode_toggled)
591+
592+ self.btn_allscreens = Gtk.RadioToolButton(group=self.btn_full)
593+ self.btn_allscreens.set_label(_("All Screens"))
594+ self.btn_allscreens.set_tooltip_text(_("Capture contents of all of your screens."))
595+ img4 = Gtk.Image.new_from_file(os.path.join(prefs.datadir, "icons", "dark", "all-screens.png"))
596+ self.btn_allscreens.set_icon_widget(img4)
597+ self.btn_allscreens.set_name("MODE_ALL")
598+ self.btn_allscreens.connect("toggled", self.cb_record_mode_toggled)
599+
600+ self.btn_window = Gtk.RadioToolButton(group=self.btn_full)
601+ self.btn_window.set_label(_("Window"))
602+ self.btn_window.set_tooltip_text(_("Capture contents of a single window."))
603+ img5 = Gtk.Image.new_from_file(os.path.join(prefs.datadir, "icons", "dark", "window.png"))
604+ self.btn_window.set_icon_widget(img5)
605+ self.btn_window.set_name("MODE_WIN")
606+ self.btn_window.connect("toggled", self.cb_record_mode_toggled)
607+ self.btn_window.connect("clicked", self.cb_record_window_clicked)
608+
609+ self.btn_area = Gtk.RadioToolButton(group=self.btn_full)
610+ self.btn_area.set_label(_("Area"))
611+ self.btn_area.set_tooltip_text(_("Capture a pre-selected area of your screen."))
612+ img6 = Gtk.Image.new_from_file(os.path.join(prefs.datadir, "icons", "dark", "area.png"))
613+ self.btn_area.set_icon_widget(img6)
614+ self.btn_area.set_name("MODE_AREA")
615+ self.btn_area.connect("toggled", self.cb_record_mode_toggled)
616+ self.btn_area.connect("clicked", self.cb_record_area_clicked)
617+
618+ self.sep_2 = Gtk.SeparatorToolItem()
619+ self.sep_2.set_draw(False)
620+ self.sep_2.set_expand(True)
621+ #self.toolbar_aux.insert(self.sep_2, -1)
622+ self.toolbar_aux.insert(self.btn_full, -1)
623+ self.toolbar_aux.insert(self.btn_allscreens, -1)
624+ self.toolbar_aux.insert(self.btn_window, -1)
625+ self.toolbar_aux.insert(self.btn_area, -1)
626+ #self.toolbar_aux.insert(self.sep_2, -1)
627+
628+ self.ntb_main.set_current_page(0)
629+
630+ #
631+ # Take care of screen size changes.
632+ #
633+ self.default_screen = Gdk.Screen.get_default()
634+ self.default_screen.connect("size-changed", self.cb_screen_size_changed)
635+ self.window.connect("configure-event", self.cb_configure_event)
636+
637+ # Fetch sources info, take care of all the widgets and saved settings and show main window
638+ if prefs.sound:
639+ prefs.get_audio_sources()
640+
641+ if not prefs.silent:
642+ self.window.show_all()
643+ else:
644+ logger.info("""Starting in silent mode:\n"""
645+ """ SUPER-CTRL-W to toggle main window.\n"""
646+ """ SUPER-CTRL-R to start recording.\n"""
647+ """ SUPER-CTRL-F to finish recording.\n"""
648+ """ SUPER-CTRL-P to pause/resume recording.\n"""
649+ """ SUPER-CTRL-Q to quit.\n"""
650+ )
651+
652+ self.restore_UI()
653+
654+ if not prefs.sound:
655+ self.combobox_audio.set_sensitive(False)
656+ self.combobox_audio2.set_sensitive(False)
657+ self.volumebutton_audio.set_sensitive(False)
658+ self.volumebutton_audio2.set_sensitive(False)
659+
660+ HW.get_current_screen(self.window)
661+ self.startup = False
662+
663+ #
664+ # Callbacks, go down here ...
665+ #
666+
667+ #
668+ # Mode of operation toggles
669+ #
670+
671+ def cb_main_toggled(self, widget):
672+ name = widget.get_name()
673+ if name == "MAIN_SCREENCAST" and widget.get_active():
674+ logger.debug("Main toggled: {0}".format(name))
675+ self.main_mode = MODE_SCREENCAST
676+ self.ntb_main.set_current_page(0)
677+ self.indicator.menuitem_start.set_label(_("Start recording"))
678+
679+ elif name == "MAIN_SCREENSHOT" and widget.get_active():
680+ logger.debug("Main toggled: {0}".format(name))
681+ self.main_mode = MODE_SCREENSHOT
682+ self.ntb_main.set_current_page(1)
683+ if self.record_mode == MODE_WIN:
684+ self.last_mode.set_active(True)
685+ self.indicator.menuitem_start.set_label(_("Take screenshot"))
686+
687+ #
688+ # Record mode toggles
689+ #
690+ def cb_record_mode_toggled(self, widget):
691+ if widget.get_active():
692+ self.current_mode = widget
693+ else:
694+ self.last_mode = widget
695+
696+ if widget.get_name() == "MODE_AREA" and widget.get_active():
697+ logger.debug("Area ON.")
698+ self.area_window = AreaWindow()
699+ self.tmp_sig1 = self.area_window.connect("area-selected", self.cb_area_selected)
700+ self.tmp_sig2 = self.area_window.connect("area-canceled", self.cb_area_canceled)
701+ self.record_mode = MODE_AREA
702+
703+ if widget.get_name() == "MODE_AREA" and not widget.get_active():
704+ logger.debug("Area OFF.")
705+ if self.area_window:
706+ self.area_window.disconnect(self.tmp_sig1)
707+ self.area_window.disconnect(self.tmp_sig2)
708+ self.area_window.window.destroy()
709+ self.area_window = None
710+
711+ if widget.get_name() == "MODE_FULL" and widget.get_active():
712+ logger.debug("Capture full screen.")
713+ self.record_mode = MODE_FULL
714+
715+ if widget.get_name() == "MODE_ALL" and widget.get_active():
716+ logger.debug("Capture all screens.")
717+ self.record_mode = MODE_ALL
718+
719+ if widget.get_name() == "MODE_WIN" and widget.get_active():
720+ logger.debug("Window capture ON.")
721+ self.select_window = SelectWindow()
722+ self.tmp_sig3 = self.select_window.connect("window-selected", self.cb_window_selected)
723+ self.tmp_sig4 = self.select_window.connect("window-canceled", self.cb_window_canceled)
724+ self.record_mode = MODE_WIN
725+
726+ if widget.get_name() == "MODE_WIN" and not widget.get_active():
727+ logger.debug("Window capture OFF.")
728+ if self.select_window:
729+ self.select_window.disconnect(self.tmp_sig3)
730+ self.select_window.disconnect(self.tmp_sig4)
731+ self.select_window.window.destroy()
732+ self.select_window = None
733+
734+
735+ #
736+ # Unity quick list callbacks
737+ #
738+
739+ def cb_ql_screencast(self, menu, data):
740+ logger.debug("Screencast quicklist activated.")
741+ self.btn_cast.set_active(True)
742+ self.run_counter()
743+
744+ def cb_ql_screenshot(self, menu, data):
745+ logger.debug("Screenshot quicklist activated.")
746+ self.btn_shot.set_active(True)
747+ self.run_counter()
748+
749+ def cb_ql_preferences(self, menu, data):
750+ logger.debug("Preferences quicklist activated.")
751+ self.cb_preferences_request(None)
752+
753+ def cb_record_area_clicked(self, widget):
754+ if self.area_window:
755+ logger.debug("Area mode clicked.")
756+ self.area_window.window.show_all()
757+ self.window.set_sensitive(False)
758+
759+ def cb_record_window_clicked(self, widget):
760+ if self.select_window:
761+ logger.debug("Window mode clicked.")
762+ self.select_window.window.show_all()
763+ self.window.set_sensitive(False)
764+
765+ def cb_area_selected(self, widget):
766+ logger.debug("Area selected: SX: {0}, SY: {1}, EX: {2}, EY: {3}".format(
767+ self.area_window.startx,
768+ self.area_window.starty,
769+ self.area_window.endx,
770+ self.area_window.endy))
771+ self.window.set_sensitive(True)
772+ prefs.area = (self.area_window.startx,
773+ self.area_window.starty,
774+ self.area_window.endx,
775+ self.area_window.endy,
776+ self.area_window.width,
777+ self.area_window.height)
778+
779+ def cb_area_canceled(self, widget):
780+ logger.debug("Area selection canceled.")
781+ self.window.set_sensitive(True)
782+ self.last_mode.set_active(True)
783+
784+ def cb_window_selected(self, widget):
785+ prefs.xid = self.select_window.xid
786+ prefs.xid_geometry = self.select_window.geometry
787+ logger.debug("Window selected: {0} - {1}".format(self.select_window.win_name, prefs.xid))
788+ logger.debug("Window geometry: {0}".format(self.select_window.geometry))
789+ self.window.set_sensitive(True)
790+
791+ def cb_window_canceled(self, widget):
792+ logger.debug("Window selection canceled.")
793+ self.window.set_sensitive(True)
794+ self.last_mode.set_active(True)
795+
796+ def cb_screen_size_changed(self, screen):
797+ logger.debug("Screen size changed.")
798+ HW.get_screens()
799+ #
800+ # I combined screen was set to none, turn off the button for all screens
801+ #
802+ if HW.combined_screen:
803+ self.btn_allscreens.set_sensitive(True)
804+ else:
805+ self.btn_allscreens.set_sensitive(False)
806+
807+
808+ def cb_configure_event(self, widget, event):
809+ if event.type == Gdk.EventType.CONFIGURE:
810+ prefs.main_x = event.x
811+ prefs.main_y = event.y
812+
813+ def cb_quit_request(self, indicator):
814+ logger.debug("Quit requested.")
815+ (prefs.main_x, prefs.main_y) = self.window.get_position()
816+ try:
817+ os.remove(self.recorder.tempfile)
818+ os.remove("{0}.mux".format(self.recorder.tempfile))
819+ except OSError:
820+ logger.info("Unable to delete one of the temporary files. Check your temporary directory.")
821+ except AttributeError:
822+ pass
823+
824+ prefs.save_config()
825+
826+ if prefs.sound:
827+ prefs.pa_q.end()
828+
829+ Gtk.main_quit()
830+
831+ def cb_preferences_request(self, indicator):
832+ logger.debug("Preferences requested.")
833+ self.preferences_window = Preferences()
834+ self.preferences_window.open()
835+
836+ def cb_show_request(self, indicator):
837+ if not self.window.get_property("visible"):
838+ logger.debug("Show requested, raising window.")
839+ self.window.show_all()
840+ self.window.present()
841+ self.window.move(prefs.main_x, prefs.main_y)
842+ else:
843+ self.window.hide()
844+
845+ def cb_close_clicked(self, indicator):
846+ (prefs.main_x, prefs.main_y) = self.window.get_position()
847+ self.window.hide()
848+
849+ def cb_about_request(self, activated):
850+ AboutDialog(self.icons)
851+
852+ def cb_delete_event(self, widget, user_data):
853+ self.cb_quit_request(None)
854+
855+ def cb_start_request(self, widget):
856+ logger.debug("Start recording selected.")
857+ self.run_counter()
858+
859+ def cb_record_clicked(self, widget):
860+ logger.debug("Record clicked, invoking Screencast.")
861+ self.run_counter()
862+
863+ def cb_counter_finished(self, widget):
864+ logger.debug("Counter finished.")
865+ self.in_countdown = False
866+ self.countdown = None
867+ self.indicator.blink_set_state(BLINK_STOP)
868+ if self.main_mode == MODE_SCREENCAST:
869+ self.indicator.menuitem_finish.set_label(_("Finish recording"))
870+ self.indicator.menuitem_pause.set_sensitive(True)
871+ self.indicator.start_recording()
872+ self.recorder.start_recording()
873+ elif self.main_mode == MODE_SCREENSHOT:
874+ self.indicator.hide_it()
875+ self.grabber.grab()
876+ self.indicator.show_it()
877+
878+ def cb_stop_request(self, widget):
879+ self.recording = False
880+ if self.in_countdown:
881+ logger.debug("Cancel countdown request.")
882+ self.countdown.cancel_countdown()
883+ self.countdown = None
884+ self.indicator.menuitem_finish.set_label(_("Finish recording"))
885+ self.window.set_sensitive(True)
886+ self.window.show()
887+ self.window.present()
888+ else:
889+ if self.recording_paused:
890+ self.recorder.unpause_recording()
891+ logger.debug("Stop request.")
892+ self.recorder.stop_recording()
893+ self.tempfile = self.recorder.get_tempfile()
894+ logger.debug("Recorded tmp file: {0}".format(self.tempfile))
895+ logger.debug("Waiting for data to flush.")
896+
897+ def cb_flush_done(self, widget):
898+ if self.main_mode == MODE_SCREENCAST and prefs.autosave_video:
899+ logger.debug("Autosaving enabled.")
900+ fname = get_next_filename(prefs.video_dest,
901+ prefs.autosave_video_file,
902+ CODEC_LIST[prefs.codec][3])
903+
904+ shutil.move(self.tempfile, fname)
905+
906+ self.window.set_sensitive(True)
907+ self.window.show()
908+ self.window.present()
909+ elif self.main_mode == MODE_SCREENCAST:
910+ self.done_recording = DoneRecording(self.icons,
911+ self.tempfile,
912+ prefs.codec,
913+ self.old_vid_path)
914+ logger.debug("Done Recording initialized.")
915+ self.done_recording.connect("save-done", self.cb_save_done)
916+ self.done_recording.connect("save-cancel", self.cb_save_cancel)
917+ self.done_recording.connect("edit-request", self.cb_edit_request)
918+ logger.debug("Done recording signals connected.")
919+ self.done_recording.show_all()
920+ self.window.set_sensitive(False)
921+
922+ elif self.main_mode == MODE_SCREENSHOT:
923+ self.grabber.connect("save-done", self.cb_save_done)
924+ self.indicator.recording = False
925+ self.indicator.menuitem_start.set_sensitive(True)
926+ self.indicator.menuitem_pause.set_sensitive(False)
927+ self.indicator.menuitem_pause.set_active(False)
928+ self.indicator.menuitem_finish.set_sensitive(False)
929+ self.indicator.menuitem_show.set_sensitive(True)
930+ self.indicator.menuitem_quit.set_sensitive(True)
931+
932+ if prefs.autosave_picture:
933+ fname = get_next_filename(prefs.picture_dest, prefs.autosave_picture_file, ".png")
934+ self.grabber.autosave(fname)
935+ else:
936+ self.grabber.save_capture(self.old_pic_path)
937+
938+
939+ def cb_pause_request(self, widget):
940+ logger.debug("Pause requested.")
941+ self.recording_paused = True
942+ self.recorder.pause_recording()
943+
944+ def cb_unpause_request(self, widget):
945+ logger.debug("Unpause requested.")
946+ self.recording_paused = False
947+ self.recorder.unpause_recording()
948+
949+ def cb_save_done(self, widget, result):
950+ logger.debug("Save Done, result: {0}".format(result))
951+ if self.main_mode == MODE_SCREENCAST:
952+ self.old_vid_path = result
953+ else:
954+ self.old_pic_path = result
955+
956+ self.window.set_sensitive(True)
957+ self.window.show_all()
958+ self.window.present()
959+ self.window.move(prefs.main_x, prefs.main_y)
960+
961+ def cb_save_cancel(self, widget):
962+ try:
963+ logger.debug("Save canceled, removing {0}".format(self.tempfile))
964+ os.remove(self.tempfile)
965+ except OSError:
966+ logger.info("Failed to remove tempfile {0}".format(self.tempfile))
967+ except AttributeError:
968+ logger.info("Failed to remove tempfile {0}".format(self.tempfile))
969+ pass
970+
971+ self.window.set_sensitive(True)
972+ self.window.show_all()
973+ self.window.present()
974+ self.window.move(prefs.main_x, prefs.main_y)
975+
976+ def cb_help_about(self, widget):
977+ AboutDialog(self.icons)
978+
979+ def cb_edit_request(self, widget, data):
980+ (command, arg_list) = data
981+ arg_list.insert(0, command)
982+ #
983+ # Even if we're not autosaving get the next autosave file and move currently recorded file there
984+ # In case user might lost it.
985+ #
986+ fname = get_next_filename(prefs.video_dest,
987+ prefs.autosave_video_file,
988+ CODEC_LIST[prefs.codec][3])
989+
990+ shutil.move(self.tempfile, fname)
991+ arg_list.append(fname)
992+ logger.debug("Edit request, cmd: {0}".format(arg_list))
993+ try:
994+ Popen(arg_list)
995+ except:
996+ logger.warning("Failed to open selected editor. Have no ")
997+ self.window.set_sensitive(True)
998+ self.window.show_all()
999+
1000+ def cb_check_cursor(self, widget):
1001+ prefs.capture_cursor = widget.get_active()
1002+ logger.debug("Capture cursor: {0}.".format(prefs.capture_cursor))
1003+
1004+ def cb_check_cursor_pic(self, widget):
1005+ prefs.capture_cursor_pic = widget.get_active()
1006+ logger.debug("Capture cursor_pic: {0}.".format(prefs.capture_cursor_pic))
1007+
1008+ def cb_check_borders_pic(self, widget):
1009+ prefs.capture_borders_pic = widget.get_active()
1010+ logger.debug("Capture borders_pic: {0}.".format(prefs.capture_borders_pic))
1011+
1012+ def cb_check_speakers(self, widget):
1013+ prefs.capture_speakers = widget.get_active()
1014+ logger.debug("Capture speakers: {0}.".format(prefs.capture_speakers))
1015+
1016+ def cb_check_microphone(self, widget):
1017+ prefs.capture_microphone = widget.get_active()
1018+ logger.debug("Capture microphone: {0}.".format(prefs.capture_microphone))
1019+
1020+ def cb_spinbutton_delay_change(self, widget):
1021+ prefs.countdown_timer = widget.get_value_as_int()
1022+ logger.debug("Start delay now: {0}".format(prefs.countdown_timer))
1023+
1024+ #
1025+ # Other somewhat useful stuff ...
1026+ #
1027+
1028+ def run_counter(self):
1029+ #
1030+ # Annoyances with the menus
1031+ #
1032+ (main_x, main_y) = self.window.get_position()
1033+ if main_x and main_y:
1034+ prefs.main_x = main_x
1035+ prefs.main_y = main_y
1036+
1037+ self.indicator.recording = True
1038+ self.indicator.menuitem_start.set_sensitive(False)
1039+ self.indicator.menuitem_pause.set_sensitive(False)
1040+ self.indicator.menuitem_finish.set_sensitive(True)
1041+ self.indicator.menuitem_show.set_sensitive(False)
1042+ self.indicator.menuitem_quit.set_sensitive(False)
1043+ self.indicator.menuitem_finish.set_label(_("Cancel countdown"))
1044+ self.in_countdown = True
1045+
1046+ self.indicator.blink_set_state(BLINK_START)
1047+
1048+ if self.main_mode == MODE_SCREENCAST and prefs.sound:
1049+ if prefs.capture_speakers and prefs.audio_source > 0:
1050+ audio_source = prefs.audio_sources[prefs.audio_source][1]
1051+ else:
1052+ audio_source = None
1053+
1054+ if prefs.capture_microphone and prefs.audio2_source > 0:
1055+ audio2_source = prefs.audio_sources[prefs.audio2_source][1]
1056+ else:
1057+ audio2_source = None
1058+ else:
1059+ audio_source = None
1060+ audio2_source = None
1061+
1062+ #
1063+ # Get appropriate coordinates for recording
1064+ #
1065+
1066+ video_source = None
1067+
1068+ if self.record_mode == MODE_FULL:
1069+ screen = HW.get_current_screen(self.window)
1070+ video_source = HW.screens[screen]
1071+ else:
1072+ video_source = HW.combined_screen
1073+
1074+ if self.main_mode == MODE_SCREENCAST:
1075+ self.recorder = Screencast()
1076+ self.recorder.setup_sources(video_source,
1077+ audio_source,
1078+ audio2_source,
1079+ prefs.area if self.record_mode == MODE_AREA else None,
1080+ prefs.xid if self.record_mode == MODE_WIN else None)
1081+
1082+ self.recorder.connect("flush-done", self.cb_flush_done)
1083+
1084+ elif self.main_mode == MODE_SCREENSHOT:
1085+ self.grabber = Grabber()
1086+ self.grabber.setup_sources(video_source,
1087+ prefs.area if self.record_mode == MODE_AREA else None,
1088+ prefs.xid if self.record_mode == MODE_WIN else None)
1089+ self.grabber.connect("flush-done", self.cb_flush_done)
1090+
1091+
1092+ self.countdown = CountdownWindow(self.indicator, show_window = prefs.countdown_splash)
1093+ self.countdown.connect("counter-finished", self.cb_counter_finished)
1094+ self.countdown.run(prefs.countdown_timer)
1095+ self.recording = True
1096+ logger.debug("Hiding main window.")
1097+ self.window.hide()
1098+
1099+ def setup_translations(self):
1100+ gettext.bindtextdomain("kazam", "/usr/share/locale")
1101+ gettext.textdomain("kazam")
1102+ try:
1103+ locale.setlocale(locale.LC_ALL, "")
1104+ except Exception as e:
1105+ logger.exception("EXCEPTION: Setlocale failed, no language support.")
1106+
1107+
1108+ def restore_UI (self):
1109+ self.window.move(prefs.main_x, prefs.main_y)
1110+ self.chk_cursor.set_active(prefs.capture_cursor)
1111+ self.chk_speakers.set_active(prefs.capture_speakers)
1112+ self.chk_microphone.set_active(prefs.capture_microphone)
1113+ self.chk_cursor_pic.set_active(prefs.capture_cursor_pic)
1114+ self.chk_borders_pic.set_active(prefs.capture_borders_pic)
1115+ self.spinbutton_delay.set_value(prefs.countdown_timer)
1116+
1117+ #
1118+ # Turn off the combined screen icon if we don't have more than one screen.
1119+ #
1120+ if HW.combined_screen:
1121+ self.btn_allscreens.set_sensitive(True)
1122+ else:
1123+ self.btn_allscreens.set_sensitive(False)
1124
1125=== added directory 'build/lib.linux-x86_64-2.7/kazam/backend'
1126=== added file 'build/lib.linux-x86_64-2.7/kazam/backend/__init__.py'
1127--- build/lib.linux-x86_64-2.7/kazam/backend/__init__.py 1970-01-01 00:00:00 +0000
1128+++ build/lib.linux-x86_64-2.7/kazam/backend/__init__.py 2012-11-15 10:17:01 +0000
1129@@ -0,0 +1,1 @@
1130+
1131
1132=== added file 'build/lib.linux-x86_64-2.7/kazam/backend/config.py'
1133--- build/lib.linux-x86_64-2.7/kazam/backend/config.py 1970-01-01 00:00:00 +0000
1134+++ build/lib.linux-x86_64-2.7/kazam/backend/config.py 2012-11-15 10:17:01 +0000
1135@@ -0,0 +1,128 @@
1136+# -*- coding: utf-8 -*-
1137+#
1138+# config.py
1139+#
1140+# Copyright 2012 David Klasinc <bigwhale@lubica.net>
1141+# Copyright 2010 Andrew <andrew@karmic-desktop>
1142+#
1143+# This program is free software; you can redistribute it and/or modify
1144+# it under the terms of the GNU General Public License as published by
1145+# the Free Software Foundation; either version 3 of the License, or
1146+# (at your option) any later version.
1147+#
1148+# This program is distributed in the hope that it will be useful,
1149+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1150+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1151+# GNU General Public License for more details.
1152+#
1153+# You should have received a copy of the GNU General Public License
1154+# along with this program; if not, write to the Free Software
1155+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
1156+# MA 02110-1301, USA.
1157+
1158+import os
1159+from ConfigParser import SafeConfigParser, NoSectionError, NoOptionError
1160+from xdg.BaseDirectory import xdg_config_home
1161+
1162+class KazamConfig(SafeConfigParser):
1163+
1164+ DEFAULTS = [{
1165+ "name": "main",
1166+ "keys": {
1167+ "video_toggled" : "True",
1168+ "video_source" : "0",
1169+ "audio_toggled" : "False",
1170+ "audio_source" : "0",
1171+ "audio_volume" : "0",
1172+ "audio2_toggled" : "False",
1173+ "audio2_source" : "0",
1174+ "audio2_volume" : "0",
1175+ "codec" : "0",
1176+ "counter" : "5",
1177+ "capture_cursor" : "True",
1178+ "capture_microphone" : "False",
1179+ "capture_speakers" : "False",
1180+ "capture_cursor_pic" : "True",
1181+ "capture_borders_pic" : "True",
1182+ "framerate" : "15",
1183+ "countdown_splash" : "True",
1184+ "last_x" : "60",
1185+ "last_y" : "25",
1186+ "advanced" : "0",
1187+ "silent" : "0",
1188+ "autosave_video" : "False",
1189+ "autosave_video_dir" : "",
1190+ "autosave_video_file" : "Kazam_screencast",
1191+ "autosave_picture" : "False",
1192+ "autosave_picture_dir" : "",
1193+ "autosave_picture_file" : "Kazam_screenshot",
1194+ "shutter_sound" : "True",
1195+ "shutter_type" : "0",
1196+ },
1197+ },
1198+ {
1199+ "name": "keyboard_shortcuts",
1200+ "keys": {
1201+ "pause": "<Shift><Control>p",
1202+ "finish": "<Shift><Control>f",
1203+ "show": "<Shift><Control>s",
1204+ "quit": "<Shift><Control>q",
1205+ },
1206+ }]
1207+
1208+ CONFIGDIR = os.path.join(xdg_config_home, "kazam")
1209+ CONFIGFILE = os.path.join(CONFIGDIR, "kazam.conf")
1210+
1211+ def __init__(self):
1212+ SafeConfigParser.__init__(self, self.DEFAULTS[0]['keys'])
1213+ if not os.path.isdir(self.CONFIGDIR):
1214+ os.makedirs(self.CONFIGDIR)
1215+ if not os.path.isfile(self.CONFIGFILE):
1216+ self.create_default()
1217+ self.write()
1218+ self.read(self.CONFIGFILE)
1219+
1220+ def create_default(self):
1221+ # For every section
1222+ for section in self.DEFAULTS:
1223+ # Add the section
1224+ self.add_section(section["name"])
1225+ # And add every key in it, with its default value
1226+ for key in section["keys"]:
1227+ value = section["keys"][key]
1228+ self.set(section["name"], key, value)
1229+
1230+ def find_default(self, section, key):
1231+ for d_section in self.DEFAULTS:
1232+ if d_section["name"] == section:
1233+ for d_key in d_section["keys"]:
1234+ if d_key == key:
1235+ return d_section["keys"][key]
1236+
1237+ def get(self, section, key):
1238+ try:
1239+ return SafeConfigParser.get(self, section, key)
1240+ except NoSectionError:
1241+ default = self.find_default(section, key)
1242+ self.set(section, key, default)
1243+ self.write()
1244+ return default
1245+ except NoOptionError:
1246+ default = self.find_default(section, key)
1247+ self.set(section, key, default)
1248+ self.write()
1249+ return default
1250+
1251+ def set(self, section, option, value):
1252+ # If the section referred to doesn't exist (rare case),
1253+ # then create it
1254+ if not self.has_section(section):
1255+ self.add_section(section)
1256+ SafeConfigParser.set(self, section, option, str(value))
1257+
1258+ def write(self):
1259+ file_ = open(self.CONFIGFILE, "w")
1260+ SafeConfigParser.write(self, file_)
1261+ file_.close()
1262+
1263+
1264
1265=== added file 'build/lib.linux-x86_64-2.7/kazam/backend/constants.py'
1266--- build/lib.linux-x86_64-2.7/kazam/backend/constants.py 1970-01-01 00:00:00 +0000
1267+++ build/lib.linux-x86_64-2.7/kazam/backend/constants.py 2012-11-15 10:17:01 +0000
1268@@ -0,0 +1,152 @@
1269+# -*- coding: utf-8 -*-
1270+#
1271+# constants.py
1272+#
1273+# Copyright 2012 David Klasinc <bigwhale@lubica.net>
1274+#
1275+# This program is free software; you can redistribute it and/or modify
1276+# it under the terms of the GNU General Public License as published by
1277+# the Free Software Foundation; either version 3 of the License, or
1278+# (at your option) any later version.
1279+#
1280+# This program is distributed in the hope that it will be useful,
1281+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1282+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1283+# GNU General Public License for more details.
1284+#
1285+# You should have received a copy of the GNU General Public License
1286+# along with this program; if not, write to the Free Software
1287+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
1288+# MA 02110-1301, USA.
1289+
1290+
1291+# Codecs
1292+
1293+CODEC_RAW = 0
1294+CODEC_VP8 = 1
1295+CODEC_H264 = 2
1296+CODEC_HUFF = 3
1297+CODEC_JPEG = 4
1298+
1299+#
1300+# Number, gstreamer element name, string description, file extension, advanced
1301+#
1302+
1303+CODEC_LIST = [
1304+ [0, None, 'RAW / AVI', '.avi', True],
1305+ [1, 'vp8enc', 'VP8 / WEBM', '.webm', False],
1306+ [2, 'x264enc', 'H264 / MP4', '.mp4', False],
1307+ [3, 'ffenc_huffyuv', 'HUFFYUV / AVI', '.avi', True],
1308+ [4, 'ffenc_ljpeg', 'Lossless JPEG / AVI', '.avi', True],
1309+ ]
1310+
1311+# PulseAudio Error Codes
1312+PA_LOAD_ERROR = 1
1313+PA_GET_STATE_ERROR = 2
1314+PA_STARTUP_ERROR = 3
1315+PA_UNABLE_TO_CONNECT = 4
1316+PA_UNABLE_TO_CONNECT2 = 5
1317+PA_MAINLOOP_START_ERROR = 6
1318+PA_GET_SOURCES_ERROR = 7
1319+PA_GET_SOURCES_TIMEOUT = 8
1320+PA_GET_SOURCE_ERROR = 9
1321+PA_GET_SOURCE_TIMEOUT = 10
1322+PA_MAINLOOP_END_ERROR = 11
1323+
1324+
1325+# PulseAudio Status Codes
1326+PA_STOPPED = 0
1327+PA_WORKING = 1
1328+PA_FINISHED = 2
1329+PA_ERROR = 3
1330+
1331+# PulseAudio State Codes
1332+PA_STATE_READY = 0
1333+PA_STATE_BUSY = 1
1334+PA_STATE_FAILED = 2
1335+PA_STATE_WORKING = 3
1336+
1337+
1338+# Various actions
1339+ACTION_SAVE = 0
1340+ACTION_EDIT = 1
1341+
1342+# Blink modes and states
1343+BLINK_STOP = 0
1344+BLINK_START = 1
1345+BLINK_SLOW = 2
1346+BLINK_FAST = 3
1347+BLINK_STOP_ICON = 4
1348+BLINK_READY_ICON = 5
1349+
1350+# Main modes
1351+MODE_SCREENCAST = 0
1352+MODE_SCREENSHOT = 1
1353+
1354+# Record modes
1355+MODE_FULL = 0
1356+MODE_ALL = 1
1357+MODE_AREA = 2
1358+MODE_WIN = 3
1359+MODE_ACTIVE = 4
1360+MODE_GOD = 666
1361+
1362+import logging
1363+
1364+from gi.repository import Gdk, GdkX11
1365+
1366+class hw:
1367+ def __init__(self):
1368+ self.logger = logging.getLogger("Constants")
1369+ self.logger.debug("Getting hardware specs")
1370+ self.screens = None
1371+ self.combined_screen = None
1372+
1373+ self.get_screens()
1374+
1375+ def get_current_screen(self, window = None):
1376+ try:
1377+ if window:
1378+ screen = self.default_screen.get_monitor_at_window(window.get_window())
1379+ else:
1380+ disp = GdkX11.X11Display.get_default()
1381+ dm = Gdk.Display.get_device_manager(disp)
1382+ pntr_device = dm.get_client_pointer()
1383+ (src, x, y) = pntr_device.get_position()
1384+ screen = self.default_screen.get_monitor_at_point(x, y)
1385+ except:
1386+ screen = 0
1387+ return screen
1388+
1389+ def get_screens(self):
1390+ try:
1391+ self.logger.debug("Getting Video sources.")
1392+ self.screens = []
1393+ self.default_screen = Gdk.Screen.get_default()
1394+ self.logger.debug("Found {0} monitors.".format(self.default_screen.get_n_monitors()))
1395+
1396+ for i in range(self.default_screen.get_n_monitors()):
1397+ rect = self.default_screen.get_monitor_geometry(i)
1398+ self.logger.debug(" Monitor {0} - X: {1}, Y: {2}, W: {3}, H: {4}".format(i,
1399+ rect.x,
1400+ rect.y,
1401+ rect.width,
1402+ rect.height))
1403+ self.screens.append({"x": rect.x,
1404+ "y": rect.y,
1405+ "width": rect.width,
1406+ "height": rect.height})
1407+
1408+ if self.default_screen.get_n_monitors() > 1:
1409+ self.combined_screen = {"x": 0, "y": 0,
1410+ "width": self.default_screen.get_width(),
1411+ "height": self.default_screen.get_height()}
1412+ self.logger.debug(" Combined screen - X: 0, Y: 0, W: {0}, H: {1}".format(self.default_screen.get_width(),
1413+ self.default_screen.get_height()))
1414+ else:
1415+ self.combined_screen = None
1416+
1417+ except:
1418+ self.logger.warning("Unable to find any video sources.")
1419+
1420+HW = hw()
1421
1422=== added file 'build/lib.linux-x86_64-2.7/kazam/backend/export.py'
1423--- build/lib.linux-x86_64-2.7/kazam/backend/export.py 1970-01-01 00:00:00 +0000
1424+++ build/lib.linux-x86_64-2.7/kazam/backend/export.py 2012-11-15 10:17:01 +0000
1425@@ -0,0 +1,194 @@
1426+# -*- coding: utf-8 -*-
1427+#
1428+# export_backend.py
1429+#
1430+# Copyright 2012 David Klasinc <bigwhale@lubica.net>
1431+# Copyright 2010 Andrew <andrew@karmic-desktop>
1432+#
1433+# This program is free software; you can redistribute it and/or modify
1434+# it under the terms of the GNU General Public License as published by
1435+# the Free Software Foundation; either version 3 of the License, or
1436+# (at your option) any later version.
1437+#
1438+# This program is distributed in the hope that it will be useful,
1439+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1440+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1441+# GNU General Public License for more details.
1442+#
1443+# You should have received a copy of the GNU General Public License
1444+# along with this program; if not, write to the Free Software
1445+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
1446+# MA 02110-1301, USA.
1447+
1448+import os
1449+
1450+from gi.repository import GObject
1451+
1452+import kazam.backend.export_sources
1453+from kazam.utils import *
1454+
1455+class ExportBackend(GObject.GObject):
1456+
1457+ __gsignals__ = {
1458+ "authenticate-requested" : (GObject.SIGNAL_RUN_LAST,
1459+ GObject.TYPE_NONE,
1460+ ([GObject.TYPE_PYOBJECT,
1461+ GObject.TYPE_PYOBJECT,
1462+ GObject.TYPE_PYOBJECT]),),
1463+ "login-started" : (GObject.SIGNAL_RUN_LAST,
1464+ GObject.TYPE_NONE,
1465+ ( ),),
1466+ "login-completed" : (GObject.SIGNAL_RUN_LAST,
1467+ GObject.TYPE_NONE,
1468+ ([bool]),),
1469+ "convert-started" : (GObject.SIGNAL_RUN_LAST,
1470+ GObject.TYPE_NONE,
1471+ ( ),),
1472+ "convert-completed" : (GObject.SIGNAL_RUN_LAST,
1473+ GObject.TYPE_NONE,
1474+ ([bool]),),
1475+ "upload-started" : (GObject.SIGNAL_RUN_LAST,
1476+ GObject.TYPE_NONE,
1477+ ( ),),
1478+ "upload-completed" : (GObject.SIGNAL_RUN_LAST,
1479+ GObject.TYPE_NONE,
1480+ ([bool, str]),),
1481+ }
1482+
1483+ def __init__(self, frontend, datadir):
1484+ super(ExportBackend, self).__init__()
1485+
1486+ self.frontend = frontend
1487+ self.frontend.connect("export-requested", self.cb_export_requested)
1488+
1489+ self.datadir = datadir
1490+ self.active_export_object = None
1491+
1492+ self.error = False
1493+
1494+ export_module_files = self._get_export_module_files()
1495+ self.export_objects = self._create_export_objects(export_module_files)
1496+
1497+ def _get_export_module_files(self):
1498+ """
1499+ Returns a list of export source files
1500+ """
1501+ export_module_list = []
1502+ # For each directory that provides kazam.export_sources
1503+ for path in kazam.backend.export_sources.__path__:
1504+ directory = os.path.abspath(path)
1505+ # List files in that directory
1506+ for f in os.listdir(directory):
1507+ # If the file is a python file append the file to our list
1508+ if f[-3:] == ".py":
1509+ export_module_list.append(f)
1510+
1511+ # Remove __init__.py and any duplicates
1512+ export_module_list.remove("__init__.py")
1513+ export_module_list = remove_list_dups(export_module_list)
1514+
1515+ return export_module_list
1516+
1517+ def _import_export_module(self, name):
1518+ """
1519+ Import an export_source module and return the module
1520+ """
1521+ return getattr(__import__("kazam.backend.export_sources", globals(),
1522+ locals(), [name], -1), name)
1523+
1524+ def _create_export_objects(self, export_module_files):
1525+ """
1526+ Return a list of export objects
1527+ """
1528+ export_objects = []
1529+ for f in export_module_files:
1530+ f = f[:-3]
1531+ # Find and import the module for each file
1532+ module = self._import_export_module(f)
1533+ # Append an instance of it, to our export_objects list
1534+ upload_source = module.UploadSource()
1535+ upload_source.gui_extra(self.datadir)
1536+ export_objects.append(upload_source)
1537+ return export_objects
1538+
1539+ def get_export_objects(self):
1540+ return self.export_objects
1541+
1542+ def set_active_export_object(self, i):
1543+ self.active_export_object = self.export_objects[i]
1544+ return self.active_export_object
1545+
1546+ def get_active_export_object(self):
1547+ return self.active_export_object
1548+
1549+ def get_export_meta(self):
1550+ return self.export_object.META
1551+
1552+ def cb_export_requested(self, frontend):
1553+ self.error = False
1554+ self.login()
1555+ if not self.error:
1556+ self.create_meta()
1557+ if not self.error:
1558+ self.convert()
1559+ if not self.error:
1560+ self.upload()
1561+
1562+ def login(self):
1563+ if self.active_export_object.authentication == True:
1564+ self.emit("authenticate-requested",
1565+ self.active_export_object.ICONS,
1566+ self.active_export_object.NAME,
1567+ self.active_export_object.REGISTER_URL)
1568+ else:
1569+ self.details = (None, None)
1570+ if hasattr(self, "details"):
1571+ try:
1572+ self.emit("login-started")
1573+ (username, password) = self.details
1574+ self.active_export_object.login_pre(username, password)
1575+ create_wait_thread(self.active_export_object.login_in)
1576+ self.active_export_object.login_post()
1577+ success = True
1578+ except Exception, e:
1579+ print e
1580+ self.error = True
1581+ success = False
1582+ else:
1583+ success = False
1584+ self.error = True
1585+ self.emit("login-completed", success)
1586+
1587+ def create_meta(self):
1588+ self.active_export_object.create_meta(**self.frontend.get_meta())
1589+
1590+ def convert(self):
1591+ self.emit("convert-started")
1592+ try:
1593+ screencast = self.frontend.get_screencast()
1594+ screencast.convert(self.active_export_object.FFMPEG_OPTIONS,
1595+ self.active_export_object.FFMPEG_FILE_EXTENSION,
1596+ self.frontend.get_video_quality(),
1597+ self.frontend.get_audio_quality())
1598+ while not hasattr(screencast, "converted_file"):
1599+ gtk.main_iteration()
1600+ self.converted_file_path = screencast.converted_file
1601+ self.emit("convert-completed", True)
1602+ except Exception, e:
1603+ print e
1604+ self.error = True
1605+ self.emit("convert-completed", False)
1606+
1607+ def upload(self):
1608+ self.emit("upload-started")
1609+ url = ""
1610+ try:
1611+ self.active_export_object.upload_pre()
1612+ create_wait_thread(self.active_export_object.upload_in, (self.converted_file_path,))
1613+ url = self.active_export_object.upload_post()
1614+ success = True
1615+ except Exception, e:
1616+ print e
1617+ self.error = True
1618+ success = False
1619+ self.emit("upload-completed", success, url)
1620
1621=== added file 'build/lib.linux-x86_64-2.7/kazam/backend/ffmpeg.py'
1622--- build/lib.linux-x86_64-2.7/kazam/backend/ffmpeg.py 1970-01-01 00:00:00 +0000
1623+++ build/lib.linux-x86_64-2.7/kazam/backend/ffmpeg.py 2012-11-15 10:17:01 +0000
1624@@ -0,0 +1,132 @@
1625+#!/usr/bin/env python
1626+# -*- coding: utf-8 -*-
1627+#
1628+# recording.py
1629+#
1630+# Copyright 2012 David Klasinc <bigwhale@lubica.net>
1631+# Copyright 2010 Andrew <andrew@karmic-desktop>
1632+#
1633+# This program is free software; you can redistribute it and/or modify
1634+# it under the terms of the GNU General Public License as published by
1635+# the Free Software Foundation; either version 3 of the License, or
1636+# (at your option) any later version.
1637+#
1638+# This program is distributed in the hope that it will be useful,
1639+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1640+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1641+# GNU General Public License for more details.
1642+#
1643+# You should have received a copy of the GNU General Public License
1644+# along with this program; if not, write to the Free Software
1645+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
1646+# MA 02110-1301, USA.
1647+
1648+from subprocess import Popen
1649+import tempfile
1650+import os
1651+import gobject
1652+import glib
1653+import signal
1654+
1655+class Screencast(object):
1656+ def __init__(self):
1657+ self.tempfile = tempfile.mktemp(prefix="kazam_", suffix=".mkv")
1658+
1659+ def setup_sources(self, video_source, audio_source):
1660+ self.audio_source = audio_source
1661+ self.video_source = video_source
1662+
1663+ # TODO: use gstreamer instead (see gstreamer.py for start)
1664+ self.args_list = ["ffmpeg"]
1665+
1666+ # Add the audio source if selected
1667+ if audio_source:
1668+ self.args_list += ["-f", "alsa", "-i", "pulse"]
1669+
1670+ # Add the video source
1671+ if video_source:
1672+ x = video_source.x
1673+ y = video_source.y
1674+ width = video_source.width
1675+ height = video_source.height
1676+ display = video_source.display
1677+ self.args_list += ["-f", "x11grab", "-r", "30", "-s",
1678+ "%sx%s" % (width, height), "-i",
1679+ "%s+%s,%s" % (display, x, y)]
1680+ if audio_source:
1681+ self.args_list += ["-ac", "2", "-acodec", "flac", "-ab", "128k"]
1682+
1683+ if video_source:
1684+ self.args_list += ["-vcodec", "libx264",
1685+ "-crf", "0",
1686+ "-preset", "fast",
1687+ "-tune", "stillimage",
1688+ "-vf", "unsharp=3:3:0.5:3:3:0.0"
1689+
1690+ ]
1691+ self.args_list += ["-threads", "0", self.tempfile]
1692+
1693+ arg_string = ""
1694+ for arg in self.args_list:
1695+ arg_string += " %s" % arg
1696+ print arg_string
1697+
1698+ def start_recording(self):
1699+ self.recording_command = Popen(self.args_list)
1700+
1701+ def pause_recording(self):
1702+ self.recording_command.send_signal(signal.SIGTSTP)
1703+
1704+ def unpause_recording(self):
1705+ self.recording_command.send_signal(signal.SIGCONT)
1706+
1707+ def stop_recording(self):
1708+ self.recording_command.send_signal(signal.SIGINT)
1709+
1710+ def get_recording_filename(self):
1711+ return self.tempfile
1712+
1713+ def get_audio_recorded(self):
1714+ return self.audio_source
1715+
1716+ def get_video_recorded(self):
1717+ return self.video_source
1718+
1719+ def convert(self, options, converted_file_extension, video_quality=None,
1720+ audio_quality=None):
1721+
1722+ self.converted_file_extension = converted_file_extension
1723+
1724+ # Create our ffmpeg arguments list
1725+ args_list = ["ffmpeg"]
1726+ # Add the input file
1727+ args_list += ["-i", self.tempfile]
1728+ # Add any UploadSource specific options
1729+ args_list += options
1730+
1731+ # Configure the quality as selected by the user
1732+ # If the quality slider circle is at the right-most position
1733+ # use the same quality option
1734+ if video_quality == 6001:
1735+ args_list += ["-sameq"]
1736+ elif video_quality:
1737+ args_list += ["-b", "%sk" % video_quality]
1738+ if audio_quality:
1739+ args_list += ["-ab", "%sk" % audio_quality]
1740+ # Finally add the desired output file
1741+ args_list += ["%s%s" %(self.tempfile[:-4], converted_file_extension)]
1742+
1743+ # Run the ffmpeg command and when it is done, set a variable to
1744+ # show we have finished
1745+ command = Popen(args_list)
1746+ glib.timeout_add(100, self._poll, command)
1747+
1748+ def _poll(self, command):
1749+ ret = command.poll()
1750+ if ret is None:
1751+ # Keep monitoring
1752+ return True
1753+ else:
1754+ self.converted_file = "%s%s" %(self.tempfile[:-4], self.converted_file_extension)
1755+ return False
1756+
1757
1758=== added file 'build/lib.linux-x86_64-2.7/kazam/backend/grabber.py'
1759--- build/lib.linux-x86_64-2.7/kazam/backend/grabber.py 1970-01-01 00:00:00 +0000
1760+++ build/lib.linux-x86_64-2.7/kazam/backend/grabber.py 2012-11-15 10:17:01 +0000
1761@@ -0,0 +1,166 @@
1762+# -*- coding: utf-8 -*-
1763+#
1764+# grabber.py
1765+#
1766+# Copyright 2012 David Klasinc <bigwhale@lubica.net>
1767+#
1768+# This program is free software; you can redistribute it and/or modify
1769+# it under the terms of the GNU General Public License as published by
1770+# the Free Software Foundation; either version 3 of the License, or
1771+# (at your option) any later version.
1772+#
1773+# This program is distributed in the hope that it will be useful,
1774+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1775+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1776+# GNU General Public License for more details.
1777+#
1778+# You should have received a copy of the GNU General Public License
1779+# along with this program; if not, write to the Free Software
1780+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
1781+# MA 02110-1301, USA.
1782+
1783+
1784+import os
1785+import subprocess
1786+import logging
1787+logger = logging.getLogger("Grabber")
1788+
1789+from gi.repository import GObject, Gtk, Gdk, GdkPixbuf, GdkX11
1790+
1791+from kazam.backend.prefs import *
1792+from kazam.backend.constants import *
1793+from kazam.frontend.save_dialog import SaveDialog
1794+from gettext import gettext as _
1795+
1796+class Grabber(GObject.GObject):
1797+ __gsignals__ = {
1798+ "save-done" : (GObject.SIGNAL_RUN_LAST,
1799+ None,
1800+ [GObject.TYPE_PYOBJECT],),
1801+ "flush-done" : (GObject.SIGNAL_RUN_LAST,
1802+ None,
1803+ (),),
1804+ }
1805+
1806+ def __init__(self):
1807+ GObject.GObject.__init__(self)
1808+ logger.debug("Starting Grabber.")
1809+
1810+
1811+ def setup_sources(self, video_source, area, xid, active = False, god = False):
1812+ self.video_source = video_source
1813+ self.area = area
1814+ self.xid = xid
1815+ self.god = god
1816+ if active:
1817+ from gi.repository import GdkX11
1818+ active_win = HW.default_screen.get_active_window()
1819+ self.xid = GdkX11.X11Window.get_xid(active_win)
1820+
1821+ logger.debug("Grabber source: {0}, {1}, {2}, {3}".format(self.video_source['x'],
1822+ self.video_source['y'],
1823+ self.video_source['width'],
1824+ self.video_source['height']))
1825+
1826+ def grab(self):
1827+ self.pixbuf = None
1828+ disp = GdkX11.X11Display.get_default()
1829+ dm = Gdk.Display.get_device_manager(disp)
1830+ pntr_device = dm.get_client_pointer()
1831+
1832+ #
1833+ # Rewrite this, because it sucks
1834+ #
1835+ if prefs.shutter_sound and (not self.god):
1836+ soundfile = os.path.join(prefs.datadir, 'sounds', prefs.sound_files[prefs.shutter_type])
1837+ subprocess.call(['/usr/bin/canberra-gtk-play', '-f', soundfile])
1838+
1839+ if self.xid:
1840+ if prefs.capture_borders_pic:
1841+ app_win = GdkX11.X11Window.foreign_new_for_display(disp, self.xid)
1842+ (rx, ry, rw, rh) = app_win.get_geometry()
1843+ area = app_win.get_frame_extents()
1844+ (fx, fy, fw, fh) = (area.x, area.y, area.width, area.height)
1845+ win = Gdk.get_default_root_window()
1846+ logger.debug("Coordinates RX {0} RY {1} RW {2} RH {3}".format(rx, ry, rw, rh))
1847+ logger.debug("Coordinates FX {0} FY {1} FW {2} FH {3}".format(fx, fy, fw, fh))
1848+ dx = fw - rw
1849+ dy = fh - rh
1850+ (x, y, w, h) = (fx, fy, fw, fh)
1851+ logger.debug("Coordinates delta: DX {0} DY {1}".format(dx, dy))
1852+ else:
1853+ win = GdkX11.X11Window.foreign_new_for_display(disp, self.xid)
1854+ (x, y, w, h) = win.get_geometry()
1855+ else:
1856+ win = Gdk.get_default_root_window()
1857+ (x, y, w, h) = (self.video_source['x'],
1858+ self.video_source['y'],
1859+ self.video_source['width'],
1860+ self.video_source['height'])
1861+
1862+ logger.debug("Coordinates X {0} Y {1} W {2} H {3}".format(x, y, w, h))
1863+ self.pixbuf = Gdk.pixbuf_get_from_window(win, x, y, w, h)
1864+
1865+ if prefs.capture_cursor_pic:
1866+ logger.debug("Adding cursor.")
1867+
1868+ cursor = Gdk.Cursor.new_for_display(Gdk.Display.get_default(), Gdk.CursorType.LEFT_PTR)
1869+ c_picbuf = Gdk.Cursor.get_image(cursor)
1870+
1871+ if self.xid and prefs.capture_borders_pic:
1872+ pointer = app_win.get_device_position(pntr_device)
1873+ (px, py) = (pointer[1], pointer[2])
1874+ c_picbuf.composite(self.pixbuf, rx, ry, rw, rh,
1875+ px + dx - 6,
1876+ py + dy - 2,
1877+ 1.0,
1878+ 1.0,
1879+ GdkPixbuf.InterpType.BILINEAR,
1880+ 255)
1881+ else:
1882+ pointer = win.get_device_position(pntr_device)
1883+ (px, py) = (pointer[1], pointer[2])
1884+ #
1885+ # Cursor is offseted by 6 pixels to the right and 2 down
1886+ #
1887+ c_picbuf.composite(self.pixbuf, x, y, w, h,
1888+ px - 6,
1889+ py - 2,
1890+ 1.0,
1891+ 1.0,
1892+ GdkPixbuf.InterpType.BILINEAR,
1893+ 255)
1894+
1895+ logger.debug("Cursor coords: {0} {1}".format(px, py))
1896+
1897+ if self.area is not None:
1898+ logger.debug("Cropping image.")
1899+ self.area_buf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, self.area[4], self.area[5])
1900+ self.pixbuf.copy_area(self.area[0], self.area[1], self.area[4], self.area[5], self.area_buf, 0, 0)
1901+ self.pixbuf = None
1902+ self.pixbuf = self.area_buf
1903+
1904+ self.emit("flush-done")
1905+
1906+ def save(self, filename):
1907+ if self.pixbuf is not None:
1908+ self.pixbuf.savev(filename, "png", "", "")
1909+
1910+ def save_capture(self, old_path):
1911+ logger.debug("Saving screenshot.")
1912+ self.old_path = old_path
1913+ (dialog, result, self.old_path) = SaveDialog(_("Save capture"),
1914+ self.old_path, None, main_mode=MODE_SCREENSHOT)
1915+
1916+ if result == Gtk.ResponseType.OK:
1917+ uri = os.path.join(dialog.get_current_folder(), dialog.get_filename())
1918+
1919+ self.save(uri)
1920+
1921+ dialog.destroy()
1922+ self.emit("save-done", self.old_path)
1923+
1924+ def autosave(self, filename):
1925+ logger.debug("Autosaving to: {0}".format(filename))
1926+ self.save(filename)
1927+ self.emit("save-done", filename)
1928
1929=== added file 'build/lib.linux-x86_64-2.7/kazam/backend/gstreamer.py'
1930--- build/lib.linux-x86_64-2.7/kazam/backend/gstreamer.py 1970-01-01 00:00:00 +0000
1931+++ build/lib.linux-x86_64-2.7/kazam/backend/gstreamer.py 2012-11-15 10:17:01 +0000
1932@@ -0,0 +1,416 @@
1933+# -*- coding: utf-8 -*-
1934+#
1935+# gstreamer.py
1936+#
1937+# Copyright 2012 David Klasinc <bigwhale@lubica.net>
1938+#
1939+# This program is free software; you can redistribute it and/or modify
1940+# it under the terms of the GNU General Public License as published by
1941+# the Free Software Foundation; either version 3 of the License, or
1942+# (at your option) any later version.
1943+#
1944+# This program is distributed in the hope that it will be useful,
1945+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1946+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1947+# GNU General Public License for more details.
1948+#
1949+# You should have received a copy of the GNU General Public License
1950+# along with this program; if not, write to the Free Software
1951+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
1952+# MA 02110-1301, USA.
1953+
1954+import os
1955+import logging
1956+logger = logging.getLogger("GStreamer-GI")
1957+
1958+import tempfile
1959+import multiprocessing
1960+
1961+#
1962+# This needs to be set before we load GStreamer modules!
1963+#
1964+os.environ["GST_DEBUG_DUMP_DOT_DIR"] = "/tmp"
1965+os.putenv("GST_DEBUG_DUMP_DOT_DIR", "/tmp")
1966+
1967+from gi.repository import GObject, Gst
1968+
1969+from kazam.backend.prefs import *
1970+from kazam.backend.constants import *
1971+
1972+GObject.threads_init()
1973+Gst.init(None)
1974+Gst.debug_set_active(True)
1975+
1976+class Screencast(GObject.GObject):
1977+ __gsignals__ = {
1978+ "flush-done" : (GObject.SIGNAL_RUN_LAST,
1979+ None,
1980+ (),
1981+ ),
1982+ }
1983+ def __init__(self):
1984+ GObject.GObject.__init__(self)
1985+
1986+ self.temp_fh = tempfile.mkstemp(prefix="kazam_", dir=prefs.video_dest, suffix=".movie")
1987+ self.tempfile = self.temp_fh[1]
1988+ self.muxer_tempfile = "{0}.mux".format(self.tempfile)
1989+ self.pipeline = Gst.Pipeline()
1990+ self.area = None
1991+ self.xid = None
1992+ self.crop_vid = False
1993+
1994+ def setup_sources(self,
1995+ video_source,
1996+ audio_source,
1997+ audio2_source,
1998+ area,
1999+ xid):
2000+
2001+
2002+ # Get the number of cores available then use all except one for encoding
2003+ self.cores = multiprocessing.cpu_count()
2004+
2005+ if self.cores > 1:
2006+ self.cores -= 1
2007+
2008+ self.audio_source = audio_source
2009+ self.audio2_source = audio2_source
2010+ self.video_source = video_source
2011+ self.area = area
2012+ self.xid = xid
2013+
2014+ logger.debug("audio_source : {0}".format(audio_source))
2015+ logger.debug("video_source: {0}".format(video_source))
2016+ logger.debug("xid: {0}".format(xid))
2017+ logger.debug("area: {0}".format(area))
2018+
2019+ logger.debug("Capture Cursor: {0}".format(prefs.capture_cursor))
2020+ logger.debug("Framerate : {0}".format(prefs.framerate))
2021+ logger.debug("Codec: {0}".format(CODEC_LIST[prefs.codec][1]))
2022+
2023+ if self.video_source or self.area:
2024+ self.setup_video_source()
2025+
2026+ if self.audio_source:
2027+ self.setup_audio_source()
2028+
2029+ if self.audio2_source:
2030+ self.setup_audio2_source()
2031+
2032+ self.setup_filesink()
2033+ self.setup_pipeline()
2034+ self.setup_links()
2035+
2036+ self.bus = self.pipeline.get_bus()
2037+ self.bus.add_signal_watch()
2038+ self.bus.connect("message", self.on_message)
2039+
2040+ def setup_video_source(self):
2041+
2042+ if prefs.test:
2043+ self.videosrc = Gst.ElementFactory.make("videotestsrc", "video_src")
2044+ self.videosrc.set_property("pattern", "smpte")
2045+ else:
2046+ self.videosrc = Gst.ElementFactory.make("ximagesrc", "video_src")
2047+
2048+ if self.area:
2049+ logger.debug("Capturing area.")
2050+ startx = self.area[0] if self.area[0] > 0 else 0
2051+ starty = self.area[1] if self.area[1] > 0 else 0
2052+ endx = self.area[2]
2053+ endy = self.area[3]
2054+ else:
2055+ startx = self.video_source['x']
2056+ starty = self.video_source['y']
2057+ width = self.video_source['width']
2058+ height = self.video_source['height']
2059+ endx = startx + width - 1
2060+ endy = starty + height - 1
2061+
2062+ #
2063+ # H264 requirement is that video dimensions are divisible by 2.
2064+ # If they are not, we have to get rid of that extra pixel.
2065+ #
2066+ if not abs(startx - endx) % 2 and prefs.codec == CODEC_H264:
2067+ endx -= 1
2068+
2069+ if not abs(starty - endy) % 2 and prefs.codec == CODEC_H264:
2070+ endy -= 1
2071+
2072+ logger.debug("Coordinates SX: {0} SY: {1} EX: {2} EY: {3}".format(startx, starty, endx, endy))
2073+
2074+ if prefs.test:
2075+ logger.info("Using test signal instead of screen capture.")
2076+ self.vid_caps = Gst.caps_from_string("video/x-raw,format=(x-raw-rgb),framerate={0}/1, width={1}, height={2}".format(
2077+ prefs.framerate,
2078+ endx - startx,
2079+ endy - starty))
2080+ self.vid_caps_filter = Gst.ElementFactory.make("capsfilter", "vid_filter")
2081+ self.vid_caps_filter.set_property("caps", self.vid_caps)
2082+ else:
2083+ logger.debug("testing for xid: {0}".format(self.xid))
2084+ if self.xid: # xid was passed, so we have to capture a single window.
2085+ logger.debug("Capturing Window: {0} {1}".format(self.xid, prefs.xid_geometry))
2086+ self.videosrc.set_property("xid", self.xid)
2087+
2088+ if prefs.codec == CODEC_H264:
2089+ self.videocrop = Gst.ElementFactory.make("videocrop", "cropper")
2090+ if prefs.xid_geometry[2] % 2:
2091+ self.videocrop.set_property("left", 1)
2092+ self.crop_vid = True
2093+ if prefs.xid_geometry[3] % 2:
2094+ self.videocrop.set_property("bottom", 1)
2095+ self.crop_vid = True
2096+ else:
2097+ self.videosrc.set_property("startx", startx)
2098+ self.videosrc.set_property("starty", starty)
2099+ self.videosrc.set_property("endx", endx)
2100+ self.videosrc.set_property("endy", endy)
2101+
2102+ self.videosrc.set_property("use-damage", False)
2103+ self.videosrc.set_property("show-pointer", prefs.capture_cursor)
2104+
2105+ self.vid_caps = Gst.caps_from_string("video/x-raw,format=(x-raw-rgb),framerate={0}/1".format(prefs.framerate))
2106+ self.vid_caps_filter = Gst.ElementFactory.make("capsfilter", "vid_filter")
2107+ self.vid_caps_filter.set_property("caps", self.vid_caps)
2108+
2109+ self.videoconvert = Gst.ElementFactory.make("videoconvert", "videoconvert")
2110+ self.videorate = Gst.ElementFactory.make("videorate", "video_rate")
2111+
2112+ logger.debug("Codec: {0}".format(CODEC_LIST[prefs.codec][2]))
2113+
2114+ if prefs.codec is not CODEC_RAW:
2115+ self.videnc = Gst.ElementFactory.make(CODEC_LIST[prefs.codec][1], "video_encoder")
2116+
2117+ if prefs.codec == CODEC_RAW:
2118+ self.mux = Gst.ElementFactory.make("avimux", "muxer")
2119+ elif prefs.codec == CODEC_VP8:
2120+ self.videnc.set_property("cpu-used", 2)
2121+ self.videnc.set_property("end-usage", "vbr")
2122+ self.videnc.set_property("target-bitrate", 800000000)
2123+ self.videnc.set_property("static-threshold", 1000)
2124+ self.videnc.set_property("token-partitions", 2)
2125+ self.videnc.set_property("max-quantizer", 30)
2126+ self.videnc.set_property("threads", self.cores)
2127+ self.mux = Gst.ElementFactory.make("webmmux", "muxer")
2128+ elif prefs.codec == CODEC_H264:
2129+ self.videnc.set_property("speed-preset", "ultrafast")
2130+ self.videnc.set_property("pass", 4)
2131+ self.videnc.set_property("quantizer", 15)
2132+ #
2133+ # x264enc supports maximum of four cores
2134+ #
2135+ self.videnc.set_property("threads", self.cores if self.cores <= 4 else 4)
2136+ self.mux = Gst.ElementFactory.make("mp4mux", "muxer")
2137+ self.mux.set_property("faststart", 1)
2138+ self.mux.set_property("faststart-file", self.muxer_tempfile)
2139+ self.mux.set_property("streamable", 1)
2140+ elif prefs.codec == CODEC_HUFF:
2141+ self.mux = Gst.ElementFactory.make("avimux", "muxer")
2142+ self.videnc.set_property("bitrate", 500000)
2143+ elif prefs.codec == CODEC_JPEG:
2144+ self.mux = Gst.ElementFactory.make("avimux", "muxer")
2145+
2146+ self.vid_in_queue = Gst.ElementFactory.make("queue", "queue_v1")
2147+ self.vid_out_queue = Gst.ElementFactory.make("queue", "queue_v2")
2148+
2149+ def setup_audio_source(self):
2150+ logger.debug("Audio1 Source:\n {0}".format(self.audio_source))
2151+ self.audiosrc = Gst.ElementFactory.make("pulsesrc", "audio_src")
2152+ self.audiosrc.set_property("device", self.audio_source)
2153+ self.aud_caps = Gst.caps_from_string("audio/x-raw")
2154+ self.aud_caps_filter = Gst.ElementFactory.make("capsfilter", "aud_filter")
2155+ self.aud_caps_filter.set_property("caps", self.aud_caps)
2156+ self.audioconv = Gst.ElementFactory.make("audioconvert", "audio_conv")
2157+ if prefs.codec == CODEC_VP8:
2158+ self.audioenc = Gst.ElementFactory.make("vorbisenc", "audio_encoder")
2159+ self.audioenc.set_property("quality", 1)
2160+ else:
2161+ self.audioenc = Gst.ElementFactory.make("lamemp3enc", "audio_encoder")
2162+ self.audioenc.set_property("quality", 0)
2163+
2164+ self.aud_in_queue = Gst.ElementFactory.make("queue", "queue_a_in")
2165+ self.aud_out_queue = Gst.ElementFactory.make("queue", "queue_a_out")
2166+
2167+ def setup_audio2_source(self):
2168+ logger.debug("Audio2 Source:\n {0}".format(self.audio2_source))
2169+ self.audiomixer = Gst.ElementFactory.make("adder", "audiomixer")
2170+ self.audio2src = Gst.ElementFactory.make("pulsesrc", "audio2_src")
2171+ self.audio2src.set_property("device", self.audio2_source)
2172+ self.aud2_caps = Gst.caps_from_string("audio/x-raw")
2173+ self.aud2_caps_filter = Gst.ElementFactory.make("capsfilter", "aud2_filter")
2174+ self.aud2_caps_filter.set_property("caps", self.aud2_caps)
2175+ self.aud2_in_queue = Gst.ElementFactory.make("queue", "queue_a2_in")
2176+ self.audio2conv = Gst.ElementFactory.make("audioconvert", "audio2_conv")
2177+
2178+ def setup_filesink(self):
2179+ logger.debug("Filesink: {0}".format(self.tempfile))
2180+ self.sink = Gst.ElementFactory.make("filesink", "sink")
2181+ self.sink.set_property("location", self.tempfile)
2182+ self.file_queue = Gst.ElementFactory.make("queue", "queue_file")
2183+
2184+ #
2185+ # One day, this horrific code will be optimised... I promise!
2186+ #
2187+ def setup_pipeline(self):
2188+ #
2189+ # Behold, setup the master pipeline
2190+ #
2191+ self.pipeline.add(self.videosrc)
2192+ self.pipeline.add(self.vid_in_queue)
2193+ if self.crop_vid:
2194+ self.pipeline.add(self.videocrop)
2195+ self.pipeline.add(self.videorate)
2196+ self.pipeline.add(self.vid_caps_filter)
2197+ self.pipeline.add(self.videoconvert)
2198+ self.pipeline.add(self.vid_out_queue)
2199+ self.pipeline.add(self.file_queue)
2200+
2201+ if prefs.codec is not CODEC_RAW:
2202+ self.pipeline.add(self.videnc)
2203+
2204+ if self.audio_source:
2205+ self.pipeline.add(self.audiosrc)
2206+ self.pipeline.add(self.aud_in_queue)
2207+ self.pipeline.add(self.aud_caps_filter)
2208+ self.pipeline.add(self.aud_out_queue)
2209+ self.pipeline.add(self.audioconv)
2210+ self.pipeline.add(self.audioenc)
2211+
2212+ if self.audio2_source:
2213+ self.pipeline.add(self.audiomixer)
2214+ self.pipeline.add(self.aud2_in_queue)
2215+ self.pipeline.add(self.audio2src)
2216+ self.pipeline.add(self.aud2_caps_filter)
2217+
2218+ self.pipeline.add(self.mux)
2219+ self.pipeline.add(self.sink)
2220+
2221+ # gst-launch-1.0 -e ximagesrc endx=1919 endy=1079 use-damage=false show-pointer=true ! \
2222+ # queue ! videorate ! video/x-raw,framerate=15/1 ! videoconvert ! \
2223+ # vp8enc end-usage=vbr target-bitrate=800000000 threads=3 static-threshold=1000 \
2224+ # token-partitions=2 max-quantizer=30 ! queue name=before_mux ! webmmux name=mux ! \
2225+ # queue ! filesink location="test-videorate.webm"
2226+
2227+ def setup_links(self):
2228+ # Connect everything together
2229+ self.videosrc.link(self.vid_in_queue)
2230+ if self.crop_vid:
2231+ self.vid_in_queue.link(self.videocrop)
2232+ self.videocrop.link(self.videorate)
2233+ else:
2234+ self.vid_in_queue.link(self.videorate)
2235+ self.videorate.link(self.vid_caps_filter)
2236+ self.vid_caps_filter.link(self.videoconvert)
2237+ if prefs.codec is CODEC_RAW:
2238+ self.videoconvert.link(self.vid_out_queue)
2239+ logger.debug("Linking RAW Video")
2240+ else:
2241+ logger.debug("Linking Video")
2242+ self.videoconvert.link(self.videnc)
2243+ self.videnc.link(self.vid_out_queue)
2244+
2245+ self.vid_out_queue.link(self.mux)
2246+
2247+ if self.audio_source:
2248+ logger.debug("Linking Audio")
2249+ ret = self.audiosrc.link(self.aud_in_queue)
2250+ logger.debug(" Link audiosrc -> aud_in_queue: %s" % ret)
2251+ ret = self.aud_in_queue.link(self.aud_caps_filter)
2252+ logger.debug(" Link aud_in_queue -> aud_caps_filter: %s" % ret)
2253+
2254+ if self.audio2_source:
2255+ logger.debug("Linking Audio2")
2256+ # Link first audio source to mixer
2257+ ret = self.aud_caps_filter.link(self.audiomixer)
2258+ logger.debug(" Link aud_caps_filter -> audiomixer: %s" % ret)
2259+
2260+ # Link second audio source to mixer
2261+ ret = self.audio2src.link(self.aud2_in_queue)
2262+ logger.debug(" Link audio2src -> aud2_in_queue: %s" % ret)
2263+ ret = self.aud2_in_queue.link(self.aud2_caps_filter)
2264+ logger.debug(" Link aud2_in_queue -> aud2_caps_filter: %s" % ret)
2265+ ret = self.aud2_caps_filter.link(self.audiomixer)
2266+ logger.debug(" Link aud2_caps_filter -> audiomixer: %s" % ret)
2267+
2268+ # Link mixer to audio convert
2269+ ret = self.audiomixer.link(self.audioconv)
2270+ logger.debug(" Link audiomixer -> audioconv: %s" % ret)
2271+
2272+ else:
2273+ # Link first audio source to audio convert
2274+ ret = self.aud_caps_filter.link(self.audioconv)
2275+ logger.debug(" Link aud_caps_filter -> audioconv: %s" % ret)
2276+
2277+ # Link audio to muxer
2278+ ret = self.audioconv.link(self.audioenc)
2279+ logger.debug("Link audioconv -> audioenc: %s" % ret)
2280+ ret = self.audioenc.link(self.aud_out_queue)
2281+ logger.debug("Link audioenc -> aud_out_queue: %s" % ret)
2282+ ret = self.aud_out_queue.link(self.mux)
2283+ logger.debug("Link aud_out_queue -> mux: %s" % ret)
2284+
2285+ ret = self.mux.link(self.file_queue)
2286+ logger.debug("Link mux -> file queue: %s" % ret)
2287+ ret = self.file_queue.link(self.sink)
2288+ logger.debug("Link file queue -> sink: %s" % ret)
2289+
2290+ def start_recording(self):
2291+ logger.debug("Setting STATE_PLAYING")
2292+ self.pipeline.set_state(Gst.State.PLAYING)
2293+
2294+ def pause_recording(self):
2295+ logger.debug("Setting STATE_PAUSED")
2296+ self.pipeline.set_state(Gst.State.PAUSED)
2297+
2298+ def unpause_recording(self):
2299+ logger.debug("Setting STATE_PLAYING - UNPAUSE")
2300+ self.pipeline.set_state(Gst.State.PLAYING)
2301+
2302+ def stop_recording(self):
2303+ logger.debug("Sending new EOS event")
2304+ self.pipeline.send_event(Gst.Event.new_eos())
2305+
2306+ def get_tempfile(self):
2307+ return self.tempfile
2308+
2309+ def get_audio_recorded(self):
2310+ return self.audio
2311+
2312+ def on_message(self, bus, message):
2313+ t = message.type
2314+ if t == Gst.MessageType.EOS:
2315+ logger.debug("Received EOS, setting pipeline to NULL.")
2316+ self.pipeline.set_state(Gst.State.NULL)
2317+ logger.debug("Emitting flush-done.")
2318+ self.emit("flush-done")
2319+ elif t == Gst.MessageType.ERROR:
2320+ logger.debug("Received an error message: %s", message.parse_error()[1])
2321+
2322+
2323+def detect_codecs():
2324+ codecs_supported = []
2325+ codec_test = None
2326+ for codec in CODEC_LIST:
2327+ if codec[0]:
2328+ try:
2329+ codec_test = Gst.ElementFactory.make(codec[1], "video_encoder")
2330+ except:
2331+ logger.info("Unable to find {0} GStreamer plugin - support disabled.".format(codec))
2332+ codec_test = None
2333+
2334+ if codec_test:
2335+ codecs_supported.append(codec[0])
2336+ logger.info("Supported encoder: {0}.".format(codec[2]))
2337+ else:
2338+ # RAW codec is None, so we don't try to load it.
2339+ codecs_supported.append(codec[0])
2340+ logger.info("Supported encoder: {0}.".format(codec[2]))
2341+ codec_test = None
2342+ return codecs_supported
2343+
2344+def get_codec(codec):
2345+ for c in CODEC_LIST:
2346+ if c[0] == codec:
2347+ return c
2348+ return None
2349
2350=== added file 'build/lib.linux-x86_64-2.7/kazam/backend/prefs.py'
2351--- build/lib.linux-x86_64-2.7/kazam/backend/prefs.py 1970-01-01 00:00:00 +0000
2352+++ build/lib.linux-x86_64-2.7/kazam/backend/prefs.py 2012-11-15 10:17:01 +0000
2353@@ -0,0 +1,232 @@
2354+# -*- coding: utf-8 -*-
2355+#
2356+# prefs.py
2357+#
2358+# Copyright 2012 David Klasinc <bigwhale@lubica.net>
2359+#
2360+# This program is free software; you can redistribute it and/or modify
2361+# it under the terms of the GNU General Public License as published by
2362+# the Free Software Foundation; either version 3 of the License, or
2363+# (at your option) any later version.
2364+#
2365+# This program is distributed in the hope that it will be useful,
2366+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2367+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2368+# GNU General Public License for more details.
2369+#
2370+# You should have received a copy of the GNU General Public License
2371+# along with this program; if not, write to the Free Software
2372+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
2373+# MA 02110-1301, USA.
2374+
2375+import os
2376+import logging
2377+from gettext import gettext as _
2378+from xdg.BaseDirectory import xdg_config_home
2379+
2380+from kazam.backend.config import KazamConfig
2381+
2382+
2383+class Prefs():
2384+ def __init__(self):
2385+ """Initialize prefs and set all the preference variables to their
2386+ default values.
2387+
2388+ Args:
2389+ None
2390+
2391+ Returns:
2392+ None
2393+
2394+ Raises:
2395+ None
2396+ """
2397+ self.logger = logging.getLogger("Prefs")
2398+
2399+ #
2400+ # GUI preferences and stuff
2401+ #
2402+ self.capture_cursor = False
2403+ self.capture_speakers = False
2404+ self.capture_microphone = False
2405+
2406+ self.capture_cursor_pic = False
2407+ self.capture_borders_pic = False
2408+
2409+ self.countdown_timer = 5
2410+
2411+ self.speakers_source = None
2412+ self.microphone_source = None
2413+
2414+ self.speakers_volume = 0
2415+ self.microphone_volume = 0
2416+
2417+ self.countdown_splash = True
2418+ self.silent_start = False
2419+
2420+ #
2421+ # Other stuff
2422+ #
2423+ self.datadir = None
2424+
2425+ #
2426+ # Capture related stuff
2427+ #
2428+ self.codec = None
2429+ self.pa_q = None
2430+ self.framerate = 15
2431+ self.autosave_video = False
2432+ self.autosave_video_file = None
2433+
2434+ self.autosave_picture = False
2435+ self.autosave_picture_file = None
2436+ self.shutter_sound = True
2437+ self.shutter_type = 0
2438+ self.shutter_sound_file = ""
2439+
2440+ self.area = None
2441+ self.xid = None
2442+ self.xid_geometry = None
2443+
2444+ #
2445+ # Audio sources
2446+ # - Tuple of all sources
2447+ # - Selected first source
2448+ # - Selected second source
2449+ #
2450+ self.audio_sources = None
2451+ self.audio_source = None
2452+ self.audio2_source = None
2453+
2454+ #
2455+ # Command line parameters
2456+ #
2457+ self.debug = False
2458+ self.test = False
2459+ self.dist = ('Ubuntu', '12.10', 'quantal')
2460+ self.silent = False
2461+ self.sound = True
2462+
2463+ self.config = KazamConfig()
2464+
2465+ self.read_config()
2466+
2467+ self.get_dirs()
2468+
2469+ def get_audio_sources(self):
2470+ self.logger.debug("Getting Audio sources.")
2471+ try:
2472+ self.audio_sources = prefs.pa_q.get_audio_sources()
2473+ #self.audio_sources.insert(0, [])
2474+ if prefs.debug:
2475+ for src in self.audio_sources:
2476+ self.logger.debug(" Device found: ")
2477+ for item in src:
2478+ self.logger.debug(" - {0}".format(item))
2479+ except:
2480+ # Something went wrong, just fallback to no-sound
2481+ self.logger.warning("Unable to find any audio devices.")
2482+ self.audio_sources = [[0, _("Unknown"), _("Unknown")]]
2483+
2484+ def get_dirs(self):
2485+ paths = {}
2486+ f = None
2487+ try:
2488+ f = open(os.path.join(xdg_config_home, "user-dirs.dirs"))
2489+ for la in f:
2490+ if la.startswith("XDG_VIDEOS") or la.startswith("XDG_DOCUMENTS") or la.startswith("XDG_PICTURES") :
2491+ (idx, val) = la.strip()[:-1].split('="')
2492+ paths[idx] = os.path.expandvars(val)
2493+ except:
2494+ paths['XDG_VIDEOS_DIR'] = os.path.expanduser("~/Videos/")
2495+ paths['XDG_PICTURES_DIR'] = os.path.expanduser("~/Pictures/")
2496+ paths['XDG_DOCUMENTS_DIR'] = os.path.expanduser("~/Documents/")
2497+ finally:
2498+ if f is not None:
2499+ f.close()
2500+
2501+ paths['HOME_DIR'] = os.path.expandvars("$HOME")
2502+
2503+ if os.path.isdir(paths['XDG_VIDEOS_DIR']):
2504+ self.video_dest = paths['XDG_VIDEOS_DIR']
2505+ elif os.path.isdir(paths['XDG_DOCUMENTS_DIR']):
2506+ self.video_dest = paths['XDG_DOCUMENTS_DIR']
2507+ elif os.path.isdir(paths['HOME_DIR']):
2508+ self.video_dest = paths['HOME_DIR']
2509+
2510+ if os.path.isdir(paths['XDG_PICTURES_DIR']):
2511+ self.picture_dest = paths['XDG_PICTURES_DIR']
2512+ elif os.path.isdir(paths['XDG_DOCUMENTS_DIR']):
2513+ self.picture_dest = paths['XDG_DOCUMENTS_DIR']
2514+ elif os.path.isdir(paths['HOME_DIR']):
2515+ self.picture_dest = paths['HOME_DIR']
2516+
2517+
2518+ def get_sound_files(self):
2519+ self.sound_files = []
2520+ for root, dir, files in os.walk(os.path.join(self.datadir, "sounds")):
2521+ for file in files:
2522+ if file.endswith('.ogg'):
2523+ self.sound_files.append(file)
2524+
2525+
2526+ def read_config (self):
2527+ self.audio_source = self.config.getint("main", "audio_source")
2528+ self.audio2_source = self.config.getint("main", "audio2_source")
2529+
2530+ self.main_x = self.config.getint("main", "last_x")
2531+ self.main_y = self.config.getint("main", "last_y")
2532+
2533+ self.codec = self.config.getint("main", "codec")
2534+
2535+ self.countdown_timer = self.config.getfloat("main", "counter")
2536+ self.framerate = self.config.getfloat("main", "framerate")
2537+
2538+ self.capture_cursor = self.config.getboolean("main", "capture_cursor")
2539+ self.capture_microphone = self.config.getboolean("main", "capture_microphone")
2540+ self.capture_speakers = self.config.getboolean("main", "capture_speakers")
2541+
2542+ self.capture_cursor_pic = self.config.getboolean("main", "capture_cursor_pic")
2543+ self.capture_borders_pic = self.config.getboolean("main", "capture_borders_pic")
2544+
2545+ self.countdown_splash = self.config.getboolean("main", "countdown_splash")
2546+
2547+ self.autosave_video = self.config.getboolean("main", "autosave_video")
2548+ self.autosave_video_file = self.config.get("main", "autosave_video_file")
2549+
2550+ self.autosave_picture = self.config.getboolean("main", "autosave_picture")
2551+ self.autosave_picture_file = self.config.get("main", "autosave_picture_file")
2552+
2553+ self.shutter_sound = self.config.getboolean("main", "shutter_sound")
2554+ self.shutter_type = self.config.getint("main", "shutter_type")
2555+
2556+
2557+ def save_config(self):
2558+ self.config.set("main", "capture_cursor", self.capture_cursor)
2559+ self.config.set("main", "capture_speakers", self.capture_speakers)
2560+ self.config.set("main", "capture_microphone", self.capture_microphone)
2561+
2562+ self.config.set("main", "capture_cursor_pic", self.capture_cursor_pic)
2563+ self.config.set("main", "capture_borders_pic", self.capture_borders_pic)
2564+
2565+ self.config.set("main", "last_x", self.main_x)
2566+ self.config.set("main", "last_y", self.main_y)
2567+
2568+ if self.sound:
2569+ self.config.set("main", "audio_source", self.audio_source)
2570+ self.config.set("main", "audio2_source", self.audio2_source)
2571+
2572+ self.config.set("main", "countdown_splash", self.countdown_splash)
2573+ self.config.set("main", "counter", self.countdown_timer)
2574+ self.config.set("main", "codec", self.codec)
2575+ self.config.set("main", "framerate", self.framerate)
2576+ self.config.set("main", "autosave_video", self.autosave_video)
2577+ self.config.set("main", "autosave_video_file", self.autosave_video_file)
2578+ self.config.set("main", "autosave_picture", self.autosave_picture)
2579+ self.config.set("main", "autosave_picture_file", self.autosave_picture_file)
2580+ self.config.set("main", "shutter_sound", self.shutter_sound)
2581+ self.config.set("main", "shutter_type", self.shutter_type)
2582+
2583+ self.config.write()
2584+
2585+prefs = Prefs()
2586
2587=== added directory 'build/lib.linux-x86_64-2.7/kazam/frontend'
2588=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/__init__.py'
2589--- build/lib.linux-x86_64-2.7/kazam/frontend/__init__.py 1970-01-01 00:00:00 +0000
2590+++ build/lib.linux-x86_64-2.7/kazam/frontend/__init__.py 2012-11-15 10:17:01 +0000
2591@@ -0,0 +1,1 @@
2592+
2593
2594=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/about_dialog.py'
2595--- build/lib.linux-x86_64-2.7/kazam/frontend/about_dialog.py 1970-01-01 00:00:00 +0000
2596+++ build/lib.linux-x86_64-2.7/kazam/frontend/about_dialog.py 2012-11-15 10:17:01 +0000
2597@@ -0,0 +1,70 @@
2598+# -*- coding: utf-8 -*-
2599+#
2600+# authenticate.py
2601+#
2602+# Copyright 2012 David Klasinc <bigwhale@lubica.net>
2603+# Copyright 2010 Andrew <andrew@karmic-desktop>
2604+#
2605+# This program is free software; you can redistribute it and/or modify
2606+# it under the terms of the GNU General Public License as published by
2607+# the Free Software Foundation; either version 3 of the License, or
2608+# (at your option) any later version.
2609+#
2610+# This program is distributed in the hope that it will be useful,
2611+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2612+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2613+# GNU General Public License for more details.
2614+#
2615+# You should have received a copy of the GNU General Public License
2616+# along with this program; if not, write to the Free Software
2617+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
2618+# MA 02110-1301, USA.
2619+
2620+from gettext import gettext as _
2621+from gi.repository import Gtk
2622+from kazam.version import *
2623+
2624+AUTHORS = """
2625+Andrew Higginson <rugby471@gmail.com>
2626+David Klasinc <bigwhale@lubica.net>
2627+"""
2628+
2629+ARTISTS = """
2630+Robert McKenna <ttk1opc@yahoo.com>
2631+Andrew Higginson <rugby471@gmail.com>
2632+"""
2633+LICENSE = """
2634+ This program is free software: you can redistribute it and/or modify
2635+ it under the terms of the GNU General Public License as published by
2636+ the Free Software Foundation, either version 3 of the License, or
2637+ (at your option) any later version.
2638+
2639+ This program is distributed in the hope that it will be useful,
2640+ but WITHOUT ANY WARRANTY; without even the implied warranty of
2641+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2642+ GNU General Public License for more details.
2643+
2644+ You should have received a copy of the GNU General Public License
2645+ along with this program. If not, see <http://www.gnu.org/licenses/>.
2646+"""
2647+
2648+def AboutDialog(icons):
2649+ dialog = Gtk.AboutDialog()
2650+ dialog.set_program_name(_("Kazam Screencaster") + " - \"" + CODENAME + "\"")
2651+ dialog.set_comments(_("Record a video of activity on your screen."))
2652+ dialog.set_license(LICENSE)
2653+ dialog.set_version(VERSION)
2654+ dialog.set_copyright("© 2010 Andrew Higginson, © 2012 David Klasinc")
2655+ dialog.set_website("http://launchpad.net/kazam")
2656+ dialog.set_authors(AUTHORS.split("\n"))
2657+ dialog.set_artists(ARTISTS.split("\n"))
2658+ try:
2659+ icon = icons.load_icon("kazam", 96, Gtk.IconLookupFlags.GENERIC_FALLBACK)
2660+ dialog.set_logo(icon)
2661+ except:
2662+ # Not important, we just don't get to show our lovely logo.. :)
2663+ pass
2664+ dialog.show_all()
2665+ dialog.set_position(Gtk.WindowPosition.CENTER)
2666+ dialog.run()
2667+ dialog.hide()
2668
2669=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/combobox.py'
2670--- build/lib.linux-x86_64-2.7/kazam/frontend/combobox.py 1970-01-01 00:00:00 +0000
2671+++ build/lib.linux-x86_64-2.7/kazam/frontend/combobox.py 2012-11-15 10:17:01 +0000
2672@@ -0,0 +1,116 @@
2673+# -*- coding: utf-8 -*-
2674+#
2675+# combobox.py
2676+#
2677+# Copyright 2012 David Klasinc <bigwhale@lubica.net>
2678+# Copyright 2010 Andrew <andrew@karmic-desktop>
2679+#
2680+# This program is free software; you can redistribute it and/or modify
2681+# it under the terms of the GNU General Public License as published by
2682+# the Free Software Foundation; either version 3 of the License, or
2683+# (at your option) any later version.
2684+#
2685+# This program is distributed in the hope that it will be useful,
2686+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2687+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2688+# GNU General Public License for more details.
2689+#
2690+# You should have received a copy of the GNU General Public License
2691+# along with this program; if not, write to the Free Software
2692+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
2693+# MA 02110-1301, USA.
2694+
2695+import os
2696+
2697+from xdg.DesktopEntry import DesktopEntry
2698+from gi.repository import Gtk, GdkPixbuf, GObject
2699+
2700+from kazam.backend.prefs import *
2701+
2702+class EditComboBox(Gtk.ComboBox):
2703+
2704+ KDENLIVE_VERSION = [0,8]
2705+
2706+ #
2707+ # This really needs to be done differently ...
2708+ #
2709+ if prefs.dist[2] == 'quantal':
2710+ EDITORS = {
2711+ "/usr/share/app-install/desktop/openshot:openshot.desktop":[],
2712+ "/usr/share/app-install/desktop/pitivi:pitivi.desktop":["-i", "-a"],
2713+ "/usr/share/app-install/desktop/avidemux:avidemux-gtk.desktop":[],
2714+ "/usr/share/app-install/desktop/kdenlive:kde4__kdenlive.desktop":["-i"],
2715+ }
2716+ else:
2717+ EDITORS = {
2718+ "/usr/share/applications/openshot.desktop":[],
2719+ "/usr/share/applications/pitivi.desktop":["-i", "-a"],
2720+ "/usr/share/applications/avidemux-gtk.desktop":[],
2721+ "/usr/share/applications/kde4/kdenlive.desktop":["-i"],
2722+ }
2723+
2724+ def __init__(self, icons):
2725+ Gtk.ComboBox.__init__(self)
2726+ self.icons = icons
2727+ self.empty = True
2728+ cr_pixbuf = Gtk.CellRendererPixbuf()
2729+ self.pack_start(cr_pixbuf, True)
2730+ self.add_attribute(cr_pixbuf, 'pixbuf', 0)
2731+ cr_text = Gtk.CellRendererText()
2732+ self.pack_start(cr_text, True)
2733+ self.add_attribute(cr_text, 'text', 1)
2734+
2735+ self.box_model = Gtk.ListStore(GdkPixbuf.Pixbuf, str,
2736+ GObject.TYPE_PYOBJECT,
2737+ GObject.TYPE_PYOBJECT
2738+ )
2739+ self.set_model(self.box_model)
2740+ self._populate()
2741+ self.set_active(0)
2742+ self.set_sensitive(True)
2743+ self.show()
2744+
2745+ def get_active_value(self):
2746+ i = self.get_active()
2747+ model = self.get_model()
2748+ model_iter = model.get_iter(i)
2749+ return (model.get_value(model_iter, 2),
2750+ model.get_value(model_iter, 3))
2751+
2752+ def _populate(self):
2753+ for item in self.EDITORS:
2754+ if os.path.isfile(item):
2755+ args = self.EDITORS[item]
2756+ desktop_entry = DesktopEntry(item)
2757+ command = desktop_entry.getExec()
2758+
2759+ # For .desktop files with ' %U' or ' # %F'
2760+ command = command.split(" ")[0]
2761+
2762+ name = desktop_entry.getName()
2763+ icon_name = desktop_entry.getIcon()
2764+
2765+ self._add_item(icon_name, name, command, args)
2766+
2767+ if len(self.get_model()):
2768+ self.empty = False
2769+ else:
2770+ self.empty = True
2771+
2772+ def _add_item(self, icon_name, name, command, args):
2773+ liststore = self.get_model()
2774+ try:
2775+ pixbuf = self.icons.load_icon(icon_name, 16, Gtk.IconLookupFlags.GENERIC_FALLBACK)
2776+ except:
2777+ pixbuf = self.icons.load_icon("application-x-executable", 16, Gtk.IconLookupFlags.GENERIC_FALLBACK)
2778+
2779+ liststore.append([pixbuf, name, command, args])
2780+
2781+ def _version_is_gte(self, required_version, current_version):
2782+ i = 0
2783+ for digit in current_version:
2784+ required_digit = required_version[i]
2785+ current_digit = int(digit)
2786+ if current_digit < required_digit:
2787+ return False
2788+ return True
2789
2790=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/done_recording.py'
2791--- build/lib.linux-x86_64-2.7/kazam/frontend/done_recording.py 1970-01-01 00:00:00 +0000
2792+++ build/lib.linux-x86_64-2.7/kazam/frontend/done_recording.py 2012-11-15 10:17:01 +0000
2793@@ -0,0 +1,159 @@
2794+# -*- coding: utf-8 -*-
2795+#
2796+# app.py
2797+#
2798+# Copyright 2012 David Klasinc <bigwhale@lubica.net>
2799+# Copyright 2010 Andrew <andrew@karmic-desktop>
2800+#
2801+# This program is free software; you can redistribute it and/or modify
2802+# it under the terms of the GNU General Public License as published by
2803+# the Free Software Foundation; either version 3 of the License, or
2804+# (at your option) any later version.
2805+#
2806+# This program is distributed in the hope that it will be useful,
2807+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2808+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2809+# GNU General Public License for more details.
2810+#
2811+# You should have received a copy of the GNU General Public License
2812+# along with this program; if not, write to the Free Software
2813+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
2814+# MA 02110-1301, USA.
2815+
2816+import os
2817+import shutil
2818+import logging
2819+logger = logging.getLogger("Done Recording")
2820+
2821+from gettext import gettext as _
2822+from gi.repository import Gtk, GObject
2823+
2824+from kazam.backend.constants import *
2825+from kazam.frontend.combobox import EditComboBox
2826+from kazam.frontend.save_dialog import SaveDialog
2827+
2828+class DoneRecording(Gtk.Window):
2829+
2830+ __gsignals__ = {
2831+ "save-done" : (GObject.SIGNAL_RUN_LAST,
2832+ None,
2833+ [GObject.TYPE_PYOBJECT],),
2834+ "edit-request" : (GObject.SIGNAL_RUN_LAST,
2835+ None,
2836+ [GObject.TYPE_PYOBJECT],),
2837+ "save-cancel" : (GObject.SIGNAL_RUN_LAST,
2838+ None,
2839+ (),)
2840+ }
2841+
2842+ def __init__(self, icons, tempfile, codec, old_path):
2843+ Gtk.Window.__init__(self, title=_("Kazam Screencaster - Recording finished"))
2844+ self.icons = icons
2845+ self.tempfile = tempfile
2846+ self.codec = codec
2847+ self.action = ACTION_SAVE
2848+ self.old_path = old_path
2849+ self.set_position(Gtk.WindowPosition.NONE)
2850+
2851+ # Setup UI
2852+ self.set_border_width(10)
2853+ self.vbox = Gtk.Box(spacing = 20, orientation = Gtk.Orientation.VERTICAL)
2854+ self.label_box = Gtk.Box()
2855+ self.done_label = Gtk.Label(_("Kazam finished recording.\nWhat do you want to do now?"))
2856+ self.label_box.add(self.done_label)
2857+ self.grid = Gtk.Grid(row_spacing = 10, column_spacing = 5)
2858+ self.radiobutton_edit = Gtk.RadioButton.new_with_label_from_widget(None, _("Edit with:"))
2859+ self.combobox_editor = EditComboBox(self.icons)
2860+ self.grid.add(self.radiobutton_edit)
2861+ self.grid.attach_next_to(self.combobox_editor,
2862+ self.radiobutton_edit,
2863+ Gtk.PositionType.RIGHT,
2864+ 1, 1)
2865+ self.radiobutton_save = Gtk.RadioButton.new_from_widget(self.radiobutton_edit)
2866+ self.radiobutton_save.set_label(_("Save for later"))
2867+
2868+ if self.combobox_editor.empty:
2869+ self.radiobutton_edit.set_active(False)
2870+ self.radiobutton_edit.set_sensitive(False)
2871+
2872+ self.radiobutton_save.set_active(True)
2873+
2874+ self.radiobutton_save.connect("toggled", self.cb_radiobutton_save_toggled)
2875+ self.radiobutton_edit.connect("toggled", self.cb_radiobutton_edit_toggled)
2876+ self.btn_cancel = Gtk.Button(label = _("Cancel"))
2877+ self.btn_cancel.set_size_request(100, -1)
2878+ self.btn_continue = Gtk.Button(label = _("Continue"))
2879+ self.btn_continue.set_size_request(100, -1)
2880+
2881+ self.btn_continue.connect("clicked", self.cb_continue_clicked)
2882+ self.btn_cancel.connect("clicked", self.cb_cancel_clicked)
2883+
2884+ self.hbox = Gtk.Box(spacing = 10)
2885+ self.left_hbox = Gtk.Box()
2886+ self.right_hbox = Gtk.Box(spacing = 5)
2887+
2888+ self.right_hbox.pack_start(self.btn_cancel, False, True, 0)
2889+ self.right_hbox.pack_start(self.btn_continue, False, True, 0)
2890+
2891+ self.hbox.pack_start(self.left_hbox, True, True, 0)
2892+ self.hbox.pack_start(self.right_hbox, False, False, 0)
2893+
2894+ self.vbox.pack_start(self.label_box, True, True, 0)
2895+ self.vbox.pack_start(self.grid, True, True, 0)
2896+ self.vbox.pack_start(self.radiobutton_save, True, True, 0)
2897+ self.vbox.pack_start(self.hbox, True, True, 0)
2898+ self.add(self.vbox)
2899+ self.connect("delete-event", self.cb_delete_event)
2900+ self.show_all()
2901+ self.present()
2902+
2903+
2904+ def cb_continue_clicked(self, widget):
2905+ if self.action == ACTION_EDIT:
2906+ logger.debug("Continue - Edit.")
2907+ (command, args) = self.combobox_editor.get_active_value()
2908+ self.emit("edit-request", (command, args))
2909+ self.destroy()
2910+ else:
2911+ self.set_sensitive(False)
2912+ logger.debug("Continue - Save ({0}).".format(self.codec))
2913+ (dialog, result, self.old_path) = SaveDialog(_("Save screencast"),
2914+ self.old_path, self.codec)
2915+
2916+ if result == Gtk.ResponseType.OK:
2917+ uri = os.path.join(dialog.get_current_folder(), dialog.get_filename())
2918+
2919+ if not uri.endswith(CODEC_LIST[self.codec][3]):
2920+ uri += CODEC_LIST[self.codec][3]
2921+
2922+ shutil.move(self.tempfile, uri)
2923+ dialog.destroy()
2924+ self.emit("save-done", self.old_path)
2925+ self.destroy()
2926+ else:
2927+ self.set_sensitive(True)
2928+ dialog.destroy()
2929+
2930+
2931+ def cb_cancel_clicked(self, widget):
2932+ self.emit("save-cancel")
2933+ self.destroy()
2934+
2935+ def cb_delete_event(self, widget, data):
2936+ self.emit("save-cancel")
2937+ self.destroy()
2938+
2939+ def cb_radiobutton_save_toggled(self, widget):
2940+ if not widget.get_active():
2941+ return
2942+ else:
2943+ self.action = ACTION_SAVE
2944+ self.combobox_editor.set_sensitive(False)
2945+
2946+ def cb_radiobutton_edit_toggled(self, widget):
2947+ if not widget.get_active():
2948+ return
2949+ else:
2950+ self.action = ACTION_EDIT
2951+ self.combobox_editor.set_sensitive(True)
2952+
2953
2954=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/export.py'
2955--- build/lib.linux-x86_64-2.7/kazam/frontend/export.py 1970-01-01 00:00:00 +0000
2956+++ build/lib.linux-x86_64-2.7/kazam/frontend/export.py 2012-11-15 10:17:01 +0000
2957@@ -0,0 +1,269 @@
2958+# -*- coding: utf-8 -*-
2959+#
2960+# export_frontend.py
2961+#
2962+# Copyright 2012 David Klasinc <bigwhale@lubica.net>
2963+# Copyright 2010 Andrew <andrew@karmic-desktop>
2964+#
2965+# This program is free software; you can redistribute it and/or modify
2966+# it under the terms of the GNU General Public License as published by
2967+# the Free Software Foundation; either version 3 of the License, or
2968+# (at your option) any later version.
2969+#
2970+# This program is distributed in the hope that it will be useful,
2971+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2972+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2973+# GNU General Public License for more details.
2974+#
2975+# You should have received a copy of the GNU General Public License
2976+# along with this program; if not, write to the Free Software
2977+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
2978+# MA 02110-1301, USA.
2979+
2980+import logging
2981+import os
2982+
2983+from gettext import gettext as _
2984+from gi.repository import Gtk, GObject
2985+
2986+from kazam.utils import *
2987+from kazam.backend.export import ExportBackend
2988+
2989+class ExportFrontend(GObject.GObject):
2990+
2991+ __gsignals__ = {
2992+ "back-requested" : (GObject.SIGNAL_RUN_LAST,
2993+ GObject.TYPE_NONE,
2994+ ( ),),
2995+ "export-requested" : (GObject.SIGNAL_RUN_LAST,
2996+ GObject.TYPE_NONE,
2997+ ( ),)
2998+ }
2999+
3000+ def __init__(self, datadir, icons, recorder):
3001+ GObject.GObject.__init__(self)
3002+
3003+ self.recorder = recorder
3004+
3005+ # Setup Backend
3006+ self.backend = ExportBackend(self, datadir)
3007+ self.backend.connect("authenticate-requested", self.cb_authenticate_requested)
3008+ self.backend.connect("login-started", self.cb_login_started)
3009+ self.backend.connect("login-completed", self.cb_login_completed)
3010+ self.backend.connect("convert-started", self.cb_convert_started)
3011+ self.backend.connect("convert-completed", self.cb_convert_completed)
3012+ self.backend.connect("upload-started", self.cb_upload_started)
3013+ self.backend.connect("upload-completed", self.cb_upload_completed)
3014+
3015+ self.active_alignment = None
3016+
3017+ # Setup UI
3018+ builder = Gtk.Builder()
3019+ builder.add_from_file(os.path.join(datadir, "ui", "export.ui"))
3020+
3021+ # Get window
3022+ self.window = builder.get_object("window_export")
3023+ self.window.connect("delete-event", Gtk.main_quit)
3024+
3025+ # Setup quality sliders
3026+ self.setup_quality_sliders()
3027+
3028+ # Export combobox setup
3029+ export_objects = self.backend.get_export_objects()
3030+ export_object_details = []
3031+ for obj in export_objects:
3032+ name = obj.NAME
3033+ icon = obj.ICONS[0]
3034+ tup = (icon, name)
3035+ export_object_details.append(tup)
3036+
3037+ self.combobox_export = ExportCombobox(self.icons, export_object_details)
3038+ self.combobox_export.connect("changed", self.on_combobox_export_changed)
3039+ self.hbox_export.pack_start(self.combobox_export, False, True)
3040+ self.hbox_export.reorder_child(self.combobox_export, 1)
3041+ self.on_combobox_export_changed(None)
3042+
3043+ def run(self):
3044+ self.window.show_all()
3045+
3046+ def setup_quality_sliders(self):
3047+
3048+ if self.screencast.get_video_recorded():
3049+ # Video Quality Slider
3050+ self.adjustment_quality_video = Gtk.Adjustment(3000, 200, 6001, 1)
3051+ self.hscale_quality_video = Gtk.HScale(self.adjustment_quality_video)
3052+ self.hscale_quality_video.set_draw_value(False)
3053+ self.hbox_quality_video.pack_start(self.hscale_quality_video)
3054+ else:
3055+ self.vbox_quality_video.destroy()
3056+
3057+ # (If audio was recorded) Audio Quality Slider
3058+ if self.screencast.get_audio_recorded():
3059+ self.adjustment_quality_audio = Gtk.Adjustment(140, 32, 256, 1)
3060+ self.hscale_quality_audio = Gtk.HScale(self.adjustment_quality_audio)
3061+ self.hscale_quality_audio.set_draw_value(False)
3062+ self.hbox_quality_audio.pack_start(self.hscale_quality_audio)
3063+ else:
3064+ self.vbox_quality_audio.destroy()
3065+
3066+ def on_button_back_clicked(self, button):
3067+ self.emit("back-requested")
3068+ self.window.destroy()
3069+
3070+ def on_button_export_clicked(self, button):
3071+ self.emit("export-requested")
3072+
3073+ def on_combobox_export_changed(self, combobox):
3074+ # If we already have an alignment, unpack it
3075+ if self.active_alignment:
3076+ self.vbox_main.remove(self.active_alignment)
3077+
3078+ # Get our current item's object
3079+ i = self.combobox_export.get_active()
3080+ active_object = self.backend.set_active_export_object(i)
3081+ # And its alignment
3082+ self.active_alignment = active_object.alignment_properties
3083+
3084+ # Run the alignment's expose function
3085+ active_object.property_alignment_expose()
3086+
3087+ # Pack our alignment
3088+ self.vbox_main.pack_start(self.active_alignment, True, True)
3089+ self.vbox_main.reorder_child(self.active_alignment, 2)
3090+
3091+ def _change_status(self, img, text):
3092+ for child in self.hbox_status.get_children():
3093+ child.destroy()
3094+ if img == "spinner":
3095+ img_widget = gtk.Spinner()
3096+ img_widget.start()
3097+ else:
3098+ img_widget = Gtk.image_new_from_stock(img, Gtk.ICON_SIZE_MENU)
3099+ text_widget = Gtk.Label(text)
3100+ self.hbox_status.pack_start(img_widget, False, False)
3101+ self.hbox_status.pack_start(text_widget, False, False)
3102+ self.hbox_status.show_all()
3103+
3104+ def get_screencast(self):
3105+ return self.screencast
3106+
3107+ def get_meta(self):
3108+ active_export_object = self.backend.get_active_export_object()
3109+ meta = active_export_object.META.copy()
3110+ # For every property in the meta dict...
3111+ for prop in meta:
3112+ # ..get the corresponding widget in the meta dict
3113+ widget = getattr(active_export_object, meta[prop])
3114+ # ...get the corresponding widget value and add to the dict
3115+ # inplace of the widget
3116+ meta[prop] = self.get_property_value(widget)
3117+ return meta
3118+
3119+ def get_video_quality(self):
3120+ if self.screencast.get_video_recorded():
3121+ return self.adjustment_quality_video.get_value()
3122+ return False
3123+
3124+ def get_audio_quality(self):
3125+ if self.screencast.get_audio_recorded():
3126+ return self.adjustment_quality_audio.get_value()
3127+ return False
3128+
3129+ def get_property_value(self, widget):
3130+ # Convenience function to get property value based on widget type
3131+ if isinstance(widget, gtk.Entry):
3132+ return widget.get_text()
3133+ elif isinstance(widget, gtk.TextView):
3134+ buf = widget.get_buffer()
3135+ return buf.get_text(buf.get_start_iter(), buf.get_end_iter())
3136+ elif isinstance(widget, EasyTextAndObjectComboBox):
3137+ tuple_ = (widget.get_active_value(0), widget.get_active_value(1))
3138+ return tuple_
3139+ elif issubclass(widget.__class__, EasyComboBox):
3140+ return widget.get_active_value(0)
3141+
3142+ def sensitise_content_action_widgets(self, sensitive):
3143+ self.active_alignment.set_sensitive(sensitive)
3144+ self.button_export.set_sensitive(sensitive)
3145+ self.button_back.set_sensitive(sensitive)
3146+ self.combobox_export.set_sensitive(sensitive)
3147+ self.label_export.set_sensitive(sensitive)
3148+
3149+ def cb_authenticate_requested(self, backend, icons, name, register_url):
3150+ authenticate_dialog = AuthenticateDialog(self.datadir, name, self.icons, icons, register_url)
3151+ authenticate_dialog.window.set_transient_for(self.window)
3152+ authenticate_dialog.run()
3153+ self.window.set_sensitive(False)
3154+ while (not hasattr(authenticate_dialog, "details")):
3155+ if authenticate_dialog.action == authenticate_dialog.ACTION_CANCEL:
3156+ break
3157+ gtk.main_iteration()
3158+ self.window.set_sensitive(True)
3159+ if authenticate_dialog.action == authenticate_dialog.ACTION_CANCEL:
3160+ return
3161+ self.backend.details = authenticate_dialog.details
3162+
3163+ def cb_login_started(self, backend):
3164+ self._change_status("spinner", _("Logging in..."))
3165+ # Make buttons, combobox, label and the alignment insensitive
3166+ self.sensitise_content_action_widgets(False)
3167+
3168+ def cb_login_completed(self, backend, success):
3169+ if success:
3170+ self._change_status(gtk.STOCK_OK, _("Log-in completed."))
3171+ else:
3172+ self._change_status(gtk.STOCK_DIALOG_ERROR, _("There was an error logging in."))
3173+ # Set buttons, combobox and the alignment sensitive
3174+ self.sensitise_content_action_widgets(True)
3175+
3176+ def cb_convert_started(self, backend):
3177+ self._change_status("spinner", _("Converting screencast..."))
3178+
3179+ def cb_convert_completed(self, backend, success):
3180+ if success:
3181+ self._change_status(Gtk.STOCK_OK, _("Screencast converted."))
3182+ else:
3183+ self._change_status(Gtk.STOCK_DIALOG_ERROR, _("There was an error converting."))
3184+ # Set buttons, combobox and the alignment sensitive
3185+ self.sensitise_content_action_widgets(True)
3186+
3187+ def cb_upload_started(self, backend):
3188+ self._change_status("spinner", _("Uploading screencast..."))
3189+
3190+ def cb_upload_completed(self, backend, success, url):
3191+ if success:
3192+ self._change_status(Gtk.STOCK_OK, _("Screencast uploaded."))
3193+ # Set buttons, combobox and the alignment sensitive
3194+ self.sensitise_content_action_widgets(True)
3195+ # Show a dialog with the url of the uploaded file
3196+ new_linkbutton_dialog(url, _("Your screencast has uploaded successfully."),
3197+ _("It is available at the location below:"), self.window)
3198+ else:
3199+ self._change_status(Gtk.STOCK_DIALOG_ERROR, _("There was an error uploading."))
3200+ # Set buttons, combobox and the alignment sensitive
3201+ self.sensitise_content_action_widgets(True)
3202+
3203+
3204+#if __name__ == "__main__":
3205+# from kazam.backend.ffmpeg import Screencast
3206+#
3207+# if os.path.exists("./data/ui/export.ui"):
3208+# logging.info("Running locally")
3209+# datadir = "./data"
3210+# else:
3211+# datadir = "/usr/share/kazam/"
3212+# icons = gtk.icon_theme_get_default()
3213+# icons.append_search_path(os.path.join(datadir,"icons", "48x48", "apps"))
3214+# icons.append_search_path(os.path.join(datadir,"icons", "16x16", "apps"))
3215+
3216+# screencast = Screencast()
3217+# screencast.audio = True
3218+
3219+ # export = ExportFrontend(datadir, icons, screencast)
3220+ # export.connect("back-requested", gtk.main_quit)
3221+ # export.connect("export-requested", gtk.main_quit)
3222+ # export.connect("quit-requested", gtk.main_quit)
3223+ # export.run()
3224+ # gtk.main()
3225+
3226+
3227
3228=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/indicator.py'
3229--- build/lib.linux-x86_64-2.7/kazam/frontend/indicator.py 1970-01-01 00:00:00 +0000
3230+++ build/lib.linux-x86_64-2.7/kazam/frontend/indicator.py 2012-11-15 10:17:01 +0000
3231@@ -0,0 +1,311 @@
3232+# -*- coding: utf-8 -*-
3233+#
3234+# indicator.py
3235+#
3236+# Copyright 2012 David Klasinc <bigwhale@lubica.net>
3237+# Copyright 2010 Andrew <andrew@karmic-desktop>
3238+#
3239+# This program is free software; you can redistribute it and/or modify
3240+# it under the terms of the GNU General Public License as published by
3241+# the Free Software Foundation; either version 3 of the License, or
3242+# (at your option) any later version.
3243+#
3244+# This program is distributed in the hope that it will be useful,
3245+# but WITHOUT ANY WARRANTY; without even the implied warranty of
3246+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3247+# GNU General Public License for more details.
3248+#
3249+# You should have received a copy of the GNU General Public License
3250+# along with this program; if not, write to the Free Software
3251+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
3252+# MA 02110-1301, USA.
3253+
3254+import logging
3255+logger = logging.getLogger("Indicator")
3256+
3257+from gettext import gettext as _
3258+from gi.repository import Gtk, GObject
3259+
3260+from kazam.backend.constants import *
3261+
3262+class KazamSuperIndicator(GObject.GObject):
3263+ __gsignals__ = {
3264+ "indicator-pause-request" : (GObject.SIGNAL_RUN_LAST,
3265+ None,
3266+ (), ),
3267+ "indicator-unpause-request" : (GObject.SIGNAL_RUN_LAST,
3268+ None,
3269+ (), ),
3270+ "indicator-quit-request" : (GObject.SIGNAL_RUN_LAST,
3271+ None,
3272+ (), ),
3273+ "indicator-show-request" : (GObject.SIGNAL_RUN_LAST,
3274+ None,
3275+ (), ),
3276+ "indicator-stop-request" : (GObject.SIGNAL_RUN_LAST,
3277+ None,
3278+ (), ),
3279+ "indicator-start-request" : (GObject.SIGNAL_RUN_LAST,
3280+ None,
3281+ (), ),
3282+
3283+ "indicator-about-request" : (GObject.SIGNAL_RUN_LAST,
3284+ None,
3285+ (), ),
3286+ }
3287+
3288+ def __init__(self, silent = False):
3289+ super(KazamSuperIndicator, self).__init__()
3290+ self.blink_icon = BLINK_STOP_ICON
3291+ self.blink_state = False
3292+ self.blink_mode = BLINK_SLOW
3293+ self.recording = False
3294+ self.silent = silent
3295+ logger.debug("Indicatior silent: {0}".format(self.silent))
3296+
3297+ self.menu = Gtk.Menu()
3298+
3299+ self.menuitem_start = Gtk.MenuItem(_("Start recording"))
3300+ self.menuitem_start.set_sensitive(True)
3301+ self.menuitem_start.connect("activate", self.on_menuitem_start_activate)
3302+
3303+ self.menuitem_pause = Gtk.CheckMenuItem(_("Pause recording"))
3304+ self.menuitem_pause.set_sensitive(False)
3305+ self.menuitem_pause.connect("toggled", self.on_menuitem_pause_activate)
3306+
3307+ self.menuitem_finish = Gtk.MenuItem(_("Finish recording"))
3308+ self.menuitem_finish.set_sensitive(False)
3309+ self.menuitem_finish.connect("activate", self.on_menuitem_finish_activate)
3310+
3311+ self.menuitem_separator = Gtk.SeparatorMenuItem()
3312+ self.menuitem_separator2 = Gtk.SeparatorMenuItem()
3313+
3314+ self.menuitem_show = Gtk.MenuItem(_("Record setup"))
3315+ self.menuitem_show.connect("activate", self.on_menuitem_show_activate)
3316+
3317+ self.menuitem_about = Gtk.MenuItem(_("About"))
3318+ self.menuitem_about.connect("activate", self.on_menuitem_about_activate)
3319+
3320+
3321+ self.menuitem_quit = Gtk.MenuItem(_("Quit"))
3322+ self.menuitem_quit.connect("activate", self.on_menuitem_quit_activate)
3323+
3324+ self.menu.append(self.menuitem_start)
3325+ self.menu.append(self.menuitem_pause)
3326+ self.menu.append(self.menuitem_finish)
3327+ self.menu.append(self.menuitem_separator)
3328+ self.menu.append(self.menuitem_show)
3329+ self.menu.append(self.menuitem_about)
3330+ self.menu.append(self.menuitem_separator2)
3331+ self.menu.append(self.menuitem_quit)
3332+
3333+ self.menu.show_all()
3334+
3335+ #
3336+ # Setup keybindings - Hardcore way
3337+ #
3338+ try:
3339+ from gi.repository import Keybinder
3340+ logger.debug("Trying to bind hotkeys.")
3341+ Keybinder.init()
3342+ Keybinder.bind("<Super><Ctrl>R", self.cb_hotkeys, "start-request")
3343+ Keybinder.bind("<Super><Ctrl>F", self.cb_hotkeys, "stop-request")
3344+ Keybinder.bind("<Super><Ctrl>P", self.cb_hotkeys, "pause-request")
3345+ Keybinder.bind("<Super><Ctrl>W", self.cb_hotkeys, "show-request")
3346+ Keybinder.bind("<Super><Ctrl>Q", self.cb_hotkeys, "quit-request")
3347+ self.recording = False
3348+ except ImportError:
3349+ logger.info("Unable to import Keybinder, hotkeys not available.")
3350+
3351+ def cb_hotkeys(self, key, action):
3352+ logger.debug("KEY {0}, ACTION {1}".format(key, action))
3353+ if action == "start-request" and not self.recording:
3354+ self.on_menuitem_start_activate(None)
3355+ elif action == "stop-request" and self.recording:
3356+ self.on_menuitem_finish_activate(None)
3357+ elif action == "pause-request" and self.recording:
3358+ if not self.menuitem_pause.get_active():
3359+ self.menuitem_pause.set_active(True)
3360+ else:
3361+ self.menuitem_pause.set_active(False)
3362+ elif action == "show-request" and not self.recording:
3363+ self.emit("indicator-show-request")
3364+ elif action == "quit-request" and not self.recording:
3365+ self.emit("indicator-quit-request")
3366+
3367+ def on_menuitem_pause_activate(self, menuitem):
3368+ if self.menuitem_pause.get_active():
3369+ self.emit("indicator-pause-request")
3370+ else:
3371+ self.emit("indicator-unpause-request")
3372+
3373+ def on_menuitem_start_activate(self, menuitem):
3374+ self.recording = True
3375+ self.emit("indicator-start-request")
3376+
3377+ def on_menuitem_finish_activate(self, menuitem):
3378+ self.recording = False
3379+ self.menuitem_start.set_sensitive(True)
3380+ self.menuitem_pause.set_sensitive(False)
3381+ self.menuitem_pause.set_active(False)
3382+ self.menuitem_finish.set_sensitive(False)
3383+ self.menuitem_show.set_sensitive(True)
3384+ self.menuitem_quit.set_sensitive(True)
3385+ self.emit("indicator-stop-request")
3386+
3387+ def on_menuitem_quit_activate(self, menuitem):
3388+ self.emit("indicator-quit-request")
3389+
3390+ def on_menuitem_show_activate(self, menuitem):
3391+ self.emit("indicator-show-request")
3392+
3393+ def on_menuitem_about_activate(self, menuitem):
3394+ self.emit("indicator-about-request")
3395+
3396+try:
3397+ from gi.repository import AppIndicator3
3398+
3399+ class KazamIndicator(KazamSuperIndicator):
3400+ def __init__(self, silent = False):
3401+ super(KazamIndicator, self).__init__(silent)
3402+ self.silent = silent
3403+
3404+ self.indicator = AppIndicator3.Indicator.new("kazam",
3405+ "kazam-stopped",
3406+ AppIndicator3.IndicatorCategory.APPLICATION_STATUS)
3407+
3408+ self.indicator.set_menu(self.menu)
3409+ self.indicator.set_attention_icon("kazam-recording")
3410+ self.indicator.set_icon("kazam-stopped")
3411+
3412+ if self.silent:
3413+ self.indicator.set_status(AppIndicator3.IndicatorStatus.PASSIVE)
3414+ else:
3415+ self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
3416+
3417+ def hide_it(self):
3418+ self.indicator.set_status(AppIndicator3.IndicatorStatus.PASSIVE)
3419+
3420+ def show_it(self):
3421+ self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
3422+
3423+ def on_menuitem_pause_activate(self, menuitem):
3424+ if menuitem.get_active():
3425+ self.indicator.set_attention_icon("kazam-paused")
3426+ logger.debug("Recording paused.")
3427+ else:
3428+ self.indicator.set_attention_icon("kazam-recording")
3429+ logger.debug("Recording resumed.")
3430+ KazamSuperIndicator.on_menuitem_pause_activate(self, menuitem)
3431+
3432+ def on_menuitem_finish_activate(self, menuitem):
3433+ logger.debug("Recording stopped.")
3434+ if not self.silent:
3435+ self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
3436+ KazamSuperIndicator.on_menuitem_finish_activate(self, menuitem)
3437+
3438+ def blink_set_state(self, state):
3439+ if state == BLINK_STOP:
3440+ self.blink_state = BLINK_STOP
3441+ self.indicator.set_icon("kazam-stopped")
3442+ elif state == BLINK_START:
3443+ self.blink_state = BLINK_SLOW
3444+ GObject.timeout_add(500, self.blink)
3445+ elif state == BLINK_SLOW:
3446+ self.blink_state = BLINK_SLOW
3447+ elif state == BLINK_FAST:
3448+ self.blink_state = BLINK_FAST
3449+
3450+ def blink(self):
3451+ if self.blink_state != BLINK_STOP:
3452+ if self.blink_icon == BLINK_READY_ICON:
3453+ if not self.silent:
3454+ self.indicator.set_icon("kazam-stopped")
3455+ self.blink_icon = BLINK_STOP_ICON
3456+ else:
3457+ if not self.silent:
3458+ self.indicator.set_icon("kazam-countdown")
3459+ self.blink_icon = BLINK_READY_ICON
3460+
3461+ if self.blink_state == BLINK_SLOW:
3462+ GObject.timeout_add(500, self.blink)
3463+ elif self.blink_state == BLINK_FAST:
3464+ GObject.timeout_add(200, self.blink)
3465+
3466+ def start_recording(self):
3467+ logger.debug("Recording started.")
3468+ if not self.silent:
3469+ self.indicator.set_status(AppIndicator3.IndicatorStatus.ATTENTION)
3470+
3471+except ImportError:
3472+ #
3473+ # AppIndicator failed to import, not running Ubuntu?
3474+ # Fallback to Gtk.StatusIcon.
3475+ #
3476+ class KazamIndicator(KazamSuperIndicator):
3477+
3478+ def __init__(self, silent = False):
3479+ super(KazamIndicator, self).__init__()
3480+ self.silent = silent
3481+
3482+ self.indicator = Gtk.StatusIcon()
3483+ self.indicator.set_from_icon_name("kazam-stopped")
3484+ self.indicator.connect("popup-menu", self.cb_indicator_popup_menu)
3485+ self.indicator.connect("activate", self.cb_indicator_activate)
3486+
3487+ if self.silent:
3488+ self.indicator.set_visible(False)
3489+
3490+ def cb_indicator_activate(self, widget):
3491+ def position(menu, widget):
3492+ return (Gtk.StatusIcon.position_menu(self.menu, widget))
3493+ self.menu.popup(None, None, position, self.indicator, 0, Gtk.get_current_event_time())
3494+
3495+ def cb_indicator_popup_menu(self, icon, button, time):
3496+ def position(menu, icon):
3497+ return (Gtk.StatusIcon.position_menu(self.menu, icon))
3498+ self.menu.popup(None, None, position, self.indicator, button, time)
3499+
3500+ def on_menuitem_finish_activate(self, menuitem):
3501+ logger.debug("Recording stopped.")
3502+ self.indicator.set_from_icon_name("kazam-stopped")
3503+ KazamSuperIndicator.on_menuitem_finish_activate(self, menuitem)
3504+
3505+ def on_menuitem_pause_activate(self, menuitem):
3506+ if menuitem.get_active():
3507+ self.indicator.set_from_icon_name("kazam-paused")
3508+ logger.debug("Recording paused.")
3509+ else:
3510+ self.indicator.set_from_icon_name("kazam-recording")
3511+ logger.debug("Recording resumed.")
3512+ KazamSuperIndicator.on_menuitem_pause_activate(self, menuitem)
3513+
3514+ def blink_set_state(self, state):
3515+ if state == BLINK_STOP:
3516+ self.blink_state = BLINK_STOP
3517+ self.indicator.set_from_icon_name("kazam-stopped")
3518+ elif state == BLINK_START:
3519+ self.blink_state = BLINK_SLOW
3520+ GObject.timeout_add(500, self.blink)
3521+ elif state == BLINK_SLOW:
3522+ self.blink_state = BLINK_SLOW
3523+ elif state == BLINK_FAST:
3524+ self.blink_state = BLINK_FAST
3525+
3526+ def blink(self):
3527+ if self.blink_state != BLINK_STOP:
3528+ if self.blink_icon == BLINK_READY_ICON:
3529+ self.indicator.set_from_icon_name("kazam-stopped")
3530+ self.blink_icon = BLINK_STOP_ICON
3531+ else:
3532+ self.indicator.set_from_icon_name("kazam-countdown")
3533+ self.blink_icon = BLINK_READY_ICON
3534+
3535+ if self.blink_state == BLINK_SLOW:
3536+ GObject.timeout_add(500, self.blink)
3537+ elif self.blink_state == BLINK_FAST:
3538+ GObject.timeout_add(200, self.blink)
3539+
3540+ def start_recording(self):
3541+ logger.debug("Recording started.")
3542+ self.indicator.set_from_icon_name("kazam-recording")
3543
3544=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/main_menu.py'
3545--- build/lib.linux-x86_64-2.7/kazam/frontend/main_menu.py 1970-01-01 00:00:00 +0000
3546+++ build/lib.linux-x86_64-2.7/kazam/frontend/main_menu.py 2012-11-15 10:17:01 +0000
3547@@ -0,0 +1,88 @@
3548+# -*- coding: utf-8 -*-
3549+#
3550+# main_menu.py
3551+#
3552+# Copyright 2012 David Klasinc <bigwhale@lubica.net>
3553+#
3554+# This program is free software; you can redistribute it and/or modify
3555+# it under the terms of the GNU General Public License as published by
3556+# the Free Software Foundation; either version 3 of the License, or
3557+# (at your option) any later version.
3558+#
3559+# This program is distributed in the hope that it will be useful,
3560+# but WITHOUT ANY WARRANTY; without even the implied warranty of
3561+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3562+# GNU General Public License for more details.
3563+#
3564+# You should have received a copy of the GNU General Public License
3565+# along with this program; if not, write to the Free Software
3566+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
3567+# MA 02110-1301, USA.
3568+
3569+from gettext import gettext as _
3570+
3571+from gi.repository import Gtk, GObject
3572+
3573+MENUBAR = """
3574+ <ui>
3575+ <menubar name='MenuBar'>
3576+ <menu action='FileMenu'>
3577+ <menuitem action='FilePreferences' />
3578+ <menuitem action='FileQuit' />
3579+ </menu>
3580+ <separator />
3581+ <menu action='HelpMenu'>
3582+ <menuitem action='HelpAbout' />
3583+ </menu>
3584+ </menubar>
3585+</ui>
3586+"""
3587+
3588+class MainMenu(GObject.GObject):
3589+ __gsignals__ = {
3590+ "file-preferences" : (GObject.SIGNAL_RUN_LAST,
3591+ None,
3592+ (),
3593+ ),
3594+ "file-quit" : (GObject.SIGNAL_RUN_LAST,
3595+ None,
3596+ (),
3597+ ),
3598+ "help-about" : (GObject.SIGNAL_RUN_LAST,
3599+ None,
3600+ (),
3601+ ),
3602+ }
3603+
3604+ def __init__(self):
3605+ GObject.GObject.__init__(self)
3606+
3607+ self.action_group = Gtk.ActionGroup("kazam_actions")
3608+ self.action_group.add_actions([
3609+ ("FileMenu", None, _("File")),
3610+ ("FileQuit", Gtk.STOCK_QUIT, _("Quit"), None, _("Quit Kazam"),
3611+ self.cb_file_quit),
3612+ ("FilePreferences", Gtk.STOCK_PREFERENCES, _("Preferences"), None, _("Open preferences"),
3613+ self.cb_file_preferences),
3614+ ("HelpMenu", None, _("Help")),
3615+ ("HelpAbout", None, _("About"), None , _("About Kazam"),
3616+ self.cb_help_about)
3617+ ])
3618+
3619+ self.uimanager = Gtk.UIManager()
3620+ self.uimanager.add_ui_from_string(MENUBAR)
3621+ self.uimanager.insert_action_group(self.action_group)
3622+ self.menubar = self.uimanager.get_widget("/MenuBar")
3623+
3624+
3625+ def cb_file_quit(self, action):
3626+ self.emit("file-quit")
3627+
3628+ def cb_file_preferences(self, action):
3629+ self.emit("file-preferences")
3630+
3631+ def cb_help_about(self, action):
3632+ self.emit("help-about")
3633+
3634+
3635+
3636
3637=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/preferences.py'
3638--- build/lib.linux-x86_64-2.7/kazam/frontend/preferences.py 1970-01-01 00:00:00 +0000
3639+++ build/lib.linux-x86_64-2.7/kazam/frontend/preferences.py 2012-11-15 10:17:01 +0000
3640@@ -0,0 +1,375 @@
3641+# -*- coding: utf-8 -*-
3642+#
3643+# preferences.py
3644+#
3645+# Copyright 2012 David Klasinc <bigwhale@lubica.net>
3646+#
3647+# This program is free software; you can redistribute it and/or modify
3648+# it under the terms of the GNU General Public License as published by
3649+# the Free Software Foundation; either version 3 of the License, or
3650+# (at your option) any later version.
3651+#
3652+# This program is distributed in the hope that it will be useful,
3653+# but WITHOUT ANY WARRANTY; without even the implied warranty of
3654+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3655+# GNU General Public License for more details.
3656+#
3657+# You should have received a copy of the GNU General Public License
3658+# along with this program; if not, write to the Free Software
3659+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
3660+# MA 02110-1301, USA.
3661+
3662+import os
3663+import math
3664+import logging
3665+logger = logging.getLogger("Preferences")
3666+
3667+from gi.repository import Gtk, Gdk, GObject, Pango
3668+from gettext import gettext as _
3669+
3670+from kazam.utils import *
3671+from kazam.backend.prefs import *
3672+from kazam.backend.constants import *
3673+from kazam.backend.gstreamer import detect_codecs, get_codec
3674+
3675+class Preferences(GObject.GObject):
3676+ __gsignals__ = {
3677+ "prefs-quit" : (GObject.SIGNAL_RUN_LAST,
3678+ None,
3679+ (),
3680+ ),
3681+ }
3682+
3683+ def __init__(self):
3684+ GObject.GObject.__init__(self)
3685+ logger.debug("Preferences Init.")
3686+ #
3687+ # Setup UI
3688+ #
3689+ logger.debug("Preferences UI setup.")
3690+
3691+ self.audio_source_info = None
3692+ self.audio2_source_info = None
3693+
3694+ self.builder = Gtk.Builder()
3695+ self.builder.add_from_file(os.path.join(prefs.datadir, "ui", "preferences.ui"))
3696+ self.builder.connect_signals(self)
3697+ for w in self.builder.get_objects():
3698+ if issubclass(type(w), Gtk.Buildable):
3699+ name = Gtk.Buildable.get_name(w)
3700+ setattr(self, name, w)
3701+ else:
3702+ logger.debug("Unable to get name for '%s'" % w)
3703+
3704+ codec_renderer = Gtk.CellRendererText()
3705+
3706+ audio_renderer = Gtk.CellRendererText()
3707+ audio_renderer.props.ellipsize = Pango.EllipsizeMode.END
3708+ audio_renderer.props.max_width_chars = 40
3709+
3710+ self.combobox_codec.pack_start(codec_renderer, True)
3711+ self.combobox_codec.add_attribute(codec_renderer, "text", 1)
3712+
3713+ self.combobox_audio.pack_start(audio_renderer, True)
3714+ self.combobox_audio.add_attribute(audio_renderer, "text", 0)
3715+
3716+ self.combobox_audio2.pack_start(audio_renderer, True)
3717+ self.combobox_audio2.add_attribute(audio_renderer, "text", 0)
3718+
3719+ self.filechooser_video.set_current_folder(prefs.video_dest)
3720+
3721+ self.populate_codecs()
3722+ self.populate_audio_sources()
3723+ self.populate_shutter_sounds()
3724+
3725+ self.restore_UI()
3726+
3727+ def open(self):
3728+ self.window.show_all()
3729+
3730+ def is_separator(self, model, iter, data):
3731+ if model.get_value(iter, 0) == 99:
3732+ return True
3733+ return False
3734+
3735+ def populate_codecs(self):
3736+ #
3737+ # Is this necessary?
3738+ #
3739+ old_model = self.combobox_codec.get_model()
3740+ old_model = None
3741+
3742+ codec_model = Gtk.ListStore(int, str)
3743+ codecs = detect_codecs()
3744+
3745+ #
3746+ # I'm sure this could be done without going through the list twice, right?
3747+ # Fist, we add basic codecs, then a dummy separator item and then advanced codecs.
3748+ #
3749+
3750+ for codec in codecs:
3751+ if not CODEC_LIST[codec][4]:
3752+ codec_model.append([CODEC_LIST[codec][0], CODEC_LIST[codec][2]])
3753+
3754+ codec_model.append([99, "--"]) # Insert dummy item for separator
3755+
3756+ for codec in codecs:
3757+ if CODEC_LIST[codec][4]:
3758+ codec_model.append([CODEC_LIST[codec][0], CODEC_LIST[codec][2]])
3759+
3760+ self.combobox_codec.set_model(codec_model)
3761+ self.combobox_codec.set_row_separator_func(self.is_separator, None)
3762+
3763+ def populate_audio_sources(self):
3764+ audio_source_model = Gtk.ListStore(str)
3765+ for source in prefs.audio_sources:
3766+ audio_source_model.append([source[2]])
3767+
3768+ self.combobox_audio.set_model(audio_source_model)
3769+ self.combobox_audio2.set_model(audio_source_model)
3770+
3771+ def populate_shutter_sounds(self):
3772+ for file in prefs.sound_files:
3773+ self.combobox_shutter_type.append(None, file[:-4])
3774+
3775+ def restore_UI(self):
3776+ logger.debug("Restoring UI.")
3777+
3778+ if prefs.sound:
3779+ self.combobox_audio.set_active(prefs.audio_source)
3780+ self.combobox_audio2.set_active(prefs.audio2_source)
3781+ else:
3782+ self.combobox_audio.set_sensitive(False)
3783+ self.combobox_audio2.set_sensitive(False)
3784+ self.volumebutton_audio.set_sensitive(False)
3785+ self.volumebutton_audio2.set_sensitive(False)
3786+
3787+ if prefs.countdown_splash:
3788+ self.switch_countdown_splash.set_active(True)
3789+ else:
3790+ self.switch_countdown_splash.set_active(False)
3791+
3792+ self.spinbutton_framerate.set_value(prefs.framerate)
3793+
3794+ if prefs.autosave_video:
3795+ self.switch_autosave_video.set_active(True)
3796+ self.filechooser_video.set_sensitive(True)
3797+ self.entry_autosave_video.set_sensitive(True)
3798+ else:
3799+ self.switch_autosave_video.set_active(False)
3800+ self.filechooser_video.set_sensitive(False)
3801+ self.entry_autosave_video.set_sensitive(False)
3802+
3803+ self.entry_autosave_video.set_text(prefs.autosave_video_file)
3804+
3805+ self.filechooser_video.set_current_folder(prefs.video_dest)
3806+
3807+
3808+ if prefs.shutter_sound:
3809+ self.switch_shutter_sound.set_active(True)
3810+ self.combobox_shutter_type.set_sensitive(True)
3811+ else:
3812+ self.switch_shutter_sound.set_active(False)
3813+ self.combobox_shutter_type.set_sensitive(False)
3814+
3815+ self.combobox_shutter_type.set_active(prefs.shutter_type)
3816+
3817+ if prefs.autosave_picture:
3818+ self.switch_autosave_picture.set_active(True)
3819+ self.filechooser_picture.set_sensitive(True)
3820+ self.entry_autosave_picture.set_sensitive(True)
3821+
3822+ else:
3823+ self.switch_autosave_picture.set_active(False)
3824+ self.filechooser_picture.set_sensitive(False)
3825+ self.entry_autosave_picture.set_sensitive(False)
3826+
3827+ self.entry_autosave_picture.set_text(prefs.autosave_picture_file)
3828+
3829+ self.filechooser_picture.set_current_folder(prefs.picture_dest)
3830+
3831+
3832+ #
3833+ # Crappy code below ... Can this be done some other way?
3834+ #
3835+ codec_model = self.combobox_codec.get_model()
3836+ cnt = 0
3837+ bingo = False
3838+ for entry in codec_model:
3839+ if prefs.codec == entry[0]:
3840+ bingo = True
3841+ break
3842+ cnt += 1
3843+ if not bingo:
3844+ cnt = 0
3845+
3846+ #
3847+ # No, I wasn't kidding ...
3848+ #
3849+ codec_iter = codec_model.get_iter(cnt)
3850+ self.combobox_codec.set_active_iter(codec_iter)
3851+ prefs.codec = codec_model.get_value(codec_iter, 0)
3852+
3853+ #
3854+ # General callbacks
3855+ #
3856+
3857+ def cb_delete_event(self, widget, user_data):
3858+ logger.debug("Deleteting preferences window")
3859+ self.emit("prefs-quit")
3860+
3861+ def cb_switch_countdown_splash(self, widget, user_data):
3862+ prefs.countdown_splash = widget.get_active()
3863+ logger.debug("Countdown splash: {0}.".format(prefs.countdown_splash))
3864+
3865+ def cb_audio_changed(self, widget):
3866+ logger.debug("Audio Changed.")
3867+ prefs.audio_source = self.combobox_audio.get_active()
3868+ logger.debug(" - A_1 {0}".format(prefs.audio_source))
3869+
3870+ pa_audio_idx = prefs.audio_sources[prefs.audio_source][0]
3871+ prefs.pa_q.set_source_mute_by_index(pa_audio_idx, 0)
3872+
3873+ logger.debug(" - PA Audio1 IDX: {0}".format(pa_audio_idx))
3874+ self.audio_source_info = prefs.pa_q.get_source_info_by_index(pa_audio_idx)
3875+ if len(self.audio_source_info) > 0:
3876+ val = prefs.pa_q.cvolume_to_dB(self.audio_source_info[2])
3877+ if math.isinf(val):
3878+ vol = 0
3879+ else:
3880+ vol = 60 + val
3881+ self.volumebutton_audio.set_value(vol)
3882+ else:
3883+ logger.debug("Error getting volume info for Audio 1")
3884+ if len(self.audio_source_info):
3885+ logger.debug("New Audio1: {0}".format(self.audio_source_info[3]))
3886+ else:
3887+ logger.debug("New Audio1: Error retrieving data.")
3888+
3889+ if prefs.audio_source == prefs.audio2_source:
3890+ if prefs.audio_source < len(prefs.audio_sources) - 1:
3891+ prefs.audio2_source += 1
3892+ else:
3893+ prefs.audio2_source = 0
3894+ self.combobox_audio2.set_active(prefs.audio2_source)
3895+
3896+ def cb_audio2_changed(self, widget):
3897+ logger.debug("Audio2 Changed.")
3898+
3899+ prefs.audio2_source = self.combobox_audio2.get_active()
3900+ logger.debug(" - A_2 {0}".format(prefs.audio2_source))
3901+
3902+ pa_audio2_idx = prefs.audio_sources[prefs.audio2_source][0]
3903+ prefs.pa_q.set_source_mute_by_index(pa_audio2_idx, 0)
3904+
3905+ logger.debug(" - PA Audio2 IDX: {0}".format(pa_audio2_idx))
3906+ self.audio2_source_info = prefs.pa_q.get_source_info_by_index(pa_audio2_idx)
3907+
3908+ if len(self.audio2_source_info) > 0:
3909+ val = prefs.pa_q.cvolume_to_dB(self.audio2_source_info[2])
3910+ if math.isinf(val):
3911+ vol = 0
3912+ else:
3913+ vol = 60 + val
3914+ self.volumebutton_audio2.set_value(vol)
3915+ else:
3916+ logger.debug("Error getting volume info for Audio 1")
3917+
3918+ if len(self.audio2_source_info):
3919+ logger.debug("New Audio2:\n {0}".format(self.audio2_source_info[3]))
3920+ else:
3921+ logger.debug("New Audio2:\n Error retrieving data.")
3922+
3923+ if prefs.audio_source == prefs.audio2_source:
3924+ if prefs.audio_source < len(prefs.audio_sources) - 1:
3925+ prefs.audio2_source += 1
3926+ else:
3927+ prefs.audio2_source = 0
3928+ self.combobox_audio2.set_active(prefs.audio2_source)
3929+
3930+ def cb_volume_changed(self, widget, value):
3931+ logger.debug("Volume 1 changed, new value: {0}".format(value))
3932+ idx = self.combobox_audio.get_active()
3933+ pa_idx = prefs.audio_sources[idx][0]
3934+ chn = self.audio_source_info[2].channels
3935+ cvol = prefs.pa_q.dB_to_cvolume(chn, value-60)
3936+ prefs.pa_q.set_source_volume_by_index(pa_idx, cvol)
3937+
3938+ def cb_volume2_changed(self, widget, value):
3939+ logger.debug("Volume 2 changed, new value: {0}".format(value))
3940+ idx = self.combobox_audio2.get_active()
3941+ pa_idx = prefs.audio_sources[idx][0]
3942+ chn = self.audio_source_info[2].channels
3943+ cvol = prefs.pa_q.dB_to_cvolume(chn, value-60)
3944+ prefs.pa_q.set_source_volume_by_index(pa_idx, cvol)
3945+
3946+ #
3947+ # Screencasting callbacks
3948+ #
3949+
3950+ def cb_spinbutton_framerate_change(self, widget):
3951+ prefs.framerate = widget.get_value_as_int()
3952+ logger.debug("Framerate now: {0}".format(prefs.framerate))
3953+
3954+ def cb_codec_changed(self, widget):
3955+ i = widget.get_active()
3956+ model = widget.get_model()
3957+ iter = model.get_iter(i)
3958+ prefs.codec = model.get_value(iter, 0)
3959+ logger.debug('Codec selected: {0} - {1}'.format(get_codec(prefs.codec)[2], prefs.codec))
3960+
3961+ def cb_switch_autosave_video(self, widget, user_data):
3962+ prefs.autosave_video = widget.get_active()
3963+ logger.debug("Autosave for Video: {0}.".format(prefs.autosave_video))
3964+
3965+ if prefs.autosave_video:
3966+ self.filechooser_video.set_sensitive(True)
3967+ self.entry_autosave_video.set_sensitive(True)
3968+ else:
3969+ self.filechooser_video.set_sensitive(False)
3970+ self.entry_autosave_video.set_sensitive(False)
3971+
3972+ def cb_filechooser_video(self, widget):
3973+ prefs.video_dest = self.filechooser_video.get_current_folder()
3974+ logger.debug("Video folder set to: {0}".format(prefs.video_dest))
3975+
3976+ def cb_entry_autosave_video(self, widget):
3977+ prefs.autosave_video_file = widget.get_text()
3978+ logger.debug("Video autosave file set to: {0}".format(prefs.autosave_video_file))
3979+
3980+ #
3981+ # Screenshot callbacks
3982+ #
3983+
3984+ def cb_switch_shutter_sound(self, widget, user_data):
3985+ prefs.shutter_sound = widget.get_active()
3986+ logger.debug("Shutter sound: {0}.".format(prefs.shutter_sound))
3987+
3988+ if prefs.shutter_sound:
3989+ self.combobox_shutter_type.set_sensitive(True)
3990+ else:
3991+ self.combobox_shutter_type.set_sensitive(False)
3992+
3993+ def cb_shutter_type(self, widget):
3994+ prefs.shutter_type = self.combobox_shutter_type.get_active()
3995+ logger.debug("Shutter type set to: {0} - {1}".format(prefs.shutter_type, prefs.shutter_sound_file))
3996+
3997+ def cb_switch_autosave_picture(self, widget, user_data):
3998+ prefs.autosave_picture = widget.get_active()
3999+ logger.debug("Autosave for Picture: {0}.".format(prefs.autosave_picture))
4000+
4001+ if prefs.autosave_picture:
4002+ self.filechooser_picture.set_sensitive(True)
4003+ self.entry_autosave_picture.set_sensitive(True)
4004+ else:
4005+ self.filechooser_picture.set_sensitive(False)
4006+ self.entry_autosave_picture.set_sensitive(False)
4007+
4008+ def cb_filechooser_picture(self, widget):
4009+ prefs.picture_dest = self.filechooser_picture.get_current_folder()
4010+ logger.debug("Picture folder set to: {0}".format(prefs.picture_dest))
4011+
4012+ def cb_entry_autosave_picture(self, widget):
4013+ prefs.autosave_picture_file = widget.get_text()
4014+ logger.debug("Picture autosave file set to: {0}".format(prefs.autosave_picture_file))
4015+
4016
4017=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/save_dialog.py'
4018--- build/lib.linux-x86_64-2.7/kazam/frontend/save_dialog.py 1970-01-01 00:00:00 +0000
4019+++ build/lib.linux-x86_64-2.7/kazam/frontend/save_dialog.py 2012-11-15 10:17:01 +0000
4020@@ -0,0 +1,62 @@
4021+# -*- coding: utf-8 -*-
4022+#
4023+# save_dialog.py
4024+#
4025+# Copyright 2012 David Klasinc <bigwhale@lubica.net>
4026+# Copyright 2010 Andrew <andrew@karmic-desktop>
4027+#
4028+# This program is free software; you can redistribute it and/or modify
4029+# it under the terms of the GNU General Public License as published by
4030+# the Free Software Foundation; either version 3 of the License, or
4031+# (at your option) any later version.
4032+#
4033+# This program is distributed in the hope that it will be useful,
4034+# but WITHOUT ANY WARRANTY; without even the implied warranty of
4035+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4036+# GNU General Public License for more details.
4037+#
4038+# You should have received a copy of the GNU General Public License
4039+# along with this program; if not, write to the Free Software
4040+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
4041+# MA 02110-1301, USA.
4042+
4043+import os
4044+import logging
4045+logger = logging.getLogger("Save Dialog")
4046+
4047+from gi.repository import Gtk
4048+from gettext import gettext as _
4049+from datetime import datetime
4050+from kazam.backend.prefs import *
4051+from kazam.backend.constants import *
4052+
4053+def SaveDialog(title, old_path, codec, main_mode=MODE_SCREENCAST):
4054+ logger.debug("Save dialog called.")
4055+ dialog = Gtk.FileChooserDialog(title, None,
4056+ Gtk.FileChooserAction.SAVE,
4057+ (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
4058+ _("Save"), Gtk.ResponseType.OK))
4059+
4060+
4061+ dt = datetime.today().strftime("%Y-%m-%d %H:%M:%S")
4062+ if main_mode == MODE_SCREENCAST:
4063+ dialog.set_current_name("{0} {1}{2}".format(_("Screencast"), dt, CODEC_LIST[codec][3]))
4064+ elif main_mode == MODE_SCREENSHOT:
4065+ dialog.set_current_name("{0} {1}.png".format(_("Screenshot"), dt))
4066+
4067+ dialog.set_do_overwrite_confirmation(True)
4068+
4069+ if old_path and os.path.isdir(old_path):
4070+ dialog.set_current_folder(old_path)
4071+ else:
4072+ if main_mode == MODE_SCREENCAST:
4073+ dialog.set_current_folder(prefs.video_dest)
4074+ elif main_mode == MODE_SCREENSHOT:
4075+ dialog.set_current_folder(prefs.picture_dest)
4076+
4077+
4078+ dialog.show_all()
4079+ result = dialog.run()
4080+ old_path = dialog.get_current_folder()
4081+ return dialog, result, old_path
4082+
4083
4084=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/widgets.py'
4085--- build/lib.linux-x86_64-2.7/kazam/frontend/widgets.py 1970-01-01 00:00:00 +0000
4086+++ build/lib.linux-x86_64-2.7/kazam/frontend/widgets.py 2012-11-15 10:17:01 +0000
4087@@ -0,0 +1,60 @@
4088+# -*- coding: utf-8 -*-
4089+#
4090+# widgets.py
4091+#
4092+# Copyright 2012 David Klasinc <bigwhale@lubica.net>
4093+#
4094+# This program is free software; you can redistribute it and/or modify
4095+# it under the terms of the GNU General Public License as published by
4096+# the Free Software Foundation; either version 3 of the License, or
4097+# (at your option) any later version.
4098+#
4099+# This program is distributed in the hope that it will be useful,
4100+# but WITHOUT ANY WARRANTY; without even the implied warranty of
4101+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4102+# GNU General Public License for more details.
4103+#
4104+# You should have received a copy of the GNU General Public License
4105+# along with this program; if not, write to the Free Software
4106+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
4107+# MA 02110-1301, USA.
4108+
4109+from gi.repository import Gtk, Gdk, Pango, GObject, GdkPixbuf
4110+
4111+class _Tile(object):
4112+ def __init__(self):
4113+ self.set_focus_on_click(False)
4114+ self.set_relief(Gtk.ReliefStyle.NONE)
4115+ self.box = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
4116+ self.box.set_size_request(62, -1)
4117+ self.add(self.box)
4118+
4119+ def create_default(self, label, icon):
4120+ if icon is not None:
4121+ if isinstance(icon, Gtk.Image):
4122+ self.image = icon
4123+ else:
4124+ self.image = Gtk.Image()
4125+ self.box.pack_start(self.image, True, True, 0)
4126+
4127+ self.label = Gtk.Label.new(label)
4128+ self.box.pack_start(self.label, True, True, 0)
4129+
4130+class TileToggleButton(Gtk.RadioButton, _Tile):
4131+ def __init__(self):
4132+ Gtk.RadioButton.__init__(self)
4133+ self.set_mode(False)
4134+ _Tile.__init__(self)
4135+
4136+class ModeButton(TileToggleButton):
4137+ def __init__(self, label, icon):
4138+ TileToggleButton.__init__(self)
4139+ html = "<small>%s</small>" % label
4140+ self.create_default(html, icon)
4141+ self.label.set_use_markup(True)
4142+ self.label.set_justify(Gtk.Justification.CENTER)
4143+
4144+ #def do_draw(self, cr):
4145+ #for child in self:
4146+ # self.propagate_draw(child, cr)
4147+
4148
4149=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/window_area.py'
4150--- build/lib.linux-x86_64-2.7/kazam/frontend/window_area.py 1970-01-01 00:00:00 +0000
4151+++ build/lib.linux-x86_64-2.7/kazam/frontend/window_area.py 2012-11-15 10:17:01 +0000
4152@@ -0,0 +1,202 @@
4153+# -*- coding: utf-8 -*-
4154+#
4155+# window_select.py
4156+#
4157+# Copyright 2012 David Klasinc <bigwhale@lubica.net>
4158+#
4159+# This program is free software; you can redistribute it and/or modify
4160+# it under the terms of the GNU General Public License as published by
4161+# the Free Software Foundation; either version 3 of the License, or
4162+# (at your option) any later version.
4163+#
4164+# This program is distributed in the hope that it will be useful,
4165+# but WITHOUT ANY WARRANTY; without even the implied warranty of
4166+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4167+# GNU General Public License for more details.
4168+#
4169+# You should have received a copy of the GNU General Public License
4170+# along with this program; if not, write to the Free Software
4171+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
4172+# MA 02110-1301, USA.
4173+
4174+import time
4175+import cairo
4176+import logging
4177+logger = logging.getLogger("Window Select")
4178+
4179+from gettext import gettext as _
4180+
4181+from gi.repository import Gtk, GObject, Gdk, Wnck, GdkX11
4182+
4183+from kazam.backend.constants import *
4184+class AreaWindow(GObject.GObject):
4185+
4186+ __gsignals__ = {
4187+ "area-selected" : (GObject.SIGNAL_RUN_LAST,
4188+ None,
4189+ (),
4190+ ),
4191+ "area-canceled" : (GObject.SIGNAL_RUN_LAST,
4192+ None,
4193+ (),
4194+ ),
4195+ }
4196+
4197+ def __init__(self):
4198+ super(AreaWindow, self).__init__()
4199+ logger.debug("Initializing select window.")
4200+
4201+ self.startx = 0
4202+ self.starty = 0
4203+ self.endx = 0
4204+ self.endy = 0
4205+ self.height = 0
4206+ self.width = 0
4207+
4208+ self.window = Gtk.Window()
4209+ self.box = Gtk.Box()
4210+ self.drawing = Gtk.DrawingArea()
4211+ self.box.pack_start(self.drawing, True, True, 0)
4212+ self.drawing.set_size_request(500, 500)
4213+ self.window.add(self.box)
4214+
4215+ self.window.connect("delete-event", Gtk.main_quit)
4216+ self.window.connect("key-press-event", self.cb_keypress_event)
4217+
4218+ self.drawing.connect("draw", self.cb_draw)
4219+ self.drawing.connect("motion-notify-event", self.cb_draw_motion_notify_event)
4220+ self.drawing.connect("button-press-event", self.cb_draw_button_press_event)
4221+ self.drawing.connect("leave-notify-event", self.cb_leave_notify_event)
4222+ self.drawing.add_events(Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.POINTER_MOTION_HINT_MASK | Gdk.EventMask.LEAVE_NOTIFY_MASK)
4223+
4224+ self.window.set_border_width(0)
4225+ self.window.set_app_paintable(True)
4226+ self.window.set_has_resize_grip(False)
4227+ self.window.set_resizable(True)
4228+ self.window.set_decorated(False)
4229+ self.window.set_property("skip-taskbar-hint", True)
4230+ self.window.set_keep_above(True)
4231+ self.screen = self.window.get_screen()
4232+ self.visual = self.screen.get_rgba_visual()
4233+
4234+ self.disp = GdkX11.X11Display.get_default()
4235+ self.dm = Gdk.Display.get_device_manager(self.disp)
4236+ self.pntr_device = self.dm.get_client_pointer()
4237+
4238+ if self.visual is not None and self.screen.is_composited():
4239+ logger.debug("Compositing window manager detected.")
4240+ self.window.set_visual(self.visual)
4241+ self.compositing = True
4242+ else:
4243+ self.compositing = False
4244+
4245+ (scr, x, y) = self.pntr_device.get_position()
4246+ cur = scr.get_monitor_at_point(x, y)
4247+ self.window.move(HW.screens[cur]['x'],
4248+ HW.screens[cur]['y'])
4249+ self.window.fullscreen()
4250+
4251+ crosshair_cursor = Gdk.Cursor(Gdk.CursorType.CROSSHAIR)
4252+ self.last_cursor = Gdk.Cursor(Gdk.CursorType.LEFT_PTR)
4253+ self.gdk_win = self.window.get_root_window()
4254+ self.gdk_win.set_cursor(crosshair_cursor)
4255+
4256+ def cb_draw_motion_notify_event(self, widget, event):
4257+ (state, x, y, mask) = event.window.get_device_position(self.pntr_device)
4258+ if mask & Gdk.ModifierType.BUTTON1_MASK:
4259+ self.endx = int(event.x)
4260+ self.endy = int(event.y)
4261+ self.width = self.endx - self.startx
4262+ self.height = self.endy - self.starty
4263+ widget.queue_draw()
4264+ return True
4265+
4266+ def cb_draw_button_press_event(self, widget, event):
4267+ self.startx = int(event.x)
4268+ self.starty = int(event.y)
4269+ self.endx = 0
4270+ self.endy = 0
4271+ self.width = 0
4272+ self.height = 0
4273+
4274+ def cb_leave_notify_event(self, widget, event):
4275+ (scr, x, y) = self.pntr_device.get_position()
4276+ cur = scr.get_monitor_at_point(x, y)
4277+ self.window.unfullscreen()
4278+ self.window.move(HW.screens[cur]['x'],
4279+ HW.screens[cur]['y'])
4280+ self.window.fullscreen()
4281+ logger.debug("Move to X: {0} Y: {1}".format(HW.screens[cur]['x'], HW.screens[cur]['y']))
4282+ return True
4283+
4284+ def cb_keypress_event(self, widget, event):
4285+ (op, keycode) = event.get_keycode()
4286+ self.gdk_win.set_cursor(self.last_cursor)
4287+ if keycode == 36 or keycode == 104: # Enter
4288+ self.window.hide()
4289+ self.width = abs(self.width)
4290+ self.height = abs(self.height)
4291+ self.emit("area-selected")
4292+ elif keycode == 9: # ESC
4293+ self.window.hide()
4294+ self.emit("area-canceled")
4295+
4296+ def cb_draw(self, widget, cr):
4297+ (w, h) = self.window.get_size()
4298+
4299+ if self.compositing:
4300+ cr.set_source_rgba(0.0, 0.0, 0.0, 0.45)
4301+ else:
4302+ cr.set_source_rgb(0.5, 0.5, 0.5)
4303+
4304+ cr.set_operator(cairo.OPERATOR_SOURCE)
4305+ cr.paint()
4306+
4307+ cr.set_operator(cairo.OPERATOR_SOURCE)
4308+
4309+ # Draw the selection area
4310+ cr.move_to(self.startx, self.starty)
4311+ cr.set_source_rgb(1.0, 0.0, 0.0)
4312+ cr.rectangle(self.startx, self.starty, self.width, self.height)
4313+ cr.stroke()
4314+
4315+ if self.compositing:
4316+ cr.set_source_rgba(0.0, 0.0, 0.0, 0.0)
4317+ else:
4318+ cr.set_source_rgb(0.0, 0.0, 0.0)
4319+
4320+ cr.rectangle(self.startx, self.starty, self.width, self.height)
4321+ cr.fill()
4322+
4323+ cr.set_operator(cairo.OPERATOR_OVER)
4324+
4325+ self._outline_text(cr, w, h, 30, _("Select an area by clicking and dragging."))
4326+ self._outline_text(cr, w, h + 50, 26, _("Press ENTER to confirm or ESC to cancel"))
4327+
4328+ self._outline_text(cr, w, h + 100, 20, "({0} x {1})".format(abs(self.height), abs(self.height)))
4329+ cr.set_operator(cairo.OPERATOR_SOURCE)
4330+
4331+ def _outline_text(self, cr, w, h, size, text):
4332+ cr.set_font_size(size)
4333+ try:
4334+ cr.select_font_face("Ubuntu", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
4335+ except:
4336+ pass
4337+ te = cr.text_extents(text)
4338+ cr.set_line_width(2.0)
4339+ cx = w/2 - te[2]/2
4340+ cy = h/2 - te[3]/2
4341+ if self.compositing:
4342+ cr.set_source_rgba(0.4, 0.4, 0.4, 1.0)
4343+ else:
4344+ cr.set_source_rgb(0.4, 0.4, 0.4)
4345+
4346+ cr.move_to(cx, cy)
4347+ cr.text_path(text)
4348+ cr.stroke()
4349+ if self.compositing:
4350+ cr.set_source_rgba(1.0, 1.0, 1.0, 1.0)
4351+ else:
4352+ cr.set_source_rgb(1.0, 1.0, 1.0)
4353+ cr.move_to(cx, cy)
4354+ cr.show_text(text)
4355
4356=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/window_countdown.py'
4357--- build/lib.linux-x86_64-2.7/kazam/frontend/window_countdown.py 1970-01-01 00:00:00 +0000
4358+++ build/lib.linux-x86_64-2.7/kazam/frontend/window_countdown.py 2012-11-15 10:17:01 +0000
4359@@ -0,0 +1,140 @@
4360+# -*- coding: utf-8 -*-
4361+#
4362+# window_countdown.py
4363+#
4364+# Copyright 2012 David Klasinc <bigwhale@lubica.net>
4365+# Copyright 2010 Andrew <andrew@karmic-desktop>
4366+#
4367+# This program is free software; you can redistribute it and/or modify
4368+# it under the terms of the GNU General Public License as published by
4369+# the Free Software Foundation; either version 3 of the License, or
4370+# (at your option) any later version.
4371+#
4372+# This program is distributed in the hope that it will be useful,
4373+# but WITHOUT ANY WARRANTY; without even the implied warranty of
4374+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4375+# GNU General Public License for more details.
4376+#
4377+# You should have received a copy of the GNU General Public License
4378+# along with this program; if not, write to the Free Software
4379+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
4380+# MA 02110-1301, USA.
4381+
4382+import cairo
4383+
4384+from gettext import gettext as _
4385+from gi.repository import Gtk, GObject
4386+from kazam.backend.constants import *
4387+
4388+class CountdownWindow(GObject.GObject):
4389+
4390+ __gsignals__ = {
4391+ "counter-finished" : (GObject.SIGNAL_RUN_LAST,
4392+ None,
4393+ (),
4394+ ),
4395+ }
4396+
4397+ def __init__(self, indicator, number = 5, show_window = True):
4398+ super(CountdownWindow, self).__init__()
4399+ self.indicator = indicator
4400+ self.number = number
4401+ self.canceled = False
4402+ self.show_window = show_window
4403+
4404+ self.window = Gtk.Window()
4405+ self.window.connect("delete-event", Gtk.main_quit)
4406+ self.window.connect("draw", self.cb_draw)
4407+ self.width = 600
4408+ self.height = 240
4409+ self.window.set_default_geometry(self.height, self.width)
4410+ self.window.set_default_size(self.width, self.height)
4411+ self.window.set_position(Gtk.WindowPosition.CENTER)
4412+ self.window.set_app_paintable(True)
4413+ self.window.set_has_resize_grip(False)
4414+ self.window.set_resizable(True)
4415+
4416+ self.window.set_decorated(False)
4417+ self.window.set_property("skip-taskbar-hint", True)
4418+ self.window.set_keep_above(True)
4419+ self.screen = self.window.get_screen()
4420+ self.visual = self.screen.get_rgba_visual()
4421+
4422+ if self.visual is not None and self.screen.is_composited():
4423+ self.window.set_visual(self.visual)
4424+
4425+
4426+ def run(self, counter):
4427+ if counter > 0:
4428+ self.number = counter + 1
4429+ if self.show_window:
4430+ self.window.show_all()
4431+ else:
4432+ self.number = 0
4433+ self.countdown()
4434+
4435+ def countdown(self):
4436+ if not self.canceled:
4437+ if self.number < 5:
4438+ self.indicator.blink_set_state(BLINK_FAST)
4439+ if self.number > 1:
4440+ self.window.queue_draw()
4441+ GObject.timeout_add(1000, self.countdown)
4442+ self.number -= 1
4443+ else:
4444+ self.window.destroy()
4445+ GObject.timeout_add(400, self.counter_finished)
4446+
4447+ def cancel_countdown(self):
4448+ self.indicator.blink_set_state(BLINK_STOP)
4449+ self.canceled = True
4450+ self.window.destroy()
4451+ self.number = 0
4452+
4453+ def counter_finished(self):
4454+ self.emit("counter-finished")
4455+ return False
4456+
4457+ def cb_draw(self, widget, cr):
4458+ w = self.width
4459+ h = self.height
4460+ cr.set_source_rgba(1, 1, 1, 0)
4461+ cr.set_operator(cairo.OPERATOR_SOURCE)
4462+ cr.paint()
4463+ self._draw_rounded(cr, 1, 1, w - 10, h - 10, 20)
4464+ cr.set_line_width(1.0)
4465+ cr.set_source_rgba(0.0, 0.0, 0.0, 0.4)
4466+ cr.stroke_preserve()
4467+ cr.fill()
4468+ cr.set_operator(cairo.OPERATOR_OVER)
4469+ self._outline_text(cr, w, h, 36, _("Recording will start in ..."))
4470+ self._outline_text(cr, w, h + 70, 36, _("{0}".format(self.number)))
4471+
4472+ def _draw_rounded(self, cr, x, y, w, h, r = 20):
4473+ cr.move_to(x + r, y)
4474+ cr.line_to(x + w - r, y)
4475+ cr.curve_to(x + w,y,x+w,y,x+w,y+r)
4476+ cr.line_to(x + w,y+h-r)
4477+ cr.curve_to(x + w, y + h, x + w, y + h, x + w - r, y + h)
4478+ cr.line_to(x + r, y + h)
4479+ cr.curve_to(x, y + h, x, y + h, x, y + h - r)
4480+ cr.line_to(x, y + r)
4481+ cr.curve_to(x, y, x, y, x + r, y)
4482+
4483+ def _outline_text(self, cr, w, h, size, text):
4484+ cr.set_font_size(size)
4485+ try:
4486+ cr.select_font_face("Ubuntu", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
4487+ except:
4488+ pass
4489+ te = cr.text_extents(text)
4490+ cr.set_source_rgba(0.4, 0.4, 0.4, 1.0)
4491+ cr.set_line_width(2.0)
4492+ cx = w/2 - te[2]/2
4493+ cy = h/2 - te[3]/2
4494+ cr.move_to(cx, cy)
4495+ cr.text_path(text)
4496+ cr.stroke()
4497+ cr.set_source_rgba(1.0, 1.0, 1.0, 1.0)
4498+ cr.move_to(cx, cy)
4499+ cr.show_text(text)
4500
4501=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/window_region.py'
4502--- build/lib.linux-x86_64-2.7/kazam/frontend/window_region.py 1970-01-01 00:00:00 +0000
4503+++ build/lib.linux-x86_64-2.7/kazam/frontend/window_region.py 2012-11-15 10:17:01 +0000
4504@@ -0,0 +1,200 @@
4505+# -*- coding: utf-8 -*-
4506+#
4507+# window_region.py
4508+#
4509+# Copyright 2012 David Klasinc <bigwhale@lubica.net>
4510+# Copyright 2010 Andrew <andrew@karmic-desktop>
4511+#
4512+# This program is free software; you can redistribute it and/or modify
4513+# it under the terms of the GNU General Public License as published by
4514+# the Free Software Foundation; either version 3 of the License, or
4515+# (at your option) any later version.
4516+#
4517+# This program is distributed in the hope that it will be useful,
4518+# but WITHOUT ANY WARRANTY; without even the implied warranty of
4519+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4520+# GNU General Public License for more details.
4521+#
4522+# You should have received a copy of the GNU General Public License
4523+# along with this program; if not, write to the Free Software
4524+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
4525+# MA 02110-1301, USA.
4526+
4527+import cairo
4528+import logging
4529+logger = logging.getLogger("Window Region")
4530+
4531+from gettext import gettext as _
4532+
4533+from gi.repository import Gtk, GObject, Gdk
4534+
4535+class RegionWindow(GObject.GObject):
4536+
4537+ __gsignals__ = {
4538+ "region-selected" : (GObject.SIGNAL_RUN_LAST,
4539+ None,
4540+ (),
4541+ ),
4542+ "region-canceled" : (GObject.SIGNAL_RUN_LAST,
4543+ None,
4544+ (),
4545+ ),
4546+ }
4547+
4548+ def __init__(self, region = None):
4549+ super(RegionWindow, self).__init__()
4550+ logger.debug("Initializing region window.")
4551+ self.window = Gtk.Window()
4552+ self.window.connect("configure-event", self.cb_configure_event)
4553+ self.window.connect("delete-event", Gtk.main_quit)
4554+ self.window.connect("draw", self.cb_draw)
4555+ self.window.connect("key-press-event", self.cb_keypress_event)
4556+ self.window.connect("button-press-event", self.cb_button_press_event)
4557+
4558+ if region:
4559+ logger.debug("Old region defined at: X: {0}, Y: {1}, W: {2}, H: {3}".format(region[0],
4560+ region[1],
4561+ region[2],
4562+ region[3]))
4563+ self.startx = region[0]
4564+ self.starty = region[1]
4565+ self.endx = region[2]
4566+ self.endy = region[3]
4567+ self.window.move(self.startx, self.starty)
4568+ else:
4569+ self.startx = 0
4570+ self.starty = 0
4571+ self.endx = 640
4572+ self.endy = 480
4573+ self.window.set_position(Gtk.WindowPosition.CENTER)
4574+
4575+ self.width = self.endx - self.startx
4576+ self.height = self.endy - self.starty
4577+ self.window.set_default_geometry(self.width, self.height)
4578+
4579+ self.window.set_border_width(30)
4580+ self.window.set_app_paintable(True)
4581+ self.window.set_has_resize_grip(False)
4582+ self.window.set_resizable(True)
4583+ self.window.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
4584+ self.window.set_decorated(False)
4585+ self.window.set_property("skip-taskbar-hint", True)
4586+ self.window.set_keep_above(True)
4587+ self.screen = self.window.get_screen()
4588+ self.visual = self.screen.get_rgba_visual()
4589+ self.recording = False
4590+
4591+ self.window.set_visual(self.visual)
4592+ if self.visual is not None and self.screen.is_composited():
4593+ self.window.show_all()
4594+
4595+ def cb_button_press_event(self, widget, event):
4596+ (op, button) = event.get_button()
4597+ if button == 1:
4598+ if int(event.x) in range(0, 15) and int(event.y) in range(0,15):
4599+ self.window.begin_resize_drag(Gdk.WindowEdge.NORTH_WEST, button,
4600+ event.x_root, event.y_root, event.time)
4601+
4602+ elif int(event.x) in range(self.width-15, self.width) and int(event.y) in range(0,15):
4603+ self.window.begin_resize_drag(Gdk.WindowEdge.NORTH_EAST, button,
4604+ event.x_root, event.y_root, event.time)
4605+
4606+ elif int(event.x) in range(self.width-15, self.width) and int(event.y) in range(self.height-15,self.height):
4607+ self.window.begin_resize_drag(Gdk.WindowEdge.SOUTH_EAST, button,
4608+ event.x_root, event.y_root, event.time)
4609+
4610+ elif int(event.x) in range(0, 15) and int(event.y) in range(self.height-15, self.height):
4611+ self.window.begin_resize_drag(Gdk.WindowEdge.SOUTH_WEST, button,
4612+ event.x_root, event.y_root, event.time)
4613+
4614+ else:
4615+ self.window.begin_move_drag(button, event.x_root, event.y_root, event.time)
4616+
4617+ def cb_keypress_event(self, widget, event):
4618+ (op, keycode) = event.get_keycode()
4619+ if keycode == 36 or keycode == 104: # Enter
4620+ self.window.set_default_geometry(self.width, self.height)
4621+ (self.startx, self.starty) = self.window.get_position()
4622+ self.endx = self.startx + self.width - 1
4623+ self.endy = self.starty + self.height - 1
4624+ self.recording = True
4625+ self.window.input_shape_combine_region(None)
4626+ #
4627+ # When support for masked input is back, remove the hide() call.
4628+ #
4629+ self.window.hide()
4630+ # self.window.queue_draw()
4631+ self.emit("region-selected")
4632+ elif keycode == 9: # ESC
4633+ self.window.hide()
4634+ self.emit("region-canceled")
4635+
4636+
4637+ def cb_configure_event(self, widget, event):
4638+ self.width = event.width
4639+ self.height = event.height
4640+
4641+ def cb_draw(self, widget, cr):
4642+ w = self.width
4643+ h = self.height
4644+ #
4645+ # Drawing a red rectangle around selected area would be extremely nice
4646+ # however, cairo.Region is missing from GIR and from pycairo and
4647+ # it is needed for input_shape_combine_region().
4648+ # See: https://bugs.freedesktop.org/show_bug.cgi?id=44336
4649+ #
4650+ #if self.recording:
4651+ # cr.set_source_rgba(0.0, 0.0, 0.0, 0.0)
4652+ # cr.set_operator(cairo.OPERATOR_SOURCE)
4653+ # cr.paint()
4654+ # surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w , h)
4655+ # surface_ctx = cairo.Context(surface)
4656+ # surface_ctx.set_source_rgba(1.0, 1.0, 1.0, 0.0)
4657+ # surface_ctx.set_operator(cairo.OPERATOR_SOURCE)
4658+ # surface_ctx.paint()
4659+ # reg = Gdk.cairo_region_create_from_surface(surface)
4660+ # widget.input_shape_combine_region(reg)
4661+ # cr.move_to(0, 0)
4662+ # cr.set_source_rgb(1.0, 0.0, 0.0)
4663+ # cr.set_line_width(2.0)
4664+ # cr.rectangle(0, 0, w, h)
4665+ # cr.stroke()
4666+ # cr.set_operator(cairo.OPERATOR_OVER)
4667+ #else:
4668+ cr.set_source_rgba(0.0, 0.0, 0.0, 0.4)
4669+ cr.set_operator(cairo.OPERATOR_SOURCE)
4670+ cr.paint()
4671+ cr.set_source_rgba(1.0, 1.0, 1.0, 1.0)
4672+ cr.set_line_width(1.0)
4673+ cr.move_to(0, 0)
4674+ cr.rectangle(0, 0, 15, 15)
4675+ cr.rectangle(w-15, 0, w, 15)
4676+ cr.rectangle(0, h-15, 15, h)
4677+ cr.rectangle(w-15, h-15, w, h)
4678+ cr.fill()
4679+ cr.set_source_rgb(0.0, 0.0, 0.0)
4680+ cr.rectangle(0, 0, w, h)
4681+ cr.stroke()
4682+ cr.set_operator(cairo.OPERATOR_OVER)
4683+ self._outline_text(cr, w, h, 24, _("Select region by resizing the window"))
4684+ self._outline_text(cr, w, h + 50, 24, _("Press ENTER to confirm or ESC to cancel."))
4685+ self._outline_text(cr, w, h + 80, 12, "({0} x {1})".format(w, h))
4686+
4687+
4688+ def _outline_text(self, cr, w, h, size, text):
4689+ cr.set_font_size(size)
4690+ try:
4691+ cr.select_font_face("Ubuntu", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
4692+ except:
4693+ pass
4694+ te = cr.text_extents(text)
4695+ cr.set_line_width(2.0)
4696+ cx = w/2 - te[2]/2
4697+ cy = h/2 - te[3]/2
4698+ cr.set_source_rgba(0.4, 0.4, 0.4, 1.0)
4699+ cr.move_to(cx, cy)
4700+ cr.text_path(text)
4701+ cr.stroke()
4702+ cr.set_source_rgba(1.0, 1.0, 1.0, 1.0)
4703+ cr.move_to(cx, cy)
4704+ cr.show_text(text)
4705
4706=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/window_select.py'
4707--- build/lib.linux-x86_64-2.7/kazam/frontend/window_select.py 1970-01-01 00:00:00 +0000
4708+++ build/lib.linux-x86_64-2.7/kazam/frontend/window_select.py 2012-11-15 10:17:01 +0000
4709@@ -0,0 +1,181 @@
4710+# -*- coding: utf-8 -*-
4711+#
4712+# window_select.py
4713+#
4714+# Copyright 2012 David Klasinc <bigwhale@lubica.net>
4715+# Copyright 2010 Andrew <andrew@karmic-desktop>
4716+#
4717+# This program is free software; you can redistribute it and/or modify
4718+# it under the terms of the GNU General Public License as published by
4719+# the Free Software Foundation; either version 3 of the License, or
4720+# (at your option) any later version.
4721+#
4722+# This program is distributed in the hope that it will be useful,
4723+# but WITHOUT ANY WARRANTY; without even the implied warranty of
4724+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4725+# GNU General Public License for more details.
4726+#
4727+# You should have received a copy of the GNU General Public License
4728+# along with this program; if not, write to the Free Software
4729+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
4730+# MA 02110-1301, USA.
4731+
4732+import time
4733+import cairo
4734+import logging
4735+logger = logging.getLogger("Window Select")
4736+
4737+from gettext import gettext as _
4738+
4739+from gi.repository import Gtk, GObject, Gdk, Wnck, GdkX11
4740+
4741+from kazam.backend.constants import *
4742+
4743+class SelectWindow(GObject.GObject):
4744+
4745+ __gsignals__ = {
4746+ "window-selected" : (GObject.SIGNAL_RUN_LAST,
4747+ None,
4748+ (),
4749+ ),
4750+ "window-canceled" : (GObject.SIGNAL_RUN_LAST,
4751+ None,
4752+ (),
4753+ ),
4754+ }
4755+
4756+ def __init__(self):
4757+ super(SelectWindow, self).__init__()
4758+ logger.debug("Initializing select window.")
4759+
4760+ self.xid = None
4761+
4762+ self.window = Gtk.Window()
4763+ self.window.connect("delete-event", Gtk.main_quit)
4764+ self.window.connect("draw", self.cb_draw)
4765+ self.window.connect("key-press-event", self.cb_keypress_event)
4766+ self.window.connect("button-press-event", self.cb_button_press_event)
4767+ self.window.connect("leave-notify-event", self.cb_leave_notify_event)
4768+
4769+ self.window.set_border_width(30)
4770+ self.window.set_app_paintable(True)
4771+ self.window.set_has_resize_grip(False)
4772+ self.window.set_resizable(True)
4773+ self.window.add_events(Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.LEAVE_NOTIFY_MASK)
4774+ self.window.set_decorated(False)
4775+ self.window.set_property("skip-taskbar-hint", True)
4776+ self.window.set_keep_above(True)
4777+ self.screen = self.window.get_screen()
4778+ self.visual = self.screen.get_rgba_visual()
4779+ self.recording = False
4780+
4781+ self.disp = GdkX11.X11Display.get_default()
4782+ self.dm = Gdk.Display.get_device_manager(self.disp)
4783+ self.pntr_device = self.dm.get_client_pointer()
4784+
4785+ if self.visual is not None and self.screen.is_composited():
4786+ logger.debug("Compositing window manager detected.")
4787+ self.window.set_visual(self.visual)
4788+ self.compositing = True
4789+ else:
4790+ self.compositing = False
4791+
4792+ (scr, x, y) = self.pntr_device.get_position()
4793+ cur = scr.get_monitor_at_point(x, y)
4794+ self.window.unfullscreen()
4795+ self.window.move(HW.screens[cur]['x'],
4796+ HW.screens[cur]['y'])
4797+ self.window.fullscreen()
4798+ crosshair_cursor = Gdk.Cursor(Gdk.CursorType.CROSSHAIR)
4799+ self.last_cursor = Gdk.Cursor(Gdk.CursorType.LEFT_PTR)
4800+ self.gdk_win = self.window.get_root_window()
4801+ self.gdk_win.set_cursor(crosshair_cursor)
4802+
4803+ def cb_leave_notify_event(self, widget, event):
4804+ (scr, x, y) = self.pntr_device.get_position()
4805+ cur = scr.get_monitor_at_point(x, y)
4806+ self.window.unfullscreen()
4807+ logger.debug("Move to X: {0} Y: {1}".format(HW.screens[cur]['x'], HW.screens[cur]['y']))
4808+ self.window.move(HW.screens[cur]['x'],
4809+ HW.screens[cur]['y'])
4810+ self.window.fullscreen()
4811+
4812+ def cb_button_press_event(self, widget, event):
4813+ self.geometry = None
4814+ self.win_name = None
4815+ self.xid = None
4816+ # TODO: Error handling
4817+ (op, button) = event.get_button()
4818+ if button == 1:
4819+ screen = Wnck.Screen.get_default()
4820+ screen.force_update()
4821+ workspace = screen.get_active_workspace()
4822+ wins = screen.get_windows_stacked()
4823+
4824+ for win in reversed(wins):
4825+ if win.is_visible_on_workspace(workspace) and win.is_in_viewport(workspace):
4826+ self.win_name = win.get_name()
4827+ if not (self.win_name.lower().startswith("kazam") or self.win_name.lower().startswith("desktop")):
4828+ geometry = win.get_client_window_geometry()
4829+ self.geometry = geometry
4830+ if geometry[0] <= event.x_root <= (geometry[0] + geometry[2]) and geometry[1] <= event.y_root <= (geometry[1] + geometry[3]):
4831+ self.xid = win.get_xid()
4832+ break
4833+ self.gdk_win.set_cursor(self.last_cursor)
4834+ self.window.hide()
4835+ if self.xid:
4836+ self.emit("window-selected")
4837+ else:
4838+ self.emit("window-canceled")
4839+
4840+ def cb_keypress_event(self, widget, event):
4841+ (op, keycode) = event.get_keycode()
4842+ if keycode == 36 or keycode == 104 or keycode == 9: # Enter or Escape
4843+ self.gdk_win.set_cursor(self.last_cursor)
4844+ self.window.hide()
4845+ self.emit("window-canceled")
4846+
4847+ def cb_draw(self, widget, cr):
4848+ (w, h) = self.window.get_size()
4849+
4850+
4851+ if self.compositing:
4852+ cr.set_source_rgba(0.0, 0.0, 0.0, 0.45)
4853+ else:
4854+ cr.set_source_rgb(0.5, 0.5, 0.5)
4855+
4856+ cr.set_operator(cairo.OPERATOR_SOURCE)
4857+ cr.paint()
4858+ if self.compositing:
4859+ cr.set_source_rgba(1.0, 1.0, 1.0, 1.0)
4860+ else:
4861+ cr.set_source_rgba(1.0, 1.0, 1.0)
4862+
4863+ cr.set_operator(cairo.OPERATOR_OVER)
4864+ self._outline_text(cr, w, h, 30, _("Select a window by clicking on it."))
4865+ self._outline_text(cr, w, h + 50, 26, _("Press ENTER or ESC to cancel"))
4866+
4867+ def _outline_text(self, cr, w, h, size, text):
4868+ cr.set_font_size(size)
4869+ try:
4870+ cr.select_font_face("Ubuntu", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
4871+ except:
4872+ pass
4873+ te = cr.text_extents(text)
4874+ cr.set_line_width(2.0)
4875+ cx = w/2 - te[2]/2
4876+ cy = h/2 - te[3]/2
4877+ if self.compositing:
4878+ cr.set_source_rgba(0.4, 0.4, 0.4, 1.0)
4879+ else:
4880+ cr.set_source_rgb(0.4, 0.4, 0.4)
4881+
4882+ cr.move_to(cx, cy)
4883+ cr.text_path(text)
4884+ cr.stroke()
4885+ if self.compositing:
4886+ cr.set_source_rgba(1.0, 1.0, 1.0, 1.0)
4887+ else:
4888+ cr.set_source_rgb(1.0, 1.0, 1.0)
4889+ cr.move_to(cx, cy)
4890+ cr.show_text(text)
4891
4892=== added file 'build/lib.linux-x86_64-2.7/kazam/instant.py'
4893--- build/lib.linux-x86_64-2.7/kazam/instant.py 1970-01-01 00:00:00 +0000
4894+++ build/lib.linux-x86_64-2.7/kazam/instant.py 2012-11-15 10:17:01 +0000
4895@@ -0,0 +1,142 @@
4896+#!/usr/bin/env python
4897+# -*- coding: utf-8 -*-
4898+#
4899+# instant.py
4900+#
4901+# Copyright 2012 David Klasinc <bigwhale@lubica.net>
4902+#
4903+# This program is free software; you can redistribute it and/or modify
4904+# it under the terms of the GNU General Public License as published by
4905+# the Free Software Foundation; either version 3 of the License, or
4906+# (at your option) any later version.
4907+#
4908+# This program is distributed in the hope that it will be useful,
4909+# but WITHOUT ANY WARRANTY; without even the implied warranty of
4910+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4911+# GNU General Public License for more details.
4912+#
4913+# You should have received a copy of the GNU General Public License
4914+# along with this program; if not, write to the Free Software
4915+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
4916+# MA 02110-1301, USA.
4917+
4918+import sys
4919+import logging
4920+from gettext import gettext as _
4921+from gi.repository import Gtk, GObject
4922+
4923+from kazam.utils import *
4924+from kazam.backend.prefs import *
4925+from kazam.backend.constants import *
4926+from kazam.backend.grabber import Grabber
4927+
4928+logger = logging.getLogger("Instant")
4929+
4930+class InstantApp(GObject.GObject):
4931+
4932+ def __init__(self, datadir, dist, debug, mode, preferences=False):
4933+ GObject.GObject.__init__(self)
4934+ logger.debug("Setting variables.{0}".format(datadir))
4935+
4936+ self.mode = mode
4937+ self.take = 0
4938+
4939+ prefs.datadir = datadir
4940+ prefs.debug = debug
4941+ prefs.dist = dist
4942+ prefs.get_sound_files()
4943+
4944+ if preferences:
4945+ logger.debug("Preferences requested.")
4946+ from kazam.frontend.preferences import Preferences
4947+ from kazam.pulseaudio.pulseaudio import pulseaudio_q
4948+ prefs.pa_q = pulseaudio_q()
4949+ prefs.pa_q.start()
4950+ prefs.get_audio_sources()
4951+
4952+ self.preferences_window = Preferences()
4953+ self.preferences_window.connect("prefs-quit", self.cb_prefs_quit)
4954+ self.preferences_window.open()
4955+
4956+ else:
4957+ self.old_path = None
4958+
4959+ if HW.combined_screen:
4960+ self.video_source = HW.combined_screen
4961+ else:
4962+ screen = HW.get_current_screen()
4963+ self.video_source = HW.screens[screen]
4964+
4965+ self.grabber = Grabber()
4966+ self.grabber.connect("flush-done", self.cb_flush_done)
4967+ self.grabber.connect("save-done", self.cb_save_done)
4968+
4969+ if self.mode == MODE_AREA:
4970+ logger.debug("Area ON.")
4971+ from kazam.frontend.window_area import AreaWindow
4972+ self.area_window = AreaWindow()
4973+ self.area_window.connect("area-selected", self.cb_area_selected)
4974+ self.area_window.connect("area-canceled", self.cb_area_canceled)
4975+ self.area_window.window.show_all()
4976+ elif self.mode == MODE_ALL:
4977+ self.grabber.setup_sources(self.video_source, None, None)
4978+ logger.debug("Grabbing screen")
4979+ self.grabber.grab()
4980+ elif self.mode == MODE_ACTIVE:
4981+ self.grabber.setup_sources(self.video_source, None, None, active=True)
4982+ logger.debug("Grabbing screen")
4983+ self.grabber.grab()
4984+ elif self.mode == MODE_GOD:
4985+ logger.debug("Grabbing in god mode.")
4986+ self.grabber.setup_sources(self.video_source, None, None, god=True)
4987+ self.grabber.grab()
4988+ self.grabber.setup_sources(self.video_source, None, None, active=True, god=True)
4989+ self.grabber.grab()
4990+ else:
4991+ sys.exit(0)
4992+
4993+ def cb_area_selected(self, widget):
4994+ logger.debug("Area selected: SX: {0}, SY: {1}, EX: {2}, EY: {3}".format(
4995+ self.area_window.startx,
4996+ self.area_window.starty,
4997+ self.area_window.endx,
4998+ self.area_window.endy))
4999+ prefs.area = (self.area_window.startx,
5000+ self.area_window.starty,
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches