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
=== modified file 'AUTHORS'
--- AUTHORS 2012-02-09 21:56:49 +0000
+++ AUTHORS 2012-11-15 10:17:01 +0000
@@ -9,4 +9,8 @@
9K.Vishnoo Charan Reddy - Artwork, Bughelp, Design9K.Vishnoo Charan Reddy - Artwork, Bughelp, Design
10Gary Lasker - Coding10Gary Lasker - Coding
11David Klasinc - Coding11David Klasinc - Coding
12Georgi Karavasilev - Design, Testing
13Alan Pope - Testing
14Mattew Paul Thomas - Design, Testing
15Ken VanDine - Packaging
1216
1317
=== added file 'NEWS'
--- NEWS 1970-01-01 00:00:00 +0000
+++ NEWS 2012-11-15 10:17:01 +0000
@@ -0,0 +1,36 @@
1Kazam 1.3.4 - NCC-2893 (Stargazer Edition)
2
3- Instant mode, to capture screenshots from command line, use
4 the following switches:
5 -f / --fullscreen capture full screen
6 -w / --window capture currently active window
7 -a / --area capture a preselected screen area
8 -g / --godmode disable sounds, use automatic file saving and
9 capture full screen & active window at the same
10 time
11
12- New area and window selection screens.
13- Unity Launcher quicklist added.
14
15Kazam 1.3.1 - NCC-2893 (Stargazer Edition)
16------------------------------------------
17
18- GStreamer 1.0 support, Kazam will no longer work with older versions
19 of GStreamer. This includes 0.11 (1.0 alpha/beta/rc) version. Some
20 encoders were changed in transition from beta to final release which
21 messed up a lot of things.
22
23- Completely new GUI. Designed by https://launchpad.net/~kokoto-java with
24 the omnipresent guiding hand of https://launchpad.net/~mpt
25
26- Support for taking still screen captures, also known as screenshots.
27
28- Support for automatic file saving. You can set the prefix filename
29 separately for screenshots and screencasts.
30
31- Support for selecting a single window to screencast. Screenshots are
32 still limited to full screen and/or area selection.
33
34- Theme-able shutter sounds. Right now you can choose between Canon 7D
35 and Nikon D80. ;)
36
037
=== modified file 'README'
--- README 2012-04-25 16:49:23 +0000
+++ README 2012-11-15 10:17:01 +0000
@@ -1,5 +1,5 @@
11
2 Kazam Screencaster v1.0.6 "NCC-1701D"2 Kazam Screencaster v1.3.1 "NCC-2893"
33
44
5Introduction5Introduction
@@ -18,15 +18,25 @@
1818
19Kazam is always available from Launchpad under https://launchpad.net/kazam19Kazam is always available from Launchpad under https://launchpad.net/kazam
2020
21Right now there are only unstable versions available, the project is still21Latest stable release is 1.0.6.
22in development and a stable release is planned for Ubuntu 12.04.22Latest unstable release is 1.3.1 - Stargazer edition
2323
2424
25Installation25Installation - stable release
26------------26-----------------------------
2727
28For Ubuntu, the best way to install is to add a PPA repository and then28If you are using Ubuntu 12.04 or 12.10 then stable version (1.0.x)
29use apt-get command or Software Centre.29is available from universe repository. You can find it in Ubuntu Softare
30Center or install it from the terminal with the following command:
31
32$ sudo apt-get install kazam
33
34For Ubuntu 11.10 - Oneiric Ocelot, the best way to install Kazam is to add
35a PPA repository and then use apt-get command or Software Centre.
36
37$ sudo add-apt-repository ppa:kazam-team/stable-series
38$ sudo apt-get update
39$ sudo apt-get install kazam
3040
31For distribution independent installation you will have to get the latest41For distribution independent installation you will have to get the latest
32tarball release from Launchpad:42tarball release from Launchpad:
@@ -43,6 +53,9 @@
43 # python setup.py install53 # python setup.py install
4454
4555
56Installation - development version
57----------------------------------
58
46If you want bleeding edge, development version then you will have to get59If you want bleeding edge, development version then you will have to get
47source code from Launchpad by running the following command:60source code from Launchpad by running the following command:
4861
@@ -57,6 +70,39 @@
57path is /usr/local.70path is /usr/local.
5871
5972
73Running Kazam
74-------------
75
76If you want to run Kazam from the source tree, there are a few limitations
77that you have to take into account. Right now Ubuntu App indicator will not
78allow setting custom icons. Every icon has to be taken from currently
79installed icon theme. See https://bugs.launchpad.net/kazam/+bug/657857 for
80more information.
81
82To run Kazam simply execute te following commands in the source tree:
83
84$ cd bin
85$ ./kazam
86
87If you already have Kazam installed then Kazam icon will show in the
88indicator, if not, the only way to get to the menu is to click on one
89of the icons in the indicator and then move around with the cursor keys.
90
91Keyboard shortcuts
92------------------
93
94If you have keybinder3.0 from the unstable PPA installed, then you can
95use these keyboard shortcuts for controlling Kazam:
96
97SUPER-CTRL-Q - Quit
98SUPER-CTRL-W - Show/Hide main window
99SUPER-CTRL-R - Start Recording
100SUPER-CTRL-F - Finish Recording
101
102Keyboard shortcuts will work if you installed Kazam 1.3.1 from a PPA,
103keybinder 3.0 is now a dependency and will be installed automatically.
104
105
60Known Issues106Known Issues
61------------107------------
62108
@@ -67,30 +113,14 @@
67- Placing Region selector outside of screen borders will produce unknown113- Placing Region selector outside of screen borders will produce unknown
68results and you will probably end up with no video.114results and you will probably end up with no video.
69115
70- Two warnings appear during the normal usage:
71
72/usr/lib/python2.7/dist-packages/gobject/constants.py:24: Warning:
73g_boxed_type_register_static: assertion `g_type_from_name (name) == 0' failed
74
75This happens when Gtk.GObject was imported before importing gst in python
76and is still being investigated. So far it appears to be mostly harmless.
77
78Second warning comes from Gtk.FileChooser():
79
80kazam:5144): Gtk-WARNING **: Unable to retrieve the file info for <file>
81Error stating file <file> : No such file or directory
82
83This happens when you confirm file save in the dialog box. This is an error
84in Gtk.FileChooser and in Precise Pangolin it is fixed.
85
86- Trouble with recording from certain Monitor sources. I noticed this with116- Trouble with recording from certain Monitor sources. I noticed this with
87Logitech G110 USB Keyboard that can play audio. Pulse Audio will see two117Logitech G110 USB Keyboard that can play audio. Pulse Audio will see two
88devices: USP PnP Stereo Device and Monitor of USB PnP Stereo Device. When118devices: USP PnP Stereo Device and Monitor of USB PnP Stereo Device. When
89recording from the monitor, volume controls for both devices will affect119recording from the monitor, volume controls for both devices will affect
90the volume in the final recording.120the volume in the final recording.
91121
92- I have no idea where to put Mute/Unmute button, so you'll have to check122- I have no idea where to put Mute/Unmute button, so right now every audio
93that in pavucontrol or sound settings. :)123source you select is automatically unmuted.
94124
95- It was reported that sound is disappearing after couple of minutes into125- It was reported that sound is disappearing after couple of minutes into
96the recording. I wasn't able to reproduce this bug and any more info is126the recording. I wasn't able to reproduce this bug and any more info is
@@ -100,10 +130,9 @@
100Recording Tips130Recording Tips
101--------------131--------------
102132
103Framerates above 20fps are unlikely to work because of software and hardware133Framerates above 20fps are unlikely to work well because of software and
104limitations. If you increase framerate and in resulting video134hardware limitations. If you increase framerate and framerate in
105framerate actually drops, that is because encoder can't keep up with135resulting video drops, that is because encoder can't keep up.
106the framerate.
107136
108Always do a sound check. Especially if you are recording a live commentary137Always do a sound check. Especially if you are recording a live commentary
109with background sound. I got the best results when I used earphones to listen138with background sound. I got the best results when I used earphones to listen
@@ -117,9 +146,5 @@
117If you encounter a bug or any kind of unexpected behavior please try to146If you encounter a bug or any kind of unexpected behavior please try to
118reproduce it while you run Kazam from standard terminal with --debug option.147reproduce it while you run Kazam from standard terminal with --debug option.
119Use Launchpad to report bugs (https://bugs.launchpad.net/kazam/+filebug) and148Use Launchpad to report bugs (https://bugs.launchpad.net/kazam/+filebug) and
120include generated output. It will also be helpful if you can attach generated149include generated output.
121'dot' file. You will find this file in /tmp/kazam_debug.dot.
122
123If you have graphviz package installed there is also /tmp/kazam_pipeline.png
124file and you can inspect GStreamer pipeline if everything checks out ok.
125150
126151
=== modified file 'TODO'
--- TODO 2012-02-29 20:43:50 +0000
+++ TODO 2012-11-15 10:17:01 +0000
@@ -1,8 +1,14 @@
1TODO1TODO
2----2----
3Short term:3
4 - Make a list of new features4Whishlist (by BigWhale) and reasons why is something still on a whishlist
55
6Long(er) term:6- Frame marking the capture area while recording is in progress
7 - Implement new features ;)7 A transparent window with no input mask is required on screen. However,
8 for that to work, Gdk.cairo_region_create_from_surface() is required. For
9 some reason, this fuction still isn't introspected. See:
10
11 http://askubuntu.com/questions/97789/creating-a-gtk-window-with-input-shape-mask-in-python
12
13 (This is still an issue ... :'( )
814
915
=== modified file 'bin/kazam'
--- bin/kazam 2012-02-29 20:43:50 +0000
+++ bin/kazam 2012-11-15 10:17:01 +0000
@@ -30,25 +30,36 @@
3030
31if __name__ == "__main__":31if __name__ == "__main__":
3232
33 log = logging.getLogger()33 logger = logging.getLogger()
34 log.name = "Kazam"34 logger.name = "Kazam"
35 handler = logging.StreamHandler()35 handler = logging.StreamHandler()
36 formatter = logging.Formatter('%(levelname)s %(name)-10s - %(message)s')36 formatter = logging.Formatter('%(levelname)s %(name)s - %(message)s')
37 handler.setFormatter(formatter)37 handler.setFormatter(formatter)
38 log.addHandler(handler)38 logger.addHandler(handler)
39 logger.setLevel(logging.INFO)
3940
40 log.info("Logger intialized.")41 logger.info("Logger intialized.")
4142
42 if os.path.exists("../data"):43 if os.path.exists("../data"):
43 log.info("Running locally, AppIndicator icons might be missing.")44 logger.info("Running locally, AppIndicator icons might be missing.")
44 datadir = "../data"45 datadir = "../data"
45 sys.path.insert(0, "..")46 sys.path.insert(0, "..")
46 else:47 else:
47 # A bit more flexible setting of datadir, it works48 # A bit more flexible setting of datadir, it works
48 # when base install path is not /usr49 # when base install path is not /usr
49 curpath = os.path.abspath(__file__)50 curpath = os.path.abspath(__file__)
51 curpath = os.path.realpath(curpath)
50 datadir = curpath.split('bin/')[0] + "share/kazam/"52 datadir = curpath.split('bin/')[0] + "share/kazam/"
5153
54 try:
55 import platform
56 dist = platform.linux_distribution()
57 logger.info("Running on: {0} {1}".format(dist[0], dist[1]))
58 except:
59 # Fallback to the almighty Ubuntu 12.10 ;)
60 dist = ('Ubuntu', '12.10', 'quantal')
61 logger.warning("Failed to correctly detect operating system.")
62
52 from kazam.version import *63 from kazam.version import *
53 version = "%(prog)s {0} '{1}'".format(VERSION, CODENAME)64 version = "%(prog)s {0} '{1}'".format(VERSION, CODENAME)
54 parser = ArgumentParser(description = "Screen recording program.")65 parser = ArgumentParser(description = "Screen recording program.")
@@ -62,16 +73,72 @@
62 action = "version",73 action = "version",
63 version = version)74 version = version)
6475
76 parser.add_argument("-t", "--test",
77 action = "store_true",
78 help = "generate test video signal",
79 default = False)
80
81 parser.add_argument("-n", "--nosound",
82 action = "store_true",
83 help = "disable PulseAudio",
84 default = False)
85
86 parser.add_argument("-s", "--silent",
87 action = "store_true",
88 help = "silent start",
89 default = False)
90
91 parser.add_argument("-f", "--fullscreen",
92 action = "store_true",
93 help = "instant screenshot of full screen",
94 default = False)
95
96 parser.add_argument("-a", "--area",
97 action = "store_true",
98 help = "instant screenshot of preselected screen area",
99 default = False)
100
101 parser.add_argument("-w", "--window",
102 action = "store_true",
103 help = "instant screenshot of active window",
104 default = False)
105
106 parser.add_argument("-p", "--preferences",
107 action = "store_true",
108 help = "show preferences window",
109 default = False)
110
111 parser.add_argument("-g", "--godmode",
112 action = "store_true",
113 help = "god mode of capture",
114 default = False)
115
65 args = parser.parse_args()116 args = parser.parse_args()
66 if args.debug:117 if args.debug:
67 log.setLevel(logging.DEBUG)118 logger.setLevel(logging.DEBUG)
68 else:119 else:
69 log.setLevel(logging.INFO)120 logger.setLevel(logging.INFO)
70121
71 from kazam.app import KazamApp122 logger.debug("Starting ...")
72123
73 log.debug("Starting ...")124 if args.fullscreen:
74 appWindow = KazamApp(datadir, args.debug)125 from kazam.instant import InstantApp
75 appWindow.show_all()126 app = InstantApp(datadir, dist, args.debug, 1) # MODE_ALL
127 elif args.area:
128 from kazam.instant import InstantApp
129 app = InstantApp(datadir, dist, args.debug, 2) # MODE_AREA
130 elif args.window:
131 from kazam.instant import InstantApp
132 app = InstantApp(datadir, dist, args.debug, 4) # MODE_ACTIVE
133 elif args.godmode:
134 from kazam.instant import InstantApp
135 app = InstantApp(datadir, dist, args.debug, 666) # MODE_ACTIVE
136 elif args.preferences:
137 from kazam.instant import InstantApp
138 app = InstantApp(datadir, dist, args.debug, 0, preferences=True)
139 else:
140 from kazam.app import KazamApp
141 appWindow = KazamApp(datadir, dist, args.debug, args.test, args.nosound, args.silent)
142
76 Gtk.main()143 Gtk.main()
77 log.debug("Finishing ...")144 logger.debug("Finishing ...")
78145
=== added directory 'build'
=== added directory 'build/lib.linux-x86_64-2.7'
=== added directory 'build/lib.linux-x86_64-2.7/kazam'
=== added file 'build/lib.linux-x86_64-2.7/kazam/__init__.py'
--- build/lib.linux-x86_64-2.7/kazam/__init__.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/__init__.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,1 @@
1
02
=== added file 'build/lib.linux-x86_64-2.7/kazam/app.py'
--- build/lib.linux-x86_64-2.7/kazam/app.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/app.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,748 @@
1# -*- coding: utf-8 -*-
2#
3# app.py
4#
5# Copyright 2012 David Klasinc <bigwhale@lubica.net>
6# Copyright 2010 Andrew <andrew@karmic-desktop>
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21# MA 02110-1301, USA.
22
23import os
24import sys
25import locale
26import shutil
27import gettext
28import logging
29
30from subprocess import Popen
31from gi.repository import Gtk, Gdk, GObject
32from gettext import gettext as _
33
34from kazam.utils import *
35from kazam.backend.prefs import *
36from kazam.backend.constants import *
37from kazam.backend.grabber import Grabber
38from kazam.frontend.main_menu import MainMenu
39from kazam.frontend.window_area import AreaWindow
40from kazam.backend.gstreamer import Screencast
41from kazam.frontend.preferences import Preferences
42from kazam.frontend.about_dialog import AboutDialog
43from kazam.frontend.indicator import KazamIndicator
44from kazam.frontend.window_select import SelectWindow
45from kazam.frontend.done_recording import DoneRecording
46from kazam.frontend.window_countdown import CountdownWindow
47
48logger = logging.getLogger("Main")
49
50#
51# Detect GStreamer version and bail out if lower than 1.0 and no GI
52#
53try:
54 from gi.repository import Gst
55 gst_gi = Gst.version()
56 if not gst_gi[0]:
57 logger.critical("Gstreamer 1.0 or higher requred, bailing out.")
58 gst_gi = None
59 sys.exit(0)
60 else:
61 logger.debug("Gstreamer version detected: {0}.{1}.{2}.{3}".format(gst_gi[0],
62 gst_gi[1],
63 gst_gi[2],
64 gst_gi[3]))
65except ImportError:
66 logger.critical("Gstreamer 1.0 or higher requred, bailing out.")
67 sys.exit(0)
68
69class KazamApp(GObject.GObject):
70
71 def __init__(self, datadir, dist, debug, test, sound, silent):
72 GObject.GObject.__init__(self)
73 logger.debug("Setting variables.")
74
75 prefs.datadir = datadir
76 prefs.get_sound_files()
77
78 self.startup = True
79 prefs.debug = debug
80 prefs.test = test
81 prefs.dist = dist
82 prefs.silent = silent
83 prefs.sound = not sound # Parameter is called nosound and if true, then we don't have sound.
84 # Tricky parameters are tricky!
85
86 self.setup_translations()
87
88 if prefs.sound:
89 try:
90 from kazam.pulseaudio.pulseaudio import pulseaudio_q
91 prefs.sound = True
92 except:
93 logger.warning("Pulse Audio Failed to load. Sound recording disabled.")
94 prefs.sound = False
95
96 self.icons = Gtk.IconTheme.get_default()
97 self.icons.append_search_path(os.path.join(prefs.datadir,"icons", "48x48", "apps"))
98 self.icons.append_search_path(os.path.join(prefs.datadir,"icons", "16x16", "apps"))
99
100 try:
101 from gi.repository import Unity, Dbusmenu
102 launcher = Unity.LauncherEntry.get_for_desktop_id("kazam.desktop")
103 ql = Dbusmenu.Menuitem.new()
104 ql_item1 = Dbusmenu.Menuitem.new()
105 ql_item1.property_set(Dbusmenu.MENUITEM_PROP_LABEL, _("Record screencast"))
106 ql_item1.property_set_bool(Dbusmenu.MENUITEM_PROP_VISIBLE, True)
107 ql_item1.connect("item-activated", self.cb_ql_screencast)
108 ql.child_append(ql_item1)
109 ql_item2 = Dbusmenu.Menuitem.new()
110 ql_item2.property_set(Dbusmenu.MENUITEM_PROP_LABEL, _("Take screenshot"))
111 ql_item2.property_set_bool(Dbusmenu.MENUITEM_PROP_VISIBLE, True)
112 ql_item2.connect("item-activated", self.cb_ql_screenshot)
113 ql.child_append(ql_item2)
114 ql_item3 = Dbusmenu.Menuitem.new()
115 ql_item3.property_set(Dbusmenu.MENUITEM_PROP_LABEL, _("Preferences"))
116 ql_item3.property_set_bool(Dbusmenu.MENUITEM_PROP_VISIBLE, True)
117 ql_item3.connect("item-activated", self.cb_ql_preferences)
118 ql.child_append(ql_item3)
119 launcher.set_property("quicklist", ql)
120 except ImportError:
121 logger.warning("Unity and Dbusmenu not found. Skipping launcher integration.")
122
123 # Initialize all the variables
124
125 self.main_x = 0
126 self.main_y = 0
127 self.countdown = None
128 self.tempfile = ""
129 self.recorder = None
130 self.area_window = None
131 self.old_vid_path = None
132 self.old_pic_path = None
133 self.in_countdown = False
134 self.recording_paused = False
135 self.recording = False
136 self.main_mode = 0
137 self.record_mode = 0
138 self.last_mode = None
139
140 if prefs.sound:
141 prefs.pa_q = pulseaudio_q()
142 prefs.pa_q.start()
143
144 self.mainmenu = MainMenu()
145
146 logger.debug("Connecting indicator signals.")
147 logger.debug("Starting in silent mode: {0}".format(prefs.silent))
148 self.indicator = KazamIndicator(prefs.silent)
149 self.indicator.connect("indicator-quit-request", self.cb_quit_request)
150 self.indicator.connect("indicator-show-request", self.cb_show_request)
151 self.indicator.connect("indicator-start-request", self.cb_start_request)
152 self.indicator.connect("indicator-stop-request", self.cb_stop_request)
153 self.indicator.connect("indicator-pause-request", self.cb_pause_request)
154 self.indicator.connect("indicator-unpause-request", self.cb_unpause_request)
155 self.indicator.connect("indicator-about-request", self.cb_about_request)
156
157 self.mainmenu.connect("file-quit", self.cb_quit_request)
158 self.mainmenu.connect("file-preferences", self.cb_preferences_request)
159 self.mainmenu.connect("help-about", self.cb_help_about)
160
161 #
162 # Setup UI
163 #
164 logger.debug("Main Window UI setup.")
165
166 self.builder = Gtk.Builder()
167 self.builder.add_from_file(os.path.join(prefs.datadir, "ui", "kazam.ui"))
168 self.builder.connect_signals(self)
169 for w in self.builder.get_objects():
170 if issubclass(type(w), Gtk.Buildable):
171 name = Gtk.Buildable.get_name(w)
172 setattr(self, name, w)
173 else:
174 logger.debug("Unable to get name for '%s'" % w)
175
176 # Main Menu
177 self.MainGrid.attach(self.mainmenu.menubar, 0, 0, 1, 1)
178
179 self.context = self.toolbar_main.get_style_context()
180 self.context.add_class(Gtk.STYLE_CLASS_PRIMARY_TOOLBAR)
181
182 self.btn_cast = Gtk.RadioToolButton(group=None)
183 self.btn_cast.set_label(_("Screencast"))
184 self.btn_cast.set_tooltip_text(_("Record a video of your desktop."))
185 img1 = Gtk.Image.new_from_file(os.path.join(prefs.datadir, "icons", "light", "screencast.png"))
186 self.btn_cast.set_icon_widget(img1)
187 self.btn_cast.set_active(True)
188 self.btn_cast.set_name("MAIN_SCREENCAST")
189 self.btn_cast.connect("toggled", self.cb_main_toggled)
190
191 self.btn_shot = Gtk.RadioToolButton(group=self.btn_cast)
192 self.btn_shot.set_label(_("Screenshot"))
193 self.btn_shot.set_tooltip_text(_("Record a picture of your desktop."))
194 img2 = Gtk.Image.new_from_file(os.path.join(prefs.datadir, "icons", "light", "screenshot-1.png"))
195 self.btn_shot.set_icon_widget(img2)
196 self.btn_shot.set_name("MAIN_SCREENSHOT")
197 self.btn_shot.connect("toggled", self.cb_main_toggled)
198
199 self.sep_1 = Gtk.SeparatorToolItem()
200 self.sep_1.set_draw(False)
201 self.sep_1.set_expand(True)
202 self.toolbar_main.insert(self.sep_1, -1)
203 self.toolbar_main.insert(self.btn_cast, -1)
204 self.toolbar_main.insert(self.btn_shot, -1)
205 self.toolbar_main.insert(self.sep_1, -1)
206
207 # Auxiliary toolbar
208 self.btn_full = Gtk.RadioToolButton(group=None)
209 self.btn_full.set_label(_("Fullscreen"))
210 self.btn_full.set_tooltip_text(_("Capture contents of the current screen."))
211 img3 = Gtk.Image.new_from_file(os.path.join(prefs.datadir, "icons", "dark", "fullscreen.png"))
212 self.btn_full.set_icon_widget(img3)
213 self.btn_full.set_active(True)
214 self.btn_full.set_name("MODE_FULL")
215 self.btn_full.connect("toggled", self.cb_record_mode_toggled)
216
217 self.btn_allscreens = Gtk.RadioToolButton(group=self.btn_full)
218 self.btn_allscreens.set_label(_("All Screens"))
219 self.btn_allscreens.set_tooltip_text(_("Capture contents of all of your screens."))
220 img4 = Gtk.Image.new_from_file(os.path.join(prefs.datadir, "icons", "dark", "all-screens.png"))
221 self.btn_allscreens.set_icon_widget(img4)
222 self.btn_allscreens.set_name("MODE_ALL")
223 self.btn_allscreens.connect("toggled", self.cb_record_mode_toggled)
224
225 self.btn_window = Gtk.RadioToolButton(group=self.btn_full)
226 self.btn_window.set_label(_("Window"))
227 self.btn_window.set_tooltip_text(_("Capture contents of a single window."))
228 img5 = Gtk.Image.new_from_file(os.path.join(prefs.datadir, "icons", "dark", "window.png"))
229 self.btn_window.set_icon_widget(img5)
230 self.btn_window.set_name("MODE_WIN")
231 self.btn_window.connect("toggled", self.cb_record_mode_toggled)
232 self.btn_window.connect("clicked", self.cb_record_window_clicked)
233
234 self.btn_area = Gtk.RadioToolButton(group=self.btn_full)
235 self.btn_area.set_label(_("Area"))
236 self.btn_area.set_tooltip_text(_("Capture a pre-selected area of your screen."))
237 img6 = Gtk.Image.new_from_file(os.path.join(prefs.datadir, "icons", "dark", "area.png"))
238 self.btn_area.set_icon_widget(img6)
239 self.btn_area.set_name("MODE_AREA")
240 self.btn_area.connect("toggled", self.cb_record_mode_toggled)
241 self.btn_area.connect("clicked", self.cb_record_area_clicked)
242
243 self.sep_2 = Gtk.SeparatorToolItem()
244 self.sep_2.set_draw(False)
245 self.sep_2.set_expand(True)
246 #self.toolbar_aux.insert(self.sep_2, -1)
247 self.toolbar_aux.insert(self.btn_full, -1)
248 self.toolbar_aux.insert(self.btn_allscreens, -1)
249 self.toolbar_aux.insert(self.btn_window, -1)
250 self.toolbar_aux.insert(self.btn_area, -1)
251 #self.toolbar_aux.insert(self.sep_2, -1)
252
253 self.ntb_main.set_current_page(0)
254
255 #
256 # Take care of screen size changes.
257 #
258 self.default_screen = Gdk.Screen.get_default()
259 self.default_screen.connect("size-changed", self.cb_screen_size_changed)
260 self.window.connect("configure-event", self.cb_configure_event)
261
262 # Fetch sources info, take care of all the widgets and saved settings and show main window
263 if prefs.sound:
264 prefs.get_audio_sources()
265
266 if not prefs.silent:
267 self.window.show_all()
268 else:
269 logger.info("""Starting in silent mode:\n"""
270 """ SUPER-CTRL-W to toggle main window.\n"""
271 """ SUPER-CTRL-R to start recording.\n"""
272 """ SUPER-CTRL-F to finish recording.\n"""
273 """ SUPER-CTRL-P to pause/resume recording.\n"""
274 """ SUPER-CTRL-Q to quit.\n"""
275 )
276
277 self.restore_UI()
278
279 if not prefs.sound:
280 self.combobox_audio.set_sensitive(False)
281 self.combobox_audio2.set_sensitive(False)
282 self.volumebutton_audio.set_sensitive(False)
283 self.volumebutton_audio2.set_sensitive(False)
284
285 HW.get_current_screen(self.window)
286 self.startup = False
287
288 #
289 # Callbacks, go down here ...
290 #
291
292 #
293 # Mode of operation toggles
294 #
295
296 def cb_main_toggled(self, widget):
297 name = widget.get_name()
298 if name == "MAIN_SCREENCAST" and widget.get_active():
299 logger.debug("Main toggled: {0}".format(name))
300 self.main_mode = MODE_SCREENCAST
301 self.ntb_main.set_current_page(0)
302 self.indicator.menuitem_start.set_label(_("Start recording"))
303
304 elif name == "MAIN_SCREENSHOT" and widget.get_active():
305 logger.debug("Main toggled: {0}".format(name))
306 self.main_mode = MODE_SCREENSHOT
307 self.ntb_main.set_current_page(1)
308 if self.record_mode == MODE_WIN:
309 self.last_mode.set_active(True)
310 self.indicator.menuitem_start.set_label(_("Take screenshot"))
311
312 #
313 # Record mode toggles
314 #
315 def cb_record_mode_toggled(self, widget):
316 if widget.get_active():
317 self.current_mode = widget
318 else:
319 self.last_mode = widget
320
321 if widget.get_name() == "MODE_AREA" and widget.get_active():
322 logger.debug("Area ON.")
323 self.area_window = AreaWindow()
324 self.tmp_sig1 = self.area_window.connect("area-selected", self.cb_area_selected)
325 self.tmp_sig2 = self.area_window.connect("area-canceled", self.cb_area_canceled)
326 self.record_mode = MODE_AREA
327
328 if widget.get_name() == "MODE_AREA" and not widget.get_active():
329 logger.debug("Area OFF.")
330 if self.area_window:
331 self.area_window.disconnect(self.tmp_sig1)
332 self.area_window.disconnect(self.tmp_sig2)
333 self.area_window.window.destroy()
334 self.area_window = None
335
336 if widget.get_name() == "MODE_FULL" and widget.get_active():
337 logger.debug("Capture full screen.")
338 self.record_mode = MODE_FULL
339
340 if widget.get_name() == "MODE_ALL" and widget.get_active():
341 logger.debug("Capture all screens.")
342 self.record_mode = MODE_ALL
343
344 if widget.get_name() == "MODE_WIN" and widget.get_active():
345 logger.debug("Window capture ON.")
346 self.select_window = SelectWindow()
347 self.tmp_sig3 = self.select_window.connect("window-selected", self.cb_window_selected)
348 self.tmp_sig4 = self.select_window.connect("window-canceled", self.cb_window_canceled)
349 self.record_mode = MODE_WIN
350
351 if widget.get_name() == "MODE_WIN" and not widget.get_active():
352 logger.debug("Window capture OFF.")
353 if self.select_window:
354 self.select_window.disconnect(self.tmp_sig3)
355 self.select_window.disconnect(self.tmp_sig4)
356 self.select_window.window.destroy()
357 self.select_window = None
358
359
360 #
361 # Unity quick list callbacks
362 #
363
364 def cb_ql_screencast(self, menu, data):
365 logger.debug("Screencast quicklist activated.")
366 self.btn_cast.set_active(True)
367 self.run_counter()
368
369 def cb_ql_screenshot(self, menu, data):
370 logger.debug("Screenshot quicklist activated.")
371 self.btn_shot.set_active(True)
372 self.run_counter()
373
374 def cb_ql_preferences(self, menu, data):
375 logger.debug("Preferences quicklist activated.")
376 self.cb_preferences_request(None)
377
378 def cb_record_area_clicked(self, widget):
379 if self.area_window:
380 logger.debug("Area mode clicked.")
381 self.area_window.window.show_all()
382 self.window.set_sensitive(False)
383
384 def cb_record_window_clicked(self, widget):
385 if self.select_window:
386 logger.debug("Window mode clicked.")
387 self.select_window.window.show_all()
388 self.window.set_sensitive(False)
389
390 def cb_area_selected(self, widget):
391 logger.debug("Area selected: SX: {0}, SY: {1}, EX: {2}, EY: {3}".format(
392 self.area_window.startx,
393 self.area_window.starty,
394 self.area_window.endx,
395 self.area_window.endy))
396 self.window.set_sensitive(True)
397 prefs.area = (self.area_window.startx,
398 self.area_window.starty,
399 self.area_window.endx,
400 self.area_window.endy,
401 self.area_window.width,
402 self.area_window.height)
403
404 def cb_area_canceled(self, widget):
405 logger.debug("Area selection canceled.")
406 self.window.set_sensitive(True)
407 self.last_mode.set_active(True)
408
409 def cb_window_selected(self, widget):
410 prefs.xid = self.select_window.xid
411 prefs.xid_geometry = self.select_window.geometry
412 logger.debug("Window selected: {0} - {1}".format(self.select_window.win_name, prefs.xid))
413 logger.debug("Window geometry: {0}".format(self.select_window.geometry))
414 self.window.set_sensitive(True)
415
416 def cb_window_canceled(self, widget):
417 logger.debug("Window selection canceled.")
418 self.window.set_sensitive(True)
419 self.last_mode.set_active(True)
420
421 def cb_screen_size_changed(self, screen):
422 logger.debug("Screen size changed.")
423 HW.get_screens()
424 #
425 # I combined screen was set to none, turn off the button for all screens
426 #
427 if HW.combined_screen:
428 self.btn_allscreens.set_sensitive(True)
429 else:
430 self.btn_allscreens.set_sensitive(False)
431
432
433 def cb_configure_event(self, widget, event):
434 if event.type == Gdk.EventType.CONFIGURE:
435 prefs.main_x = event.x
436 prefs.main_y = event.y
437
438 def cb_quit_request(self, indicator):
439 logger.debug("Quit requested.")
440 (prefs.main_x, prefs.main_y) = self.window.get_position()
441 try:
442 os.remove(self.recorder.tempfile)
443 os.remove("{0}.mux".format(self.recorder.tempfile))
444 except OSError:
445 logger.info("Unable to delete one of the temporary files. Check your temporary directory.")
446 except AttributeError:
447 pass
448
449 prefs.save_config()
450
451 if prefs.sound:
452 prefs.pa_q.end()
453
454 Gtk.main_quit()
455
456 def cb_preferences_request(self, indicator):
457 logger.debug("Preferences requested.")
458 self.preferences_window = Preferences()
459 self.preferences_window.open()
460
461 def cb_show_request(self, indicator):
462 if not self.window.get_property("visible"):
463 logger.debug("Show requested, raising window.")
464 self.window.show_all()
465 self.window.present()
466 self.window.move(prefs.main_x, prefs.main_y)
467 else:
468 self.window.hide()
469
470 def cb_close_clicked(self, indicator):
471 (prefs.main_x, prefs.main_y) = self.window.get_position()
472 self.window.hide()
473
474 def cb_about_request(self, activated):
475 AboutDialog(self.icons)
476
477 def cb_delete_event(self, widget, user_data):
478 self.cb_quit_request(None)
479
480 def cb_start_request(self, widget):
481 logger.debug("Start recording selected.")
482 self.run_counter()
483
484 def cb_record_clicked(self, widget):
485 logger.debug("Record clicked, invoking Screencast.")
486 self.run_counter()
487
488 def cb_counter_finished(self, widget):
489 logger.debug("Counter finished.")
490 self.in_countdown = False
491 self.countdown = None
492 self.indicator.blink_set_state(BLINK_STOP)
493 if self.main_mode == MODE_SCREENCAST:
494 self.indicator.menuitem_finish.set_label(_("Finish recording"))
495 self.indicator.menuitem_pause.set_sensitive(True)
496 self.indicator.start_recording()
497 self.recorder.start_recording()
498 elif self.main_mode == MODE_SCREENSHOT:
499 self.indicator.hide_it()
500 self.grabber.grab()
501 self.indicator.show_it()
502
503 def cb_stop_request(self, widget):
504 self.recording = False
505 if self.in_countdown:
506 logger.debug("Cancel countdown request.")
507 self.countdown.cancel_countdown()
508 self.countdown = None
509 self.indicator.menuitem_finish.set_label(_("Finish recording"))
510 self.window.set_sensitive(True)
511 self.window.show()
512 self.window.present()
513 else:
514 if self.recording_paused:
515 self.recorder.unpause_recording()
516 logger.debug("Stop request.")
517 self.recorder.stop_recording()
518 self.tempfile = self.recorder.get_tempfile()
519 logger.debug("Recorded tmp file: {0}".format(self.tempfile))
520 logger.debug("Waiting for data to flush.")
521
522 def cb_flush_done(self, widget):
523 if self.main_mode == MODE_SCREENCAST and prefs.autosave_video:
524 logger.debug("Autosaving enabled.")
525 fname = get_next_filename(prefs.video_dest,
526 prefs.autosave_video_file,
527 CODEC_LIST[prefs.codec][3])
528
529 shutil.move(self.tempfile, fname)
530
531 self.window.set_sensitive(True)
532 self.window.show()
533 self.window.present()
534 elif self.main_mode == MODE_SCREENCAST:
535 self.done_recording = DoneRecording(self.icons,
536 self.tempfile,
537 prefs.codec,
538 self.old_vid_path)
539 logger.debug("Done Recording initialized.")
540 self.done_recording.connect("save-done", self.cb_save_done)
541 self.done_recording.connect("save-cancel", self.cb_save_cancel)
542 self.done_recording.connect("edit-request", self.cb_edit_request)
543 logger.debug("Done recording signals connected.")
544 self.done_recording.show_all()
545 self.window.set_sensitive(False)
546
547 elif self.main_mode == MODE_SCREENSHOT:
548 self.grabber.connect("save-done", self.cb_save_done)
549 self.indicator.recording = False
550 self.indicator.menuitem_start.set_sensitive(True)
551 self.indicator.menuitem_pause.set_sensitive(False)
552 self.indicator.menuitem_pause.set_active(False)
553 self.indicator.menuitem_finish.set_sensitive(False)
554 self.indicator.menuitem_show.set_sensitive(True)
555 self.indicator.menuitem_quit.set_sensitive(True)
556
557 if prefs.autosave_picture:
558 fname = get_next_filename(prefs.picture_dest, prefs.autosave_picture_file, ".png")
559 self.grabber.autosave(fname)
560 else:
561 self.grabber.save_capture(self.old_pic_path)
562
563
564 def cb_pause_request(self, widget):
565 logger.debug("Pause requested.")
566 self.recording_paused = True
567 self.recorder.pause_recording()
568
569 def cb_unpause_request(self, widget):
570 logger.debug("Unpause requested.")
571 self.recording_paused = False
572 self.recorder.unpause_recording()
573
574 def cb_save_done(self, widget, result):
575 logger.debug("Save Done, result: {0}".format(result))
576 if self.main_mode == MODE_SCREENCAST:
577 self.old_vid_path = result
578 else:
579 self.old_pic_path = result
580
581 self.window.set_sensitive(True)
582 self.window.show_all()
583 self.window.present()
584 self.window.move(prefs.main_x, prefs.main_y)
585
586 def cb_save_cancel(self, widget):
587 try:
588 logger.debug("Save canceled, removing {0}".format(self.tempfile))
589 os.remove(self.tempfile)
590 except OSError:
591 logger.info("Failed to remove tempfile {0}".format(self.tempfile))
592 except AttributeError:
593 logger.info("Failed to remove tempfile {0}".format(self.tempfile))
594 pass
595
596 self.window.set_sensitive(True)
597 self.window.show_all()
598 self.window.present()
599 self.window.move(prefs.main_x, prefs.main_y)
600
601 def cb_help_about(self, widget):
602 AboutDialog(self.icons)
603
604 def cb_edit_request(self, widget, data):
605 (command, arg_list) = data
606 arg_list.insert(0, command)
607 #
608 # Even if we're not autosaving get the next autosave file and move currently recorded file there
609 # In case user might lost it.
610 #
611 fname = get_next_filename(prefs.video_dest,
612 prefs.autosave_video_file,
613 CODEC_LIST[prefs.codec][3])
614
615 shutil.move(self.tempfile, fname)
616 arg_list.append(fname)
617 logger.debug("Edit request, cmd: {0}".format(arg_list))
618 try:
619 Popen(arg_list)
620 except:
621 logger.warning("Failed to open selected editor. Have no ")
622 self.window.set_sensitive(True)
623 self.window.show_all()
624
625 def cb_check_cursor(self, widget):
626 prefs.capture_cursor = widget.get_active()
627 logger.debug("Capture cursor: {0}.".format(prefs.capture_cursor))
628
629 def cb_check_cursor_pic(self, widget):
630 prefs.capture_cursor_pic = widget.get_active()
631 logger.debug("Capture cursor_pic: {0}.".format(prefs.capture_cursor_pic))
632
633 def cb_check_borders_pic(self, widget):
634 prefs.capture_borders_pic = widget.get_active()
635 logger.debug("Capture borders_pic: {0}.".format(prefs.capture_borders_pic))
636
637 def cb_check_speakers(self, widget):
638 prefs.capture_speakers = widget.get_active()
639 logger.debug("Capture speakers: {0}.".format(prefs.capture_speakers))
640
641 def cb_check_microphone(self, widget):
642 prefs.capture_microphone = widget.get_active()
643 logger.debug("Capture microphone: {0}.".format(prefs.capture_microphone))
644
645 def cb_spinbutton_delay_change(self, widget):
646 prefs.countdown_timer = widget.get_value_as_int()
647 logger.debug("Start delay now: {0}".format(prefs.countdown_timer))
648
649 #
650 # Other somewhat useful stuff ...
651 #
652
653 def run_counter(self):
654 #
655 # Annoyances with the menus
656 #
657 (main_x, main_y) = self.window.get_position()
658 if main_x and main_y:
659 prefs.main_x = main_x
660 prefs.main_y = main_y
661
662 self.indicator.recording = True
663 self.indicator.menuitem_start.set_sensitive(False)
664 self.indicator.menuitem_pause.set_sensitive(False)
665 self.indicator.menuitem_finish.set_sensitive(True)
666 self.indicator.menuitem_show.set_sensitive(False)
667 self.indicator.menuitem_quit.set_sensitive(False)
668 self.indicator.menuitem_finish.set_label(_("Cancel countdown"))
669 self.in_countdown = True
670
671 self.indicator.blink_set_state(BLINK_START)
672
673 if self.main_mode == MODE_SCREENCAST and prefs.sound:
674 if prefs.capture_speakers and prefs.audio_source > 0:
675 audio_source = prefs.audio_sources[prefs.audio_source][1]
676 else:
677 audio_source = None
678
679 if prefs.capture_microphone and prefs.audio2_source > 0:
680 audio2_source = prefs.audio_sources[prefs.audio2_source][1]
681 else:
682 audio2_source = None
683 else:
684 audio_source = None
685 audio2_source = None
686
687 #
688 # Get appropriate coordinates for recording
689 #
690
691 video_source = None
692
693 if self.record_mode == MODE_FULL:
694 screen = HW.get_current_screen(self.window)
695 video_source = HW.screens[screen]
696 else:
697 video_source = HW.combined_screen
698
699 if self.main_mode == MODE_SCREENCAST:
700 self.recorder = Screencast()
701 self.recorder.setup_sources(video_source,
702 audio_source,
703 audio2_source,
704 prefs.area if self.record_mode == MODE_AREA else None,
705 prefs.xid if self.record_mode == MODE_WIN else None)
706
707 self.recorder.connect("flush-done", self.cb_flush_done)
708
709 elif self.main_mode == MODE_SCREENSHOT:
710 self.grabber = Grabber()
711 self.grabber.setup_sources(video_source,
712 prefs.area if self.record_mode == MODE_AREA else None,
713 prefs.xid if self.record_mode == MODE_WIN else None)
714 self.grabber.connect("flush-done", self.cb_flush_done)
715
716
717 self.countdown = CountdownWindow(self.indicator, show_window = prefs.countdown_splash)
718 self.countdown.connect("counter-finished", self.cb_counter_finished)
719 self.countdown.run(prefs.countdown_timer)
720 self.recording = True
721 logger.debug("Hiding main window.")
722 self.window.hide()
723
724 def setup_translations(self):
725 gettext.bindtextdomain("kazam", "/usr/share/locale")
726 gettext.textdomain("kazam")
727 try:
728 locale.setlocale(locale.LC_ALL, "")
729 except Exception as e:
730 logger.exception("EXCEPTION: Setlocale failed, no language support.")
731
732
733 def restore_UI (self):
734 self.window.move(prefs.main_x, prefs.main_y)
735 self.chk_cursor.set_active(prefs.capture_cursor)
736 self.chk_speakers.set_active(prefs.capture_speakers)
737 self.chk_microphone.set_active(prefs.capture_microphone)
738 self.chk_cursor_pic.set_active(prefs.capture_cursor_pic)
739 self.chk_borders_pic.set_active(prefs.capture_borders_pic)
740 self.spinbutton_delay.set_value(prefs.countdown_timer)
741
742 #
743 # Turn off the combined screen icon if we don't have more than one screen.
744 #
745 if HW.combined_screen:
746 self.btn_allscreens.set_sensitive(True)
747 else:
748 self.btn_allscreens.set_sensitive(False)
0749
=== added directory 'build/lib.linux-x86_64-2.7/kazam/backend'
=== added file 'build/lib.linux-x86_64-2.7/kazam/backend/__init__.py'
--- build/lib.linux-x86_64-2.7/kazam/backend/__init__.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/backend/__init__.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,1 @@
1
02
=== added file 'build/lib.linux-x86_64-2.7/kazam/backend/config.py'
--- build/lib.linux-x86_64-2.7/kazam/backend/config.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/backend/config.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,128 @@
1# -*- coding: utf-8 -*-
2#
3# config.py
4#
5# Copyright 2012 David Klasinc <bigwhale@lubica.net>
6# Copyright 2010 Andrew <andrew@karmic-desktop>
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21# MA 02110-1301, USA.
22
23import os
24from ConfigParser import SafeConfigParser, NoSectionError, NoOptionError
25from xdg.BaseDirectory import xdg_config_home
26
27class KazamConfig(SafeConfigParser):
28
29 DEFAULTS = [{
30 "name": "main",
31 "keys": {
32 "video_toggled" : "True",
33 "video_source" : "0",
34 "audio_toggled" : "False",
35 "audio_source" : "0",
36 "audio_volume" : "0",
37 "audio2_toggled" : "False",
38 "audio2_source" : "0",
39 "audio2_volume" : "0",
40 "codec" : "0",
41 "counter" : "5",
42 "capture_cursor" : "True",
43 "capture_microphone" : "False",
44 "capture_speakers" : "False",
45 "capture_cursor_pic" : "True",
46 "capture_borders_pic" : "True",
47 "framerate" : "15",
48 "countdown_splash" : "True",
49 "last_x" : "60",
50 "last_y" : "25",
51 "advanced" : "0",
52 "silent" : "0",
53 "autosave_video" : "False",
54 "autosave_video_dir" : "",
55 "autosave_video_file" : "Kazam_screencast",
56 "autosave_picture" : "False",
57 "autosave_picture_dir" : "",
58 "autosave_picture_file" : "Kazam_screenshot",
59 "shutter_sound" : "True",
60 "shutter_type" : "0",
61 },
62 },
63 {
64 "name": "keyboard_shortcuts",
65 "keys": {
66 "pause": "<Shift><Control>p",
67 "finish": "<Shift><Control>f",
68 "show": "<Shift><Control>s",
69 "quit": "<Shift><Control>q",
70 },
71 }]
72
73 CONFIGDIR = os.path.join(xdg_config_home, "kazam")
74 CONFIGFILE = os.path.join(CONFIGDIR, "kazam.conf")
75
76 def __init__(self):
77 SafeConfigParser.__init__(self, self.DEFAULTS[0]['keys'])
78 if not os.path.isdir(self.CONFIGDIR):
79 os.makedirs(self.CONFIGDIR)
80 if not os.path.isfile(self.CONFIGFILE):
81 self.create_default()
82 self.write()
83 self.read(self.CONFIGFILE)
84
85 def create_default(self):
86 # For every section
87 for section in self.DEFAULTS:
88 # Add the section
89 self.add_section(section["name"])
90 # And add every key in it, with its default value
91 for key in section["keys"]:
92 value = section["keys"][key]
93 self.set(section["name"], key, value)
94
95 def find_default(self, section, key):
96 for d_section in self.DEFAULTS:
97 if d_section["name"] == section:
98 for d_key in d_section["keys"]:
99 if d_key == key:
100 return d_section["keys"][key]
101
102 def get(self, section, key):
103 try:
104 return SafeConfigParser.get(self, section, key)
105 except NoSectionError:
106 default = self.find_default(section, key)
107 self.set(section, key, default)
108 self.write()
109 return default
110 except NoOptionError:
111 default = self.find_default(section, key)
112 self.set(section, key, default)
113 self.write()
114 return default
115
116 def set(self, section, option, value):
117 # If the section referred to doesn't exist (rare case),
118 # then create it
119 if not self.has_section(section):
120 self.add_section(section)
121 SafeConfigParser.set(self, section, option, str(value))
122
123 def write(self):
124 file_ = open(self.CONFIGFILE, "w")
125 SafeConfigParser.write(self, file_)
126 file_.close()
127
128
0129
=== added file 'build/lib.linux-x86_64-2.7/kazam/backend/constants.py'
--- build/lib.linux-x86_64-2.7/kazam/backend/constants.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/backend/constants.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,152 @@
1# -*- coding: utf-8 -*-
2#
3# constants.py
4#
5# Copyright 2012 David Klasinc <bigwhale@lubica.net>
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 3 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20# MA 02110-1301, USA.
21
22
23# Codecs
24
25CODEC_RAW = 0
26CODEC_VP8 = 1
27CODEC_H264 = 2
28CODEC_HUFF = 3
29CODEC_JPEG = 4
30
31#
32# Number, gstreamer element name, string description, file extension, advanced
33#
34
35CODEC_LIST = [
36 [0, None, 'RAW / AVI', '.avi', True],
37 [1, 'vp8enc', 'VP8 / WEBM', '.webm', False],
38 [2, 'x264enc', 'H264 / MP4', '.mp4', False],
39 [3, 'ffenc_huffyuv', 'HUFFYUV / AVI', '.avi', True],
40 [4, 'ffenc_ljpeg', 'Lossless JPEG / AVI', '.avi', True],
41 ]
42
43# PulseAudio Error Codes
44PA_LOAD_ERROR = 1
45PA_GET_STATE_ERROR = 2
46PA_STARTUP_ERROR = 3
47PA_UNABLE_TO_CONNECT = 4
48PA_UNABLE_TO_CONNECT2 = 5
49PA_MAINLOOP_START_ERROR = 6
50PA_GET_SOURCES_ERROR = 7
51PA_GET_SOURCES_TIMEOUT = 8
52PA_GET_SOURCE_ERROR = 9
53PA_GET_SOURCE_TIMEOUT = 10
54PA_MAINLOOP_END_ERROR = 11
55
56
57# PulseAudio Status Codes
58PA_STOPPED = 0
59PA_WORKING = 1
60PA_FINISHED = 2
61PA_ERROR = 3
62
63# PulseAudio State Codes
64PA_STATE_READY = 0
65PA_STATE_BUSY = 1
66PA_STATE_FAILED = 2
67PA_STATE_WORKING = 3
68
69
70# Various actions
71ACTION_SAVE = 0
72ACTION_EDIT = 1
73
74# Blink modes and states
75BLINK_STOP = 0
76BLINK_START = 1
77BLINK_SLOW = 2
78BLINK_FAST = 3
79BLINK_STOP_ICON = 4
80BLINK_READY_ICON = 5
81
82# Main modes
83MODE_SCREENCAST = 0
84MODE_SCREENSHOT = 1
85
86# Record modes
87MODE_FULL = 0
88MODE_ALL = 1
89MODE_AREA = 2
90MODE_WIN = 3
91MODE_ACTIVE = 4
92MODE_GOD = 666
93
94import logging
95
96from gi.repository import Gdk, GdkX11
97
98class hw:
99 def __init__(self):
100 self.logger = logging.getLogger("Constants")
101 self.logger.debug("Getting hardware specs")
102 self.screens = None
103 self.combined_screen = None
104
105 self.get_screens()
106
107 def get_current_screen(self, window = None):
108 try:
109 if window:
110 screen = self.default_screen.get_monitor_at_window(window.get_window())
111 else:
112 disp = GdkX11.X11Display.get_default()
113 dm = Gdk.Display.get_device_manager(disp)
114 pntr_device = dm.get_client_pointer()
115 (src, x, y) = pntr_device.get_position()
116 screen = self.default_screen.get_monitor_at_point(x, y)
117 except:
118 screen = 0
119 return screen
120
121 def get_screens(self):
122 try:
123 self.logger.debug("Getting Video sources.")
124 self.screens = []
125 self.default_screen = Gdk.Screen.get_default()
126 self.logger.debug("Found {0} monitors.".format(self.default_screen.get_n_monitors()))
127
128 for i in range(self.default_screen.get_n_monitors()):
129 rect = self.default_screen.get_monitor_geometry(i)
130 self.logger.debug(" Monitor {0} - X: {1}, Y: {2}, W: {3}, H: {4}".format(i,
131 rect.x,
132 rect.y,
133 rect.width,
134 rect.height))
135 self.screens.append({"x": rect.x,
136 "y": rect.y,
137 "width": rect.width,
138 "height": rect.height})
139
140 if self.default_screen.get_n_monitors() > 1:
141 self.combined_screen = {"x": 0, "y": 0,
142 "width": self.default_screen.get_width(),
143 "height": self.default_screen.get_height()}
144 self.logger.debug(" Combined screen - X: 0, Y: 0, W: {0}, H: {1}".format(self.default_screen.get_width(),
145 self.default_screen.get_height()))
146 else:
147 self.combined_screen = None
148
149 except:
150 self.logger.warning("Unable to find any video sources.")
151
152HW = hw()
0153
=== added file 'build/lib.linux-x86_64-2.7/kazam/backend/export.py'
--- build/lib.linux-x86_64-2.7/kazam/backend/export.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/backend/export.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,194 @@
1# -*- coding: utf-8 -*-
2#
3# export_backend.py
4#
5# Copyright 2012 David Klasinc <bigwhale@lubica.net>
6# Copyright 2010 Andrew <andrew@karmic-desktop>
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21# MA 02110-1301, USA.
22
23import os
24
25from gi.repository import GObject
26
27import kazam.backend.export_sources
28from kazam.utils import *
29
30class ExportBackend(GObject.GObject):
31
32 __gsignals__ = {
33 "authenticate-requested" : (GObject.SIGNAL_RUN_LAST,
34 GObject.TYPE_NONE,
35 ([GObject.TYPE_PYOBJECT,
36 GObject.TYPE_PYOBJECT,
37 GObject.TYPE_PYOBJECT]),),
38 "login-started" : (GObject.SIGNAL_RUN_LAST,
39 GObject.TYPE_NONE,
40 ( ),),
41 "login-completed" : (GObject.SIGNAL_RUN_LAST,
42 GObject.TYPE_NONE,
43 ([bool]),),
44 "convert-started" : (GObject.SIGNAL_RUN_LAST,
45 GObject.TYPE_NONE,
46 ( ),),
47 "convert-completed" : (GObject.SIGNAL_RUN_LAST,
48 GObject.TYPE_NONE,
49 ([bool]),),
50 "upload-started" : (GObject.SIGNAL_RUN_LAST,
51 GObject.TYPE_NONE,
52 ( ),),
53 "upload-completed" : (GObject.SIGNAL_RUN_LAST,
54 GObject.TYPE_NONE,
55 ([bool, str]),),
56 }
57
58 def __init__(self, frontend, datadir):
59 super(ExportBackend, self).__init__()
60
61 self.frontend = frontend
62 self.frontend.connect("export-requested", self.cb_export_requested)
63
64 self.datadir = datadir
65 self.active_export_object = None
66
67 self.error = False
68
69 export_module_files = self._get_export_module_files()
70 self.export_objects = self._create_export_objects(export_module_files)
71
72 def _get_export_module_files(self):
73 """
74 Returns a list of export source files
75 """
76 export_module_list = []
77 # For each directory that provides kazam.export_sources
78 for path in kazam.backend.export_sources.__path__:
79 directory = os.path.abspath(path)
80 # List files in that directory
81 for f in os.listdir(directory):
82 # If the file is a python file append the file to our list
83 if f[-3:] == ".py":
84 export_module_list.append(f)
85
86 # Remove __init__.py and any duplicates
87 export_module_list.remove("__init__.py")
88 export_module_list = remove_list_dups(export_module_list)
89
90 return export_module_list
91
92 def _import_export_module(self, name):
93 """
94 Import an export_source module and return the module
95 """
96 return getattr(__import__("kazam.backend.export_sources", globals(),
97 locals(), [name], -1), name)
98
99 def _create_export_objects(self, export_module_files):
100 """
101 Return a list of export objects
102 """
103 export_objects = []
104 for f in export_module_files:
105 f = f[:-3]
106 # Find and import the module for each file
107 module = self._import_export_module(f)
108 # Append an instance of it, to our export_objects list
109 upload_source = module.UploadSource()
110 upload_source.gui_extra(self.datadir)
111 export_objects.append(upload_source)
112 return export_objects
113
114 def get_export_objects(self):
115 return self.export_objects
116
117 def set_active_export_object(self, i):
118 self.active_export_object = self.export_objects[i]
119 return self.active_export_object
120
121 def get_active_export_object(self):
122 return self.active_export_object
123
124 def get_export_meta(self):
125 return self.export_object.META
126
127 def cb_export_requested(self, frontend):
128 self.error = False
129 self.login()
130 if not self.error:
131 self.create_meta()
132 if not self.error:
133 self.convert()
134 if not self.error:
135 self.upload()
136
137 def login(self):
138 if self.active_export_object.authentication == True:
139 self.emit("authenticate-requested",
140 self.active_export_object.ICONS,
141 self.active_export_object.NAME,
142 self.active_export_object.REGISTER_URL)
143 else:
144 self.details = (None, None)
145 if hasattr(self, "details"):
146 try:
147 self.emit("login-started")
148 (username, password) = self.details
149 self.active_export_object.login_pre(username, password)
150 create_wait_thread(self.active_export_object.login_in)
151 self.active_export_object.login_post()
152 success = True
153 except Exception, e:
154 print e
155 self.error = True
156 success = False
157 else:
158 success = False
159 self.error = True
160 self.emit("login-completed", success)
161
162 def create_meta(self):
163 self.active_export_object.create_meta(**self.frontend.get_meta())
164
165 def convert(self):
166 self.emit("convert-started")
167 try:
168 screencast = self.frontend.get_screencast()
169 screencast.convert(self.active_export_object.FFMPEG_OPTIONS,
170 self.active_export_object.FFMPEG_FILE_EXTENSION,
171 self.frontend.get_video_quality(),
172 self.frontend.get_audio_quality())
173 while not hasattr(screencast, "converted_file"):
174 gtk.main_iteration()
175 self.converted_file_path = screencast.converted_file
176 self.emit("convert-completed", True)
177 except Exception, e:
178 print e
179 self.error = True
180 self.emit("convert-completed", False)
181
182 def upload(self):
183 self.emit("upload-started")
184 url = ""
185 try:
186 self.active_export_object.upload_pre()
187 create_wait_thread(self.active_export_object.upload_in, (self.converted_file_path,))
188 url = self.active_export_object.upload_post()
189 success = True
190 except Exception, e:
191 print e
192 self.error = True
193 success = False
194 self.emit("upload-completed", success, url)
0195
=== added file 'build/lib.linux-x86_64-2.7/kazam/backend/ffmpeg.py'
--- build/lib.linux-x86_64-2.7/kazam/backend/ffmpeg.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/backend/ffmpeg.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,132 @@
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4# recording.py
5#
6# Copyright 2012 David Klasinc <bigwhale@lubica.net>
7# Copyright 2010 Andrew <andrew@karmic-desktop>
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22# MA 02110-1301, USA.
23
24from subprocess import Popen
25import tempfile
26import os
27import gobject
28import glib
29import signal
30
31class Screencast(object):
32 def __init__(self):
33 self.tempfile = tempfile.mktemp(prefix="kazam_", suffix=".mkv")
34
35 def setup_sources(self, video_source, audio_source):
36 self.audio_source = audio_source
37 self.video_source = video_source
38
39 # TODO: use gstreamer instead (see gstreamer.py for start)
40 self.args_list = ["ffmpeg"]
41
42 # Add the audio source if selected
43 if audio_source:
44 self.args_list += ["-f", "alsa", "-i", "pulse"]
45
46 # Add the video source
47 if video_source:
48 x = video_source.x
49 y = video_source.y
50 width = video_source.width
51 height = video_source.height
52 display = video_source.display
53 self.args_list += ["-f", "x11grab", "-r", "30", "-s",
54 "%sx%s" % (width, height), "-i",
55 "%s+%s,%s" % (display, x, y)]
56 if audio_source:
57 self.args_list += ["-ac", "2", "-acodec", "flac", "-ab", "128k"]
58
59 if video_source:
60 self.args_list += ["-vcodec", "libx264",
61 "-crf", "0",
62 "-preset", "fast",
63 "-tune", "stillimage",
64 "-vf", "unsharp=3:3:0.5:3:3:0.0"
65
66 ]
67 self.args_list += ["-threads", "0", self.tempfile]
68
69 arg_string = ""
70 for arg in self.args_list:
71 arg_string += " %s" % arg
72 print arg_string
73
74 def start_recording(self):
75 self.recording_command = Popen(self.args_list)
76
77 def pause_recording(self):
78 self.recording_command.send_signal(signal.SIGTSTP)
79
80 def unpause_recording(self):
81 self.recording_command.send_signal(signal.SIGCONT)
82
83 def stop_recording(self):
84 self.recording_command.send_signal(signal.SIGINT)
85
86 def get_recording_filename(self):
87 return self.tempfile
88
89 def get_audio_recorded(self):
90 return self.audio_source
91
92 def get_video_recorded(self):
93 return self.video_source
94
95 def convert(self, options, converted_file_extension, video_quality=None,
96 audio_quality=None):
97
98 self.converted_file_extension = converted_file_extension
99
100 # Create our ffmpeg arguments list
101 args_list = ["ffmpeg"]
102 # Add the input file
103 args_list += ["-i", self.tempfile]
104 # Add any UploadSource specific options
105 args_list += options
106
107 # Configure the quality as selected by the user
108 # If the quality slider circle is at the right-most position
109 # use the same quality option
110 if video_quality == 6001:
111 args_list += ["-sameq"]
112 elif video_quality:
113 args_list += ["-b", "%sk" % video_quality]
114 if audio_quality:
115 args_list += ["-ab", "%sk" % audio_quality]
116 # Finally add the desired output file
117 args_list += ["%s%s" %(self.tempfile[:-4], converted_file_extension)]
118
119 # Run the ffmpeg command and when it is done, set a variable to
120 # show we have finished
121 command = Popen(args_list)
122 glib.timeout_add(100, self._poll, command)
123
124 def _poll(self, command):
125 ret = command.poll()
126 if ret is None:
127 # Keep monitoring
128 return True
129 else:
130 self.converted_file = "%s%s" %(self.tempfile[:-4], self.converted_file_extension)
131 return False
132
0133
=== added file 'build/lib.linux-x86_64-2.7/kazam/backend/grabber.py'
--- build/lib.linux-x86_64-2.7/kazam/backend/grabber.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/backend/grabber.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,166 @@
1# -*- coding: utf-8 -*-
2#
3# grabber.py
4#
5# Copyright 2012 David Klasinc <bigwhale@lubica.net>
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 3 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20# MA 02110-1301, USA.
21
22
23import os
24import subprocess
25import logging
26logger = logging.getLogger("Grabber")
27
28from gi.repository import GObject, Gtk, Gdk, GdkPixbuf, GdkX11
29
30from kazam.backend.prefs import *
31from kazam.backend.constants import *
32from kazam.frontend.save_dialog import SaveDialog
33from gettext import gettext as _
34
35class Grabber(GObject.GObject):
36 __gsignals__ = {
37 "save-done" : (GObject.SIGNAL_RUN_LAST,
38 None,
39 [GObject.TYPE_PYOBJECT],),
40 "flush-done" : (GObject.SIGNAL_RUN_LAST,
41 None,
42 (),),
43 }
44
45 def __init__(self):
46 GObject.GObject.__init__(self)
47 logger.debug("Starting Grabber.")
48
49
50 def setup_sources(self, video_source, area, xid, active = False, god = False):
51 self.video_source = video_source
52 self.area = area
53 self.xid = xid
54 self.god = god
55 if active:
56 from gi.repository import GdkX11
57 active_win = HW.default_screen.get_active_window()
58 self.xid = GdkX11.X11Window.get_xid(active_win)
59
60 logger.debug("Grabber source: {0}, {1}, {2}, {3}".format(self.video_source['x'],
61 self.video_source['y'],
62 self.video_source['width'],
63 self.video_source['height']))
64
65 def grab(self):
66 self.pixbuf = None
67 disp = GdkX11.X11Display.get_default()
68 dm = Gdk.Display.get_device_manager(disp)
69 pntr_device = dm.get_client_pointer()
70
71 #
72 # Rewrite this, because it sucks
73 #
74 if prefs.shutter_sound and (not self.god):
75 soundfile = os.path.join(prefs.datadir, 'sounds', prefs.sound_files[prefs.shutter_type])
76 subprocess.call(['/usr/bin/canberra-gtk-play', '-f', soundfile])
77
78 if self.xid:
79 if prefs.capture_borders_pic:
80 app_win = GdkX11.X11Window.foreign_new_for_display(disp, self.xid)
81 (rx, ry, rw, rh) = app_win.get_geometry()
82 area = app_win.get_frame_extents()
83 (fx, fy, fw, fh) = (area.x, area.y, area.width, area.height)
84 win = Gdk.get_default_root_window()
85 logger.debug("Coordinates RX {0} RY {1} RW {2} RH {3}".format(rx, ry, rw, rh))
86 logger.debug("Coordinates FX {0} FY {1} FW {2} FH {3}".format(fx, fy, fw, fh))
87 dx = fw - rw
88 dy = fh - rh
89 (x, y, w, h) = (fx, fy, fw, fh)
90 logger.debug("Coordinates delta: DX {0} DY {1}".format(dx, dy))
91 else:
92 win = GdkX11.X11Window.foreign_new_for_display(disp, self.xid)
93 (x, y, w, h) = win.get_geometry()
94 else:
95 win = Gdk.get_default_root_window()
96 (x, y, w, h) = (self.video_source['x'],
97 self.video_source['y'],
98 self.video_source['width'],
99 self.video_source['height'])
100
101 logger.debug("Coordinates X {0} Y {1} W {2} H {3}".format(x, y, w, h))
102 self.pixbuf = Gdk.pixbuf_get_from_window(win, x, y, w, h)
103
104 if prefs.capture_cursor_pic:
105 logger.debug("Adding cursor.")
106
107 cursor = Gdk.Cursor.new_for_display(Gdk.Display.get_default(), Gdk.CursorType.LEFT_PTR)
108 c_picbuf = Gdk.Cursor.get_image(cursor)
109
110 if self.xid and prefs.capture_borders_pic:
111 pointer = app_win.get_device_position(pntr_device)
112 (px, py) = (pointer[1], pointer[2])
113 c_picbuf.composite(self.pixbuf, rx, ry, rw, rh,
114 px + dx - 6,
115 py + dy - 2,
116 1.0,
117 1.0,
118 GdkPixbuf.InterpType.BILINEAR,
119 255)
120 else:
121 pointer = win.get_device_position(pntr_device)
122 (px, py) = (pointer[1], pointer[2])
123 #
124 # Cursor is offseted by 6 pixels to the right and 2 down
125 #
126 c_picbuf.composite(self.pixbuf, x, y, w, h,
127 px - 6,
128 py - 2,
129 1.0,
130 1.0,
131 GdkPixbuf.InterpType.BILINEAR,
132 255)
133
134 logger.debug("Cursor coords: {0} {1}".format(px, py))
135
136 if self.area is not None:
137 logger.debug("Cropping image.")
138 self.area_buf = GdkPixbuf.Pixbuf.new(GdkPixbuf.Colorspace.RGB, True, 8, self.area[4], self.area[5])
139 self.pixbuf.copy_area(self.area[0], self.area[1], self.area[4], self.area[5], self.area_buf, 0, 0)
140 self.pixbuf = None
141 self.pixbuf = self.area_buf
142
143 self.emit("flush-done")
144
145 def save(self, filename):
146 if self.pixbuf is not None:
147 self.pixbuf.savev(filename, "png", "", "")
148
149 def save_capture(self, old_path):
150 logger.debug("Saving screenshot.")
151 self.old_path = old_path
152 (dialog, result, self.old_path) = SaveDialog(_("Save capture"),
153 self.old_path, None, main_mode=MODE_SCREENSHOT)
154
155 if result == Gtk.ResponseType.OK:
156 uri = os.path.join(dialog.get_current_folder(), dialog.get_filename())
157
158 self.save(uri)
159
160 dialog.destroy()
161 self.emit("save-done", self.old_path)
162
163 def autosave(self, filename):
164 logger.debug("Autosaving to: {0}".format(filename))
165 self.save(filename)
166 self.emit("save-done", filename)
0167
=== added file 'build/lib.linux-x86_64-2.7/kazam/backend/gstreamer.py'
--- build/lib.linux-x86_64-2.7/kazam/backend/gstreamer.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/backend/gstreamer.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,416 @@
1# -*- coding: utf-8 -*-
2#
3# gstreamer.py
4#
5# Copyright 2012 David Klasinc <bigwhale@lubica.net>
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 3 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20# MA 02110-1301, USA.
21
22import os
23import logging
24logger = logging.getLogger("GStreamer-GI")
25
26import tempfile
27import multiprocessing
28
29#
30# This needs to be set before we load GStreamer modules!
31#
32os.environ["GST_DEBUG_DUMP_DOT_DIR"] = "/tmp"
33os.putenv("GST_DEBUG_DUMP_DOT_DIR", "/tmp")
34
35from gi.repository import GObject, Gst
36
37from kazam.backend.prefs import *
38from kazam.backend.constants import *
39
40GObject.threads_init()
41Gst.init(None)
42Gst.debug_set_active(True)
43
44class Screencast(GObject.GObject):
45 __gsignals__ = {
46 "flush-done" : (GObject.SIGNAL_RUN_LAST,
47 None,
48 (),
49 ),
50 }
51 def __init__(self):
52 GObject.GObject.__init__(self)
53
54 self.temp_fh = tempfile.mkstemp(prefix="kazam_", dir=prefs.video_dest, suffix=".movie")
55 self.tempfile = self.temp_fh[1]
56 self.muxer_tempfile = "{0}.mux".format(self.tempfile)
57 self.pipeline = Gst.Pipeline()
58 self.area = None
59 self.xid = None
60 self.crop_vid = False
61
62 def setup_sources(self,
63 video_source,
64 audio_source,
65 audio2_source,
66 area,
67 xid):
68
69
70 # Get the number of cores available then use all except one for encoding
71 self.cores = multiprocessing.cpu_count()
72
73 if self.cores > 1:
74 self.cores -= 1
75
76 self.audio_source = audio_source
77 self.audio2_source = audio2_source
78 self.video_source = video_source
79 self.area = area
80 self.xid = xid
81
82 logger.debug("audio_source : {0}".format(audio_source))
83 logger.debug("video_source: {0}".format(video_source))
84 logger.debug("xid: {0}".format(xid))
85 logger.debug("area: {0}".format(area))
86
87 logger.debug("Capture Cursor: {0}".format(prefs.capture_cursor))
88 logger.debug("Framerate : {0}".format(prefs.framerate))
89 logger.debug("Codec: {0}".format(CODEC_LIST[prefs.codec][1]))
90
91 if self.video_source or self.area:
92 self.setup_video_source()
93
94 if self.audio_source:
95 self.setup_audio_source()
96
97 if self.audio2_source:
98 self.setup_audio2_source()
99
100 self.setup_filesink()
101 self.setup_pipeline()
102 self.setup_links()
103
104 self.bus = self.pipeline.get_bus()
105 self.bus.add_signal_watch()
106 self.bus.connect("message", self.on_message)
107
108 def setup_video_source(self):
109
110 if prefs.test:
111 self.videosrc = Gst.ElementFactory.make("videotestsrc", "video_src")
112 self.videosrc.set_property("pattern", "smpte")
113 else:
114 self.videosrc = Gst.ElementFactory.make("ximagesrc", "video_src")
115
116 if self.area:
117 logger.debug("Capturing area.")
118 startx = self.area[0] if self.area[0] > 0 else 0
119 starty = self.area[1] if self.area[1] > 0 else 0
120 endx = self.area[2]
121 endy = self.area[3]
122 else:
123 startx = self.video_source['x']
124 starty = self.video_source['y']
125 width = self.video_source['width']
126 height = self.video_source['height']
127 endx = startx + width - 1
128 endy = starty + height - 1
129
130 #
131 # H264 requirement is that video dimensions are divisible by 2.
132 # If they are not, we have to get rid of that extra pixel.
133 #
134 if not abs(startx - endx) % 2 and prefs.codec == CODEC_H264:
135 endx -= 1
136
137 if not abs(starty - endy) % 2 and prefs.codec == CODEC_H264:
138 endy -= 1
139
140 logger.debug("Coordinates SX: {0} SY: {1} EX: {2} EY: {3}".format(startx, starty, endx, endy))
141
142 if prefs.test:
143 logger.info("Using test signal instead of screen capture.")
144 self.vid_caps = Gst.caps_from_string("video/x-raw,format=(x-raw-rgb),framerate={0}/1, width={1}, height={2}".format(
145 prefs.framerate,
146 endx - startx,
147 endy - starty))
148 self.vid_caps_filter = Gst.ElementFactory.make("capsfilter", "vid_filter")
149 self.vid_caps_filter.set_property("caps", self.vid_caps)
150 else:
151 logger.debug("testing for xid: {0}".format(self.xid))
152 if self.xid: # xid was passed, so we have to capture a single window.
153 logger.debug("Capturing Window: {0} {1}".format(self.xid, prefs.xid_geometry))
154 self.videosrc.set_property("xid", self.xid)
155
156 if prefs.codec == CODEC_H264:
157 self.videocrop = Gst.ElementFactory.make("videocrop", "cropper")
158 if prefs.xid_geometry[2] % 2:
159 self.videocrop.set_property("left", 1)
160 self.crop_vid = True
161 if prefs.xid_geometry[3] % 2:
162 self.videocrop.set_property("bottom", 1)
163 self.crop_vid = True
164 else:
165 self.videosrc.set_property("startx", startx)
166 self.videosrc.set_property("starty", starty)
167 self.videosrc.set_property("endx", endx)
168 self.videosrc.set_property("endy", endy)
169
170 self.videosrc.set_property("use-damage", False)
171 self.videosrc.set_property("show-pointer", prefs.capture_cursor)
172
173 self.vid_caps = Gst.caps_from_string("video/x-raw,format=(x-raw-rgb),framerate={0}/1".format(prefs.framerate))
174 self.vid_caps_filter = Gst.ElementFactory.make("capsfilter", "vid_filter")
175 self.vid_caps_filter.set_property("caps", self.vid_caps)
176
177 self.videoconvert = Gst.ElementFactory.make("videoconvert", "videoconvert")
178 self.videorate = Gst.ElementFactory.make("videorate", "video_rate")
179
180 logger.debug("Codec: {0}".format(CODEC_LIST[prefs.codec][2]))
181
182 if prefs.codec is not CODEC_RAW:
183 self.videnc = Gst.ElementFactory.make(CODEC_LIST[prefs.codec][1], "video_encoder")
184
185 if prefs.codec == CODEC_RAW:
186 self.mux = Gst.ElementFactory.make("avimux", "muxer")
187 elif prefs.codec == CODEC_VP8:
188 self.videnc.set_property("cpu-used", 2)
189 self.videnc.set_property("end-usage", "vbr")
190 self.videnc.set_property("target-bitrate", 800000000)
191 self.videnc.set_property("static-threshold", 1000)
192 self.videnc.set_property("token-partitions", 2)
193 self.videnc.set_property("max-quantizer", 30)
194 self.videnc.set_property("threads", self.cores)
195 self.mux = Gst.ElementFactory.make("webmmux", "muxer")
196 elif prefs.codec == CODEC_H264:
197 self.videnc.set_property("speed-preset", "ultrafast")
198 self.videnc.set_property("pass", 4)
199 self.videnc.set_property("quantizer", 15)
200 #
201 # x264enc supports maximum of four cores
202 #
203 self.videnc.set_property("threads", self.cores if self.cores <= 4 else 4)
204 self.mux = Gst.ElementFactory.make("mp4mux", "muxer")
205 self.mux.set_property("faststart", 1)
206 self.mux.set_property("faststart-file", self.muxer_tempfile)
207 self.mux.set_property("streamable", 1)
208 elif prefs.codec == CODEC_HUFF:
209 self.mux = Gst.ElementFactory.make("avimux", "muxer")
210 self.videnc.set_property("bitrate", 500000)
211 elif prefs.codec == CODEC_JPEG:
212 self.mux = Gst.ElementFactory.make("avimux", "muxer")
213
214 self.vid_in_queue = Gst.ElementFactory.make("queue", "queue_v1")
215 self.vid_out_queue = Gst.ElementFactory.make("queue", "queue_v2")
216
217 def setup_audio_source(self):
218 logger.debug("Audio1 Source:\n {0}".format(self.audio_source))
219 self.audiosrc = Gst.ElementFactory.make("pulsesrc", "audio_src")
220 self.audiosrc.set_property("device", self.audio_source)
221 self.aud_caps = Gst.caps_from_string("audio/x-raw")
222 self.aud_caps_filter = Gst.ElementFactory.make("capsfilter", "aud_filter")
223 self.aud_caps_filter.set_property("caps", self.aud_caps)
224 self.audioconv = Gst.ElementFactory.make("audioconvert", "audio_conv")
225 if prefs.codec == CODEC_VP8:
226 self.audioenc = Gst.ElementFactory.make("vorbisenc", "audio_encoder")
227 self.audioenc.set_property("quality", 1)
228 else:
229 self.audioenc = Gst.ElementFactory.make("lamemp3enc", "audio_encoder")
230 self.audioenc.set_property("quality", 0)
231
232 self.aud_in_queue = Gst.ElementFactory.make("queue", "queue_a_in")
233 self.aud_out_queue = Gst.ElementFactory.make("queue", "queue_a_out")
234
235 def setup_audio2_source(self):
236 logger.debug("Audio2 Source:\n {0}".format(self.audio2_source))
237 self.audiomixer = Gst.ElementFactory.make("adder", "audiomixer")
238 self.audio2src = Gst.ElementFactory.make("pulsesrc", "audio2_src")
239 self.audio2src.set_property("device", self.audio2_source)
240 self.aud2_caps = Gst.caps_from_string("audio/x-raw")
241 self.aud2_caps_filter = Gst.ElementFactory.make("capsfilter", "aud2_filter")
242 self.aud2_caps_filter.set_property("caps", self.aud2_caps)
243 self.aud2_in_queue = Gst.ElementFactory.make("queue", "queue_a2_in")
244 self.audio2conv = Gst.ElementFactory.make("audioconvert", "audio2_conv")
245
246 def setup_filesink(self):
247 logger.debug("Filesink: {0}".format(self.tempfile))
248 self.sink = Gst.ElementFactory.make("filesink", "sink")
249 self.sink.set_property("location", self.tempfile)
250 self.file_queue = Gst.ElementFactory.make("queue", "queue_file")
251
252 #
253 # One day, this horrific code will be optimised... I promise!
254 #
255 def setup_pipeline(self):
256 #
257 # Behold, setup the master pipeline
258 #
259 self.pipeline.add(self.videosrc)
260 self.pipeline.add(self.vid_in_queue)
261 if self.crop_vid:
262 self.pipeline.add(self.videocrop)
263 self.pipeline.add(self.videorate)
264 self.pipeline.add(self.vid_caps_filter)
265 self.pipeline.add(self.videoconvert)
266 self.pipeline.add(self.vid_out_queue)
267 self.pipeline.add(self.file_queue)
268
269 if prefs.codec is not CODEC_RAW:
270 self.pipeline.add(self.videnc)
271
272 if self.audio_source:
273 self.pipeline.add(self.audiosrc)
274 self.pipeline.add(self.aud_in_queue)
275 self.pipeline.add(self.aud_caps_filter)
276 self.pipeline.add(self.aud_out_queue)
277 self.pipeline.add(self.audioconv)
278 self.pipeline.add(self.audioenc)
279
280 if self.audio2_source:
281 self.pipeline.add(self.audiomixer)
282 self.pipeline.add(self.aud2_in_queue)
283 self.pipeline.add(self.audio2src)
284 self.pipeline.add(self.aud2_caps_filter)
285
286 self.pipeline.add(self.mux)
287 self.pipeline.add(self.sink)
288
289 # gst-launch-1.0 -e ximagesrc endx=1919 endy=1079 use-damage=false show-pointer=true ! \
290 # queue ! videorate ! video/x-raw,framerate=15/1 ! videoconvert ! \
291 # vp8enc end-usage=vbr target-bitrate=800000000 threads=3 static-threshold=1000 \
292 # token-partitions=2 max-quantizer=30 ! queue name=before_mux ! webmmux name=mux ! \
293 # queue ! filesink location="test-videorate.webm"
294
295 def setup_links(self):
296 # Connect everything together
297 self.videosrc.link(self.vid_in_queue)
298 if self.crop_vid:
299 self.vid_in_queue.link(self.videocrop)
300 self.videocrop.link(self.videorate)
301 else:
302 self.vid_in_queue.link(self.videorate)
303 self.videorate.link(self.vid_caps_filter)
304 self.vid_caps_filter.link(self.videoconvert)
305 if prefs.codec is CODEC_RAW:
306 self.videoconvert.link(self.vid_out_queue)
307 logger.debug("Linking RAW Video")
308 else:
309 logger.debug("Linking Video")
310 self.videoconvert.link(self.videnc)
311 self.videnc.link(self.vid_out_queue)
312
313 self.vid_out_queue.link(self.mux)
314
315 if self.audio_source:
316 logger.debug("Linking Audio")
317 ret = self.audiosrc.link(self.aud_in_queue)
318 logger.debug(" Link audiosrc -> aud_in_queue: %s" % ret)
319 ret = self.aud_in_queue.link(self.aud_caps_filter)
320 logger.debug(" Link aud_in_queue -> aud_caps_filter: %s" % ret)
321
322 if self.audio2_source:
323 logger.debug("Linking Audio2")
324 # Link first audio source to mixer
325 ret = self.aud_caps_filter.link(self.audiomixer)
326 logger.debug(" Link aud_caps_filter -> audiomixer: %s" % ret)
327
328 # Link second audio source to mixer
329 ret = self.audio2src.link(self.aud2_in_queue)
330 logger.debug(" Link audio2src -> aud2_in_queue: %s" % ret)
331 ret = self.aud2_in_queue.link(self.aud2_caps_filter)
332 logger.debug(" Link aud2_in_queue -> aud2_caps_filter: %s" % ret)
333 ret = self.aud2_caps_filter.link(self.audiomixer)
334 logger.debug(" Link aud2_caps_filter -> audiomixer: %s" % ret)
335
336 # Link mixer to audio convert
337 ret = self.audiomixer.link(self.audioconv)
338 logger.debug(" Link audiomixer -> audioconv: %s" % ret)
339
340 else:
341 # Link first audio source to audio convert
342 ret = self.aud_caps_filter.link(self.audioconv)
343 logger.debug(" Link aud_caps_filter -> audioconv: %s" % ret)
344
345 # Link audio to muxer
346 ret = self.audioconv.link(self.audioenc)
347 logger.debug("Link audioconv -> audioenc: %s" % ret)
348 ret = self.audioenc.link(self.aud_out_queue)
349 logger.debug("Link audioenc -> aud_out_queue: %s" % ret)
350 ret = self.aud_out_queue.link(self.mux)
351 logger.debug("Link aud_out_queue -> mux: %s" % ret)
352
353 ret = self.mux.link(self.file_queue)
354 logger.debug("Link mux -> file queue: %s" % ret)
355 ret = self.file_queue.link(self.sink)
356 logger.debug("Link file queue -> sink: %s" % ret)
357
358 def start_recording(self):
359 logger.debug("Setting STATE_PLAYING")
360 self.pipeline.set_state(Gst.State.PLAYING)
361
362 def pause_recording(self):
363 logger.debug("Setting STATE_PAUSED")
364 self.pipeline.set_state(Gst.State.PAUSED)
365
366 def unpause_recording(self):
367 logger.debug("Setting STATE_PLAYING - UNPAUSE")
368 self.pipeline.set_state(Gst.State.PLAYING)
369
370 def stop_recording(self):
371 logger.debug("Sending new EOS event")
372 self.pipeline.send_event(Gst.Event.new_eos())
373
374 def get_tempfile(self):
375 return self.tempfile
376
377 def get_audio_recorded(self):
378 return self.audio
379
380 def on_message(self, bus, message):
381 t = message.type
382 if t == Gst.MessageType.EOS:
383 logger.debug("Received EOS, setting pipeline to NULL.")
384 self.pipeline.set_state(Gst.State.NULL)
385 logger.debug("Emitting flush-done.")
386 self.emit("flush-done")
387 elif t == Gst.MessageType.ERROR:
388 logger.debug("Received an error message: %s", message.parse_error()[1])
389
390
391def detect_codecs():
392 codecs_supported = []
393 codec_test = None
394 for codec in CODEC_LIST:
395 if codec[0]:
396 try:
397 codec_test = Gst.ElementFactory.make(codec[1], "video_encoder")
398 except:
399 logger.info("Unable to find {0} GStreamer plugin - support disabled.".format(codec))
400 codec_test = None
401
402 if codec_test:
403 codecs_supported.append(codec[0])
404 logger.info("Supported encoder: {0}.".format(codec[2]))
405 else:
406 # RAW codec is None, so we don't try to load it.
407 codecs_supported.append(codec[0])
408 logger.info("Supported encoder: {0}.".format(codec[2]))
409 codec_test = None
410 return codecs_supported
411
412def get_codec(codec):
413 for c in CODEC_LIST:
414 if c[0] == codec:
415 return c
416 return None
0417
=== added file 'build/lib.linux-x86_64-2.7/kazam/backend/prefs.py'
--- build/lib.linux-x86_64-2.7/kazam/backend/prefs.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/backend/prefs.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,232 @@
1# -*- coding: utf-8 -*-
2#
3# prefs.py
4#
5# Copyright 2012 David Klasinc <bigwhale@lubica.net>
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 3 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20# MA 02110-1301, USA.
21
22import os
23import logging
24from gettext import gettext as _
25from xdg.BaseDirectory import xdg_config_home
26
27from kazam.backend.config import KazamConfig
28
29
30class Prefs():
31 def __init__(self):
32 """Initialize prefs and set all the preference variables to their
33 default values.
34
35 Args:
36 None
37
38 Returns:
39 None
40
41 Raises:
42 None
43 """
44 self.logger = logging.getLogger("Prefs")
45
46 #
47 # GUI preferences and stuff
48 #
49 self.capture_cursor = False
50 self.capture_speakers = False
51 self.capture_microphone = False
52
53 self.capture_cursor_pic = False
54 self.capture_borders_pic = False
55
56 self.countdown_timer = 5
57
58 self.speakers_source = None
59 self.microphone_source = None
60
61 self.speakers_volume = 0
62 self.microphone_volume = 0
63
64 self.countdown_splash = True
65 self.silent_start = False
66
67 #
68 # Other stuff
69 #
70 self.datadir = None
71
72 #
73 # Capture related stuff
74 #
75 self.codec = None
76 self.pa_q = None
77 self.framerate = 15
78 self.autosave_video = False
79 self.autosave_video_file = None
80
81 self.autosave_picture = False
82 self.autosave_picture_file = None
83 self.shutter_sound = True
84 self.shutter_type = 0
85 self.shutter_sound_file = ""
86
87 self.area = None
88 self.xid = None
89 self.xid_geometry = None
90
91 #
92 # Audio sources
93 # - Tuple of all sources
94 # - Selected first source
95 # - Selected second source
96 #
97 self.audio_sources = None
98 self.audio_source = None
99 self.audio2_source = None
100
101 #
102 # Command line parameters
103 #
104 self.debug = False
105 self.test = False
106 self.dist = ('Ubuntu', '12.10', 'quantal')
107 self.silent = False
108 self.sound = True
109
110 self.config = KazamConfig()
111
112 self.read_config()
113
114 self.get_dirs()
115
116 def get_audio_sources(self):
117 self.logger.debug("Getting Audio sources.")
118 try:
119 self.audio_sources = prefs.pa_q.get_audio_sources()
120 #self.audio_sources.insert(0, [])
121 if prefs.debug:
122 for src in self.audio_sources:
123 self.logger.debug(" Device found: ")
124 for item in src:
125 self.logger.debug(" - {0}".format(item))
126 except:
127 # Something went wrong, just fallback to no-sound
128 self.logger.warning("Unable to find any audio devices.")
129 self.audio_sources = [[0, _("Unknown"), _("Unknown")]]
130
131 def get_dirs(self):
132 paths = {}
133 f = None
134 try:
135 f = open(os.path.join(xdg_config_home, "user-dirs.dirs"))
136 for la in f:
137 if la.startswith("XDG_VIDEOS") or la.startswith("XDG_DOCUMENTS") or la.startswith("XDG_PICTURES") :
138 (idx, val) = la.strip()[:-1].split('="')
139 paths[idx] = os.path.expandvars(val)
140 except:
141 paths['XDG_VIDEOS_DIR'] = os.path.expanduser("~/Videos/")
142 paths['XDG_PICTURES_DIR'] = os.path.expanduser("~/Pictures/")
143 paths['XDG_DOCUMENTS_DIR'] = os.path.expanduser("~/Documents/")
144 finally:
145 if f is not None:
146 f.close()
147
148 paths['HOME_DIR'] = os.path.expandvars("$HOME")
149
150 if os.path.isdir(paths['XDG_VIDEOS_DIR']):
151 self.video_dest = paths['XDG_VIDEOS_DIR']
152 elif os.path.isdir(paths['XDG_DOCUMENTS_DIR']):
153 self.video_dest = paths['XDG_DOCUMENTS_DIR']
154 elif os.path.isdir(paths['HOME_DIR']):
155 self.video_dest = paths['HOME_DIR']
156
157 if os.path.isdir(paths['XDG_PICTURES_DIR']):
158 self.picture_dest = paths['XDG_PICTURES_DIR']
159 elif os.path.isdir(paths['XDG_DOCUMENTS_DIR']):
160 self.picture_dest = paths['XDG_DOCUMENTS_DIR']
161 elif os.path.isdir(paths['HOME_DIR']):
162 self.picture_dest = paths['HOME_DIR']
163
164
165 def get_sound_files(self):
166 self.sound_files = []
167 for root, dir, files in os.walk(os.path.join(self.datadir, "sounds")):
168 for file in files:
169 if file.endswith('.ogg'):
170 self.sound_files.append(file)
171
172
173 def read_config (self):
174 self.audio_source = self.config.getint("main", "audio_source")
175 self.audio2_source = self.config.getint("main", "audio2_source")
176
177 self.main_x = self.config.getint("main", "last_x")
178 self.main_y = self.config.getint("main", "last_y")
179
180 self.codec = self.config.getint("main", "codec")
181
182 self.countdown_timer = self.config.getfloat("main", "counter")
183 self.framerate = self.config.getfloat("main", "framerate")
184
185 self.capture_cursor = self.config.getboolean("main", "capture_cursor")
186 self.capture_microphone = self.config.getboolean("main", "capture_microphone")
187 self.capture_speakers = self.config.getboolean("main", "capture_speakers")
188
189 self.capture_cursor_pic = self.config.getboolean("main", "capture_cursor_pic")
190 self.capture_borders_pic = self.config.getboolean("main", "capture_borders_pic")
191
192 self.countdown_splash = self.config.getboolean("main", "countdown_splash")
193
194 self.autosave_video = self.config.getboolean("main", "autosave_video")
195 self.autosave_video_file = self.config.get("main", "autosave_video_file")
196
197 self.autosave_picture = self.config.getboolean("main", "autosave_picture")
198 self.autosave_picture_file = self.config.get("main", "autosave_picture_file")
199
200 self.shutter_sound = self.config.getboolean("main", "shutter_sound")
201 self.shutter_type = self.config.getint("main", "shutter_type")
202
203
204 def save_config(self):
205 self.config.set("main", "capture_cursor", self.capture_cursor)
206 self.config.set("main", "capture_speakers", self.capture_speakers)
207 self.config.set("main", "capture_microphone", self.capture_microphone)
208
209 self.config.set("main", "capture_cursor_pic", self.capture_cursor_pic)
210 self.config.set("main", "capture_borders_pic", self.capture_borders_pic)
211
212 self.config.set("main", "last_x", self.main_x)
213 self.config.set("main", "last_y", self.main_y)
214
215 if self.sound:
216 self.config.set("main", "audio_source", self.audio_source)
217 self.config.set("main", "audio2_source", self.audio2_source)
218
219 self.config.set("main", "countdown_splash", self.countdown_splash)
220 self.config.set("main", "counter", self.countdown_timer)
221 self.config.set("main", "codec", self.codec)
222 self.config.set("main", "framerate", self.framerate)
223 self.config.set("main", "autosave_video", self.autosave_video)
224 self.config.set("main", "autosave_video_file", self.autosave_video_file)
225 self.config.set("main", "autosave_picture", self.autosave_picture)
226 self.config.set("main", "autosave_picture_file", self.autosave_picture_file)
227 self.config.set("main", "shutter_sound", self.shutter_sound)
228 self.config.set("main", "shutter_type", self.shutter_type)
229
230 self.config.write()
231
232prefs = Prefs()
0233
=== added directory 'build/lib.linux-x86_64-2.7/kazam/frontend'
=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/__init__.py'
--- build/lib.linux-x86_64-2.7/kazam/frontend/__init__.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/frontend/__init__.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,1 @@
1
02
=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/about_dialog.py'
--- build/lib.linux-x86_64-2.7/kazam/frontend/about_dialog.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/frontend/about_dialog.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,70 @@
1# -*- coding: utf-8 -*-
2#
3# authenticate.py
4#
5# Copyright 2012 David Klasinc <bigwhale@lubica.net>
6# Copyright 2010 Andrew <andrew@karmic-desktop>
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21# MA 02110-1301, USA.
22
23from gettext import gettext as _
24from gi.repository import Gtk
25from kazam.version import *
26
27AUTHORS = """
28Andrew Higginson <rugby471@gmail.com>
29David Klasinc <bigwhale@lubica.net>
30"""
31
32ARTISTS = """
33Robert McKenna <ttk1opc@yahoo.com>
34Andrew Higginson <rugby471@gmail.com>
35"""
36LICENSE = """
37 This program is free software: you can redistribute it and/or modify
38 it under the terms of the GNU General Public License as published by
39 the Free Software Foundation, either version 3 of the License, or
40 (at your option) any later version.
41
42 This program is distributed in the hope that it will be useful,
43 but WITHOUT ANY WARRANTY; without even the implied warranty of
44 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
45 GNU General Public License for more details.
46
47 You should have received a copy of the GNU General Public License
48 along with this program. If not, see <http://www.gnu.org/licenses/>.
49"""
50
51def AboutDialog(icons):
52 dialog = Gtk.AboutDialog()
53 dialog.set_program_name(_("Kazam Screencaster") + " - \"" + CODENAME + "\"")
54 dialog.set_comments(_("Record a video of activity on your screen."))
55 dialog.set_license(LICENSE)
56 dialog.set_version(VERSION)
57 dialog.set_copyright("© 2010 Andrew Higginson, © 2012 David Klasinc")
58 dialog.set_website("http://launchpad.net/kazam")
59 dialog.set_authors(AUTHORS.split("\n"))
60 dialog.set_artists(ARTISTS.split("\n"))
61 try:
62 icon = icons.load_icon("kazam", 96, Gtk.IconLookupFlags.GENERIC_FALLBACK)
63 dialog.set_logo(icon)
64 except:
65 # Not important, we just don't get to show our lovely logo.. :)
66 pass
67 dialog.show_all()
68 dialog.set_position(Gtk.WindowPosition.CENTER)
69 dialog.run()
70 dialog.hide()
071
=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/combobox.py'
--- build/lib.linux-x86_64-2.7/kazam/frontend/combobox.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/frontend/combobox.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,116 @@
1# -*- coding: utf-8 -*-
2#
3# combobox.py
4#
5# Copyright 2012 David Klasinc <bigwhale@lubica.net>
6# Copyright 2010 Andrew <andrew@karmic-desktop>
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21# MA 02110-1301, USA.
22
23import os
24
25from xdg.DesktopEntry import DesktopEntry
26from gi.repository import Gtk, GdkPixbuf, GObject
27
28from kazam.backend.prefs import *
29
30class EditComboBox(Gtk.ComboBox):
31
32 KDENLIVE_VERSION = [0,8]
33
34 #
35 # This really needs to be done differently ...
36 #
37 if prefs.dist[2] == 'quantal':
38 EDITORS = {
39 "/usr/share/app-install/desktop/openshot:openshot.desktop":[],
40 "/usr/share/app-install/desktop/pitivi:pitivi.desktop":["-i", "-a"],
41 "/usr/share/app-install/desktop/avidemux:avidemux-gtk.desktop":[],
42 "/usr/share/app-install/desktop/kdenlive:kde4__kdenlive.desktop":["-i"],
43 }
44 else:
45 EDITORS = {
46 "/usr/share/applications/openshot.desktop":[],
47 "/usr/share/applications/pitivi.desktop":["-i", "-a"],
48 "/usr/share/applications/avidemux-gtk.desktop":[],
49 "/usr/share/applications/kde4/kdenlive.desktop":["-i"],
50 }
51
52 def __init__(self, icons):
53 Gtk.ComboBox.__init__(self)
54 self.icons = icons
55 self.empty = True
56 cr_pixbuf = Gtk.CellRendererPixbuf()
57 self.pack_start(cr_pixbuf, True)
58 self.add_attribute(cr_pixbuf, 'pixbuf', 0)
59 cr_text = Gtk.CellRendererText()
60 self.pack_start(cr_text, True)
61 self.add_attribute(cr_text, 'text', 1)
62
63 self.box_model = Gtk.ListStore(GdkPixbuf.Pixbuf, str,
64 GObject.TYPE_PYOBJECT,
65 GObject.TYPE_PYOBJECT
66 )
67 self.set_model(self.box_model)
68 self._populate()
69 self.set_active(0)
70 self.set_sensitive(True)
71 self.show()
72
73 def get_active_value(self):
74 i = self.get_active()
75 model = self.get_model()
76 model_iter = model.get_iter(i)
77 return (model.get_value(model_iter, 2),
78 model.get_value(model_iter, 3))
79
80 def _populate(self):
81 for item in self.EDITORS:
82 if os.path.isfile(item):
83 args = self.EDITORS[item]
84 desktop_entry = DesktopEntry(item)
85 command = desktop_entry.getExec()
86
87 # For .desktop files with ' %U' or ' # %F'
88 command = command.split(" ")[0]
89
90 name = desktop_entry.getName()
91 icon_name = desktop_entry.getIcon()
92
93 self._add_item(icon_name, name, command, args)
94
95 if len(self.get_model()):
96 self.empty = False
97 else:
98 self.empty = True
99
100 def _add_item(self, icon_name, name, command, args):
101 liststore = self.get_model()
102 try:
103 pixbuf = self.icons.load_icon(icon_name, 16, Gtk.IconLookupFlags.GENERIC_FALLBACK)
104 except:
105 pixbuf = self.icons.load_icon("application-x-executable", 16, Gtk.IconLookupFlags.GENERIC_FALLBACK)
106
107 liststore.append([pixbuf, name, command, args])
108
109 def _version_is_gte(self, required_version, current_version):
110 i = 0
111 for digit in current_version:
112 required_digit = required_version[i]
113 current_digit = int(digit)
114 if current_digit < required_digit:
115 return False
116 return True
0117
=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/done_recording.py'
--- build/lib.linux-x86_64-2.7/kazam/frontend/done_recording.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/frontend/done_recording.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,159 @@
1# -*- coding: utf-8 -*-
2#
3# app.py
4#
5# Copyright 2012 David Klasinc <bigwhale@lubica.net>
6# Copyright 2010 Andrew <andrew@karmic-desktop>
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21# MA 02110-1301, USA.
22
23import os
24import shutil
25import logging
26logger = logging.getLogger("Done Recording")
27
28from gettext import gettext as _
29from gi.repository import Gtk, GObject
30
31from kazam.backend.constants import *
32from kazam.frontend.combobox import EditComboBox
33from kazam.frontend.save_dialog import SaveDialog
34
35class DoneRecording(Gtk.Window):
36
37 __gsignals__ = {
38 "save-done" : (GObject.SIGNAL_RUN_LAST,
39 None,
40 [GObject.TYPE_PYOBJECT],),
41 "edit-request" : (GObject.SIGNAL_RUN_LAST,
42 None,
43 [GObject.TYPE_PYOBJECT],),
44 "save-cancel" : (GObject.SIGNAL_RUN_LAST,
45 None,
46 (),)
47 }
48
49 def __init__(self, icons, tempfile, codec, old_path):
50 Gtk.Window.__init__(self, title=_("Kazam Screencaster - Recording finished"))
51 self.icons = icons
52 self.tempfile = tempfile
53 self.codec = codec
54 self.action = ACTION_SAVE
55 self.old_path = old_path
56 self.set_position(Gtk.WindowPosition.NONE)
57
58 # Setup UI
59 self.set_border_width(10)
60 self.vbox = Gtk.Box(spacing = 20, orientation = Gtk.Orientation.VERTICAL)
61 self.label_box = Gtk.Box()
62 self.done_label = Gtk.Label(_("Kazam finished recording.\nWhat do you want to do now?"))
63 self.label_box.add(self.done_label)
64 self.grid = Gtk.Grid(row_spacing = 10, column_spacing = 5)
65 self.radiobutton_edit = Gtk.RadioButton.new_with_label_from_widget(None, _("Edit with:"))
66 self.combobox_editor = EditComboBox(self.icons)
67 self.grid.add(self.radiobutton_edit)
68 self.grid.attach_next_to(self.combobox_editor,
69 self.radiobutton_edit,
70 Gtk.PositionType.RIGHT,
71 1, 1)
72 self.radiobutton_save = Gtk.RadioButton.new_from_widget(self.radiobutton_edit)
73 self.radiobutton_save.set_label(_("Save for later"))
74
75 if self.combobox_editor.empty:
76 self.radiobutton_edit.set_active(False)
77 self.radiobutton_edit.set_sensitive(False)
78
79 self.radiobutton_save.set_active(True)
80
81 self.radiobutton_save.connect("toggled", self.cb_radiobutton_save_toggled)
82 self.radiobutton_edit.connect("toggled", self.cb_radiobutton_edit_toggled)
83 self.btn_cancel = Gtk.Button(label = _("Cancel"))
84 self.btn_cancel.set_size_request(100, -1)
85 self.btn_continue = Gtk.Button(label = _("Continue"))
86 self.btn_continue.set_size_request(100, -1)
87
88 self.btn_continue.connect("clicked", self.cb_continue_clicked)
89 self.btn_cancel.connect("clicked", self.cb_cancel_clicked)
90
91 self.hbox = Gtk.Box(spacing = 10)
92 self.left_hbox = Gtk.Box()
93 self.right_hbox = Gtk.Box(spacing = 5)
94
95 self.right_hbox.pack_start(self.btn_cancel, False, True, 0)
96 self.right_hbox.pack_start(self.btn_continue, False, True, 0)
97
98 self.hbox.pack_start(self.left_hbox, True, True, 0)
99 self.hbox.pack_start(self.right_hbox, False, False, 0)
100
101 self.vbox.pack_start(self.label_box, True, True, 0)
102 self.vbox.pack_start(self.grid, True, True, 0)
103 self.vbox.pack_start(self.radiobutton_save, True, True, 0)
104 self.vbox.pack_start(self.hbox, True, True, 0)
105 self.add(self.vbox)
106 self.connect("delete-event", self.cb_delete_event)
107 self.show_all()
108 self.present()
109
110
111 def cb_continue_clicked(self, widget):
112 if self.action == ACTION_EDIT:
113 logger.debug("Continue - Edit.")
114 (command, args) = self.combobox_editor.get_active_value()
115 self.emit("edit-request", (command, args))
116 self.destroy()
117 else:
118 self.set_sensitive(False)
119 logger.debug("Continue - Save ({0}).".format(self.codec))
120 (dialog, result, self.old_path) = SaveDialog(_("Save screencast"),
121 self.old_path, self.codec)
122
123 if result == Gtk.ResponseType.OK:
124 uri = os.path.join(dialog.get_current_folder(), dialog.get_filename())
125
126 if not uri.endswith(CODEC_LIST[self.codec][3]):
127 uri += CODEC_LIST[self.codec][3]
128
129 shutil.move(self.tempfile, uri)
130 dialog.destroy()
131 self.emit("save-done", self.old_path)
132 self.destroy()
133 else:
134 self.set_sensitive(True)
135 dialog.destroy()
136
137
138 def cb_cancel_clicked(self, widget):
139 self.emit("save-cancel")
140 self.destroy()
141
142 def cb_delete_event(self, widget, data):
143 self.emit("save-cancel")
144 self.destroy()
145
146 def cb_radiobutton_save_toggled(self, widget):
147 if not widget.get_active():
148 return
149 else:
150 self.action = ACTION_SAVE
151 self.combobox_editor.set_sensitive(False)
152
153 def cb_radiobutton_edit_toggled(self, widget):
154 if not widget.get_active():
155 return
156 else:
157 self.action = ACTION_EDIT
158 self.combobox_editor.set_sensitive(True)
159
0160
=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/export.py'
--- build/lib.linux-x86_64-2.7/kazam/frontend/export.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/frontend/export.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,269 @@
1# -*- coding: utf-8 -*-
2#
3# export_frontend.py
4#
5# Copyright 2012 David Klasinc <bigwhale@lubica.net>
6# Copyright 2010 Andrew <andrew@karmic-desktop>
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21# MA 02110-1301, USA.
22
23import logging
24import os
25
26from gettext import gettext as _
27from gi.repository import Gtk, GObject
28
29from kazam.utils import *
30from kazam.backend.export import ExportBackend
31
32class ExportFrontend(GObject.GObject):
33
34 __gsignals__ = {
35 "back-requested" : (GObject.SIGNAL_RUN_LAST,
36 GObject.TYPE_NONE,
37 ( ),),
38 "export-requested" : (GObject.SIGNAL_RUN_LAST,
39 GObject.TYPE_NONE,
40 ( ),)
41 }
42
43 def __init__(self, datadir, icons, recorder):
44 GObject.GObject.__init__(self)
45
46 self.recorder = recorder
47
48 # Setup Backend
49 self.backend = ExportBackend(self, datadir)
50 self.backend.connect("authenticate-requested", self.cb_authenticate_requested)
51 self.backend.connect("login-started", self.cb_login_started)
52 self.backend.connect("login-completed", self.cb_login_completed)
53 self.backend.connect("convert-started", self.cb_convert_started)
54 self.backend.connect("convert-completed", self.cb_convert_completed)
55 self.backend.connect("upload-started", self.cb_upload_started)
56 self.backend.connect("upload-completed", self.cb_upload_completed)
57
58 self.active_alignment = None
59
60 # Setup UI
61 builder = Gtk.Builder()
62 builder.add_from_file(os.path.join(datadir, "ui", "export.ui"))
63
64 # Get window
65 self.window = builder.get_object("window_export")
66 self.window.connect("delete-event", Gtk.main_quit)
67
68 # Setup quality sliders
69 self.setup_quality_sliders()
70
71 # Export combobox setup
72 export_objects = self.backend.get_export_objects()
73 export_object_details = []
74 for obj in export_objects:
75 name = obj.NAME
76 icon = obj.ICONS[0]
77 tup = (icon, name)
78 export_object_details.append(tup)
79
80 self.combobox_export = ExportCombobox(self.icons, export_object_details)
81 self.combobox_export.connect("changed", self.on_combobox_export_changed)
82 self.hbox_export.pack_start(self.combobox_export, False, True)
83 self.hbox_export.reorder_child(self.combobox_export, 1)
84 self.on_combobox_export_changed(None)
85
86 def run(self):
87 self.window.show_all()
88
89 def setup_quality_sliders(self):
90
91 if self.screencast.get_video_recorded():
92 # Video Quality Slider
93 self.adjustment_quality_video = Gtk.Adjustment(3000, 200, 6001, 1)
94 self.hscale_quality_video = Gtk.HScale(self.adjustment_quality_video)
95 self.hscale_quality_video.set_draw_value(False)
96 self.hbox_quality_video.pack_start(self.hscale_quality_video)
97 else:
98 self.vbox_quality_video.destroy()
99
100 # (If audio was recorded) Audio Quality Slider
101 if self.screencast.get_audio_recorded():
102 self.adjustment_quality_audio = Gtk.Adjustment(140, 32, 256, 1)
103 self.hscale_quality_audio = Gtk.HScale(self.adjustment_quality_audio)
104 self.hscale_quality_audio.set_draw_value(False)
105 self.hbox_quality_audio.pack_start(self.hscale_quality_audio)
106 else:
107 self.vbox_quality_audio.destroy()
108
109 def on_button_back_clicked(self, button):
110 self.emit("back-requested")
111 self.window.destroy()
112
113 def on_button_export_clicked(self, button):
114 self.emit("export-requested")
115
116 def on_combobox_export_changed(self, combobox):
117 # If we already have an alignment, unpack it
118 if self.active_alignment:
119 self.vbox_main.remove(self.active_alignment)
120
121 # Get our current item's object
122 i = self.combobox_export.get_active()
123 active_object = self.backend.set_active_export_object(i)
124 # And its alignment
125 self.active_alignment = active_object.alignment_properties
126
127 # Run the alignment's expose function
128 active_object.property_alignment_expose()
129
130 # Pack our alignment
131 self.vbox_main.pack_start(self.active_alignment, True, True)
132 self.vbox_main.reorder_child(self.active_alignment, 2)
133
134 def _change_status(self, img, text):
135 for child in self.hbox_status.get_children():
136 child.destroy()
137 if img == "spinner":
138 img_widget = gtk.Spinner()
139 img_widget.start()
140 else:
141 img_widget = Gtk.image_new_from_stock(img, Gtk.ICON_SIZE_MENU)
142 text_widget = Gtk.Label(text)
143 self.hbox_status.pack_start(img_widget, False, False)
144 self.hbox_status.pack_start(text_widget, False, False)
145 self.hbox_status.show_all()
146
147 def get_screencast(self):
148 return self.screencast
149
150 def get_meta(self):
151 active_export_object = self.backend.get_active_export_object()
152 meta = active_export_object.META.copy()
153 # For every property in the meta dict...
154 for prop in meta:
155 # ..get the corresponding widget in the meta dict
156 widget = getattr(active_export_object, meta[prop])
157 # ...get the corresponding widget value and add to the dict
158 # inplace of the widget
159 meta[prop] = self.get_property_value(widget)
160 return meta
161
162 def get_video_quality(self):
163 if self.screencast.get_video_recorded():
164 return self.adjustment_quality_video.get_value()
165 return False
166
167 def get_audio_quality(self):
168 if self.screencast.get_audio_recorded():
169 return self.adjustment_quality_audio.get_value()
170 return False
171
172 def get_property_value(self, widget):
173 # Convenience function to get property value based on widget type
174 if isinstance(widget, gtk.Entry):
175 return widget.get_text()
176 elif isinstance(widget, gtk.TextView):
177 buf = widget.get_buffer()
178 return buf.get_text(buf.get_start_iter(), buf.get_end_iter())
179 elif isinstance(widget, EasyTextAndObjectComboBox):
180 tuple_ = (widget.get_active_value(0), widget.get_active_value(1))
181 return tuple_
182 elif issubclass(widget.__class__, EasyComboBox):
183 return widget.get_active_value(0)
184
185 def sensitise_content_action_widgets(self, sensitive):
186 self.active_alignment.set_sensitive(sensitive)
187 self.button_export.set_sensitive(sensitive)
188 self.button_back.set_sensitive(sensitive)
189 self.combobox_export.set_sensitive(sensitive)
190 self.label_export.set_sensitive(sensitive)
191
192 def cb_authenticate_requested(self, backend, icons, name, register_url):
193 authenticate_dialog = AuthenticateDialog(self.datadir, name, self.icons, icons, register_url)
194 authenticate_dialog.window.set_transient_for(self.window)
195 authenticate_dialog.run()
196 self.window.set_sensitive(False)
197 while (not hasattr(authenticate_dialog, "details")):
198 if authenticate_dialog.action == authenticate_dialog.ACTION_CANCEL:
199 break
200 gtk.main_iteration()
201 self.window.set_sensitive(True)
202 if authenticate_dialog.action == authenticate_dialog.ACTION_CANCEL:
203 return
204 self.backend.details = authenticate_dialog.details
205
206 def cb_login_started(self, backend):
207 self._change_status("spinner", _("Logging in..."))
208 # Make buttons, combobox, label and the alignment insensitive
209 self.sensitise_content_action_widgets(False)
210
211 def cb_login_completed(self, backend, success):
212 if success:
213 self._change_status(gtk.STOCK_OK, _("Log-in completed."))
214 else:
215 self._change_status(gtk.STOCK_DIALOG_ERROR, _("There was an error logging in."))
216 # Set buttons, combobox and the alignment sensitive
217 self.sensitise_content_action_widgets(True)
218
219 def cb_convert_started(self, backend):
220 self._change_status("spinner", _("Converting screencast..."))
221
222 def cb_convert_completed(self, backend, success):
223 if success:
224 self._change_status(Gtk.STOCK_OK, _("Screencast converted."))
225 else:
226 self._change_status(Gtk.STOCK_DIALOG_ERROR, _("There was an error converting."))
227 # Set buttons, combobox and the alignment sensitive
228 self.sensitise_content_action_widgets(True)
229
230 def cb_upload_started(self, backend):
231 self._change_status("spinner", _("Uploading screencast..."))
232
233 def cb_upload_completed(self, backend, success, url):
234 if success:
235 self._change_status(Gtk.STOCK_OK, _("Screencast uploaded."))
236 # Set buttons, combobox and the alignment sensitive
237 self.sensitise_content_action_widgets(True)
238 # Show a dialog with the url of the uploaded file
239 new_linkbutton_dialog(url, _("Your screencast has uploaded successfully."),
240 _("It is available at the location below:"), self.window)
241 else:
242 self._change_status(Gtk.STOCK_DIALOG_ERROR, _("There was an error uploading."))
243 # Set buttons, combobox and the alignment sensitive
244 self.sensitise_content_action_widgets(True)
245
246
247#if __name__ == "__main__":
248# from kazam.backend.ffmpeg import Screencast
249#
250# if os.path.exists("./data/ui/export.ui"):
251# logging.info("Running locally")
252# datadir = "./data"
253# else:
254# datadir = "/usr/share/kazam/"
255# icons = gtk.icon_theme_get_default()
256# icons.append_search_path(os.path.join(datadir,"icons", "48x48", "apps"))
257# icons.append_search_path(os.path.join(datadir,"icons", "16x16", "apps"))
258
259# screencast = Screencast()
260# screencast.audio = True
261
262 # export = ExportFrontend(datadir, icons, screencast)
263 # export.connect("back-requested", gtk.main_quit)
264 # export.connect("export-requested", gtk.main_quit)
265 # export.connect("quit-requested", gtk.main_quit)
266 # export.run()
267 # gtk.main()
268
269
0270
=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/indicator.py'
--- build/lib.linux-x86_64-2.7/kazam/frontend/indicator.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/frontend/indicator.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,311 @@
1# -*- coding: utf-8 -*-
2#
3# indicator.py
4#
5# Copyright 2012 David Klasinc <bigwhale@lubica.net>
6# Copyright 2010 Andrew <andrew@karmic-desktop>
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21# MA 02110-1301, USA.
22
23import logging
24logger = logging.getLogger("Indicator")
25
26from gettext import gettext as _
27from gi.repository import Gtk, GObject
28
29from kazam.backend.constants import *
30
31class KazamSuperIndicator(GObject.GObject):
32 __gsignals__ = {
33 "indicator-pause-request" : (GObject.SIGNAL_RUN_LAST,
34 None,
35 (), ),
36 "indicator-unpause-request" : (GObject.SIGNAL_RUN_LAST,
37 None,
38 (), ),
39 "indicator-quit-request" : (GObject.SIGNAL_RUN_LAST,
40 None,
41 (), ),
42 "indicator-show-request" : (GObject.SIGNAL_RUN_LAST,
43 None,
44 (), ),
45 "indicator-stop-request" : (GObject.SIGNAL_RUN_LAST,
46 None,
47 (), ),
48 "indicator-start-request" : (GObject.SIGNAL_RUN_LAST,
49 None,
50 (), ),
51
52 "indicator-about-request" : (GObject.SIGNAL_RUN_LAST,
53 None,
54 (), ),
55 }
56
57 def __init__(self, silent = False):
58 super(KazamSuperIndicator, self).__init__()
59 self.blink_icon = BLINK_STOP_ICON
60 self.blink_state = False
61 self.blink_mode = BLINK_SLOW
62 self.recording = False
63 self.silent = silent
64 logger.debug("Indicatior silent: {0}".format(self.silent))
65
66 self.menu = Gtk.Menu()
67
68 self.menuitem_start = Gtk.MenuItem(_("Start recording"))
69 self.menuitem_start.set_sensitive(True)
70 self.menuitem_start.connect("activate", self.on_menuitem_start_activate)
71
72 self.menuitem_pause = Gtk.CheckMenuItem(_("Pause recording"))
73 self.menuitem_pause.set_sensitive(False)
74 self.menuitem_pause.connect("toggled", self.on_menuitem_pause_activate)
75
76 self.menuitem_finish = Gtk.MenuItem(_("Finish recording"))
77 self.menuitem_finish.set_sensitive(False)
78 self.menuitem_finish.connect("activate", self.on_menuitem_finish_activate)
79
80 self.menuitem_separator = Gtk.SeparatorMenuItem()
81 self.menuitem_separator2 = Gtk.SeparatorMenuItem()
82
83 self.menuitem_show = Gtk.MenuItem(_("Record setup"))
84 self.menuitem_show.connect("activate", self.on_menuitem_show_activate)
85
86 self.menuitem_about = Gtk.MenuItem(_("About"))
87 self.menuitem_about.connect("activate", self.on_menuitem_about_activate)
88
89
90 self.menuitem_quit = Gtk.MenuItem(_("Quit"))
91 self.menuitem_quit.connect("activate", self.on_menuitem_quit_activate)
92
93 self.menu.append(self.menuitem_start)
94 self.menu.append(self.menuitem_pause)
95 self.menu.append(self.menuitem_finish)
96 self.menu.append(self.menuitem_separator)
97 self.menu.append(self.menuitem_show)
98 self.menu.append(self.menuitem_about)
99 self.menu.append(self.menuitem_separator2)
100 self.menu.append(self.menuitem_quit)
101
102 self.menu.show_all()
103
104 #
105 # Setup keybindings - Hardcore way
106 #
107 try:
108 from gi.repository import Keybinder
109 logger.debug("Trying to bind hotkeys.")
110 Keybinder.init()
111 Keybinder.bind("<Super><Ctrl>R", self.cb_hotkeys, "start-request")
112 Keybinder.bind("<Super><Ctrl>F", self.cb_hotkeys, "stop-request")
113 Keybinder.bind("<Super><Ctrl>P", self.cb_hotkeys, "pause-request")
114 Keybinder.bind("<Super><Ctrl>W", self.cb_hotkeys, "show-request")
115 Keybinder.bind("<Super><Ctrl>Q", self.cb_hotkeys, "quit-request")
116 self.recording = False
117 except ImportError:
118 logger.info("Unable to import Keybinder, hotkeys not available.")
119
120 def cb_hotkeys(self, key, action):
121 logger.debug("KEY {0}, ACTION {1}".format(key, action))
122 if action == "start-request" and not self.recording:
123 self.on_menuitem_start_activate(None)
124 elif action == "stop-request" and self.recording:
125 self.on_menuitem_finish_activate(None)
126 elif action == "pause-request" and self.recording:
127 if not self.menuitem_pause.get_active():
128 self.menuitem_pause.set_active(True)
129 else:
130 self.menuitem_pause.set_active(False)
131 elif action == "show-request" and not self.recording:
132 self.emit("indicator-show-request")
133 elif action == "quit-request" and not self.recording:
134 self.emit("indicator-quit-request")
135
136 def on_menuitem_pause_activate(self, menuitem):
137 if self.menuitem_pause.get_active():
138 self.emit("indicator-pause-request")
139 else:
140 self.emit("indicator-unpause-request")
141
142 def on_menuitem_start_activate(self, menuitem):
143 self.recording = True
144 self.emit("indicator-start-request")
145
146 def on_menuitem_finish_activate(self, menuitem):
147 self.recording = False
148 self.menuitem_start.set_sensitive(True)
149 self.menuitem_pause.set_sensitive(False)
150 self.menuitem_pause.set_active(False)
151 self.menuitem_finish.set_sensitive(False)
152 self.menuitem_show.set_sensitive(True)
153 self.menuitem_quit.set_sensitive(True)
154 self.emit("indicator-stop-request")
155
156 def on_menuitem_quit_activate(self, menuitem):
157 self.emit("indicator-quit-request")
158
159 def on_menuitem_show_activate(self, menuitem):
160 self.emit("indicator-show-request")
161
162 def on_menuitem_about_activate(self, menuitem):
163 self.emit("indicator-about-request")
164
165try:
166 from gi.repository import AppIndicator3
167
168 class KazamIndicator(KazamSuperIndicator):
169 def __init__(self, silent = False):
170 super(KazamIndicator, self).__init__(silent)
171 self.silent = silent
172
173 self.indicator = AppIndicator3.Indicator.new("kazam",
174 "kazam-stopped",
175 AppIndicator3.IndicatorCategory.APPLICATION_STATUS)
176
177 self.indicator.set_menu(self.menu)
178 self.indicator.set_attention_icon("kazam-recording")
179 self.indicator.set_icon("kazam-stopped")
180
181 if self.silent:
182 self.indicator.set_status(AppIndicator3.IndicatorStatus.PASSIVE)
183 else:
184 self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
185
186 def hide_it(self):
187 self.indicator.set_status(AppIndicator3.IndicatorStatus.PASSIVE)
188
189 def show_it(self):
190 self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
191
192 def on_menuitem_pause_activate(self, menuitem):
193 if menuitem.get_active():
194 self.indicator.set_attention_icon("kazam-paused")
195 logger.debug("Recording paused.")
196 else:
197 self.indicator.set_attention_icon("kazam-recording")
198 logger.debug("Recording resumed.")
199 KazamSuperIndicator.on_menuitem_pause_activate(self, menuitem)
200
201 def on_menuitem_finish_activate(self, menuitem):
202 logger.debug("Recording stopped.")
203 if not self.silent:
204 self.indicator.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
205 KazamSuperIndicator.on_menuitem_finish_activate(self, menuitem)
206
207 def blink_set_state(self, state):
208 if state == BLINK_STOP:
209 self.blink_state = BLINK_STOP
210 self.indicator.set_icon("kazam-stopped")
211 elif state == BLINK_START:
212 self.blink_state = BLINK_SLOW
213 GObject.timeout_add(500, self.blink)
214 elif state == BLINK_SLOW:
215 self.blink_state = BLINK_SLOW
216 elif state == BLINK_FAST:
217 self.blink_state = BLINK_FAST
218
219 def blink(self):
220 if self.blink_state != BLINK_STOP:
221 if self.blink_icon == BLINK_READY_ICON:
222 if not self.silent:
223 self.indicator.set_icon("kazam-stopped")
224 self.blink_icon = BLINK_STOP_ICON
225 else:
226 if not self.silent:
227 self.indicator.set_icon("kazam-countdown")
228 self.blink_icon = BLINK_READY_ICON
229
230 if self.blink_state == BLINK_SLOW:
231 GObject.timeout_add(500, self.blink)
232 elif self.blink_state == BLINK_FAST:
233 GObject.timeout_add(200, self.blink)
234
235 def start_recording(self):
236 logger.debug("Recording started.")
237 if not self.silent:
238 self.indicator.set_status(AppIndicator3.IndicatorStatus.ATTENTION)
239
240except ImportError:
241 #
242 # AppIndicator failed to import, not running Ubuntu?
243 # Fallback to Gtk.StatusIcon.
244 #
245 class KazamIndicator(KazamSuperIndicator):
246
247 def __init__(self, silent = False):
248 super(KazamIndicator, self).__init__()
249 self.silent = silent
250
251 self.indicator = Gtk.StatusIcon()
252 self.indicator.set_from_icon_name("kazam-stopped")
253 self.indicator.connect("popup-menu", self.cb_indicator_popup_menu)
254 self.indicator.connect("activate", self.cb_indicator_activate)
255
256 if self.silent:
257 self.indicator.set_visible(False)
258
259 def cb_indicator_activate(self, widget):
260 def position(menu, widget):
261 return (Gtk.StatusIcon.position_menu(self.menu, widget))
262 self.menu.popup(None, None, position, self.indicator, 0, Gtk.get_current_event_time())
263
264 def cb_indicator_popup_menu(self, icon, button, time):
265 def position(menu, icon):
266 return (Gtk.StatusIcon.position_menu(self.menu, icon))
267 self.menu.popup(None, None, position, self.indicator, button, time)
268
269 def on_menuitem_finish_activate(self, menuitem):
270 logger.debug("Recording stopped.")
271 self.indicator.set_from_icon_name("kazam-stopped")
272 KazamSuperIndicator.on_menuitem_finish_activate(self, menuitem)
273
274 def on_menuitem_pause_activate(self, menuitem):
275 if menuitem.get_active():
276 self.indicator.set_from_icon_name("kazam-paused")
277 logger.debug("Recording paused.")
278 else:
279 self.indicator.set_from_icon_name("kazam-recording")
280 logger.debug("Recording resumed.")
281 KazamSuperIndicator.on_menuitem_pause_activate(self, menuitem)
282
283 def blink_set_state(self, state):
284 if state == BLINK_STOP:
285 self.blink_state = BLINK_STOP
286 self.indicator.set_from_icon_name("kazam-stopped")
287 elif state == BLINK_START:
288 self.blink_state = BLINK_SLOW
289 GObject.timeout_add(500, self.blink)
290 elif state == BLINK_SLOW:
291 self.blink_state = BLINK_SLOW
292 elif state == BLINK_FAST:
293 self.blink_state = BLINK_FAST
294
295 def blink(self):
296 if self.blink_state != BLINK_STOP:
297 if self.blink_icon == BLINK_READY_ICON:
298 self.indicator.set_from_icon_name("kazam-stopped")
299 self.blink_icon = BLINK_STOP_ICON
300 else:
301 self.indicator.set_from_icon_name("kazam-countdown")
302 self.blink_icon = BLINK_READY_ICON
303
304 if self.blink_state == BLINK_SLOW:
305 GObject.timeout_add(500, self.blink)
306 elif self.blink_state == BLINK_FAST:
307 GObject.timeout_add(200, self.blink)
308
309 def start_recording(self):
310 logger.debug("Recording started.")
311 self.indicator.set_from_icon_name("kazam-recording")
0312
=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/main_menu.py'
--- build/lib.linux-x86_64-2.7/kazam/frontend/main_menu.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/frontend/main_menu.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,88 @@
1# -*- coding: utf-8 -*-
2#
3# main_menu.py
4#
5# Copyright 2012 David Klasinc <bigwhale@lubica.net>
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 3 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20# MA 02110-1301, USA.
21
22from gettext import gettext as _
23
24from gi.repository import Gtk, GObject
25
26MENUBAR = """
27 <ui>
28 <menubar name='MenuBar'>
29 <menu action='FileMenu'>
30 <menuitem action='FilePreferences' />
31 <menuitem action='FileQuit' />
32 </menu>
33 <separator />
34 <menu action='HelpMenu'>
35 <menuitem action='HelpAbout' />
36 </menu>
37 </menubar>
38</ui>
39"""
40
41class MainMenu(GObject.GObject):
42 __gsignals__ = {
43 "file-preferences" : (GObject.SIGNAL_RUN_LAST,
44 None,
45 (),
46 ),
47 "file-quit" : (GObject.SIGNAL_RUN_LAST,
48 None,
49 (),
50 ),
51 "help-about" : (GObject.SIGNAL_RUN_LAST,
52 None,
53 (),
54 ),
55 }
56
57 def __init__(self):
58 GObject.GObject.__init__(self)
59
60 self.action_group = Gtk.ActionGroup("kazam_actions")
61 self.action_group.add_actions([
62 ("FileMenu", None, _("File")),
63 ("FileQuit", Gtk.STOCK_QUIT, _("Quit"), None, _("Quit Kazam"),
64 self.cb_file_quit),
65 ("FilePreferences", Gtk.STOCK_PREFERENCES, _("Preferences"), None, _("Open preferences"),
66 self.cb_file_preferences),
67 ("HelpMenu", None, _("Help")),
68 ("HelpAbout", None, _("About"), None , _("About Kazam"),
69 self.cb_help_about)
70 ])
71
72 self.uimanager = Gtk.UIManager()
73 self.uimanager.add_ui_from_string(MENUBAR)
74 self.uimanager.insert_action_group(self.action_group)
75 self.menubar = self.uimanager.get_widget("/MenuBar")
76
77
78 def cb_file_quit(self, action):
79 self.emit("file-quit")
80
81 def cb_file_preferences(self, action):
82 self.emit("file-preferences")
83
84 def cb_help_about(self, action):
85 self.emit("help-about")
86
87
88
089
=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/preferences.py'
--- build/lib.linux-x86_64-2.7/kazam/frontend/preferences.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/frontend/preferences.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,375 @@
1# -*- coding: utf-8 -*-
2#
3# preferences.py
4#
5# Copyright 2012 David Klasinc <bigwhale@lubica.net>
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 3 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20# MA 02110-1301, USA.
21
22import os
23import math
24import logging
25logger = logging.getLogger("Preferences")
26
27from gi.repository import Gtk, Gdk, GObject, Pango
28from gettext import gettext as _
29
30from kazam.utils import *
31from kazam.backend.prefs import *
32from kazam.backend.constants import *
33from kazam.backend.gstreamer import detect_codecs, get_codec
34
35class Preferences(GObject.GObject):
36 __gsignals__ = {
37 "prefs-quit" : (GObject.SIGNAL_RUN_LAST,
38 None,
39 (),
40 ),
41 }
42
43 def __init__(self):
44 GObject.GObject.__init__(self)
45 logger.debug("Preferences Init.")
46 #
47 # Setup UI
48 #
49 logger.debug("Preferences UI setup.")
50
51 self.audio_source_info = None
52 self.audio2_source_info = None
53
54 self.builder = Gtk.Builder()
55 self.builder.add_from_file(os.path.join(prefs.datadir, "ui", "preferences.ui"))
56 self.builder.connect_signals(self)
57 for w in self.builder.get_objects():
58 if issubclass(type(w), Gtk.Buildable):
59 name = Gtk.Buildable.get_name(w)
60 setattr(self, name, w)
61 else:
62 logger.debug("Unable to get name for '%s'" % w)
63
64 codec_renderer = Gtk.CellRendererText()
65
66 audio_renderer = Gtk.CellRendererText()
67 audio_renderer.props.ellipsize = Pango.EllipsizeMode.END
68 audio_renderer.props.max_width_chars = 40
69
70 self.combobox_codec.pack_start(codec_renderer, True)
71 self.combobox_codec.add_attribute(codec_renderer, "text", 1)
72
73 self.combobox_audio.pack_start(audio_renderer, True)
74 self.combobox_audio.add_attribute(audio_renderer, "text", 0)
75
76 self.combobox_audio2.pack_start(audio_renderer, True)
77 self.combobox_audio2.add_attribute(audio_renderer, "text", 0)
78
79 self.filechooser_video.set_current_folder(prefs.video_dest)
80
81 self.populate_codecs()
82 self.populate_audio_sources()
83 self.populate_shutter_sounds()
84
85 self.restore_UI()
86
87 def open(self):
88 self.window.show_all()
89
90 def is_separator(self, model, iter, data):
91 if model.get_value(iter, 0) == 99:
92 return True
93 return False
94
95 def populate_codecs(self):
96 #
97 # Is this necessary?
98 #
99 old_model = self.combobox_codec.get_model()
100 old_model = None
101
102 codec_model = Gtk.ListStore(int, str)
103 codecs = detect_codecs()
104
105 #
106 # I'm sure this could be done without going through the list twice, right?
107 # Fist, we add basic codecs, then a dummy separator item and then advanced codecs.
108 #
109
110 for codec in codecs:
111 if not CODEC_LIST[codec][4]:
112 codec_model.append([CODEC_LIST[codec][0], CODEC_LIST[codec][2]])
113
114 codec_model.append([99, "--"]) # Insert dummy item for separator
115
116 for codec in codecs:
117 if CODEC_LIST[codec][4]:
118 codec_model.append([CODEC_LIST[codec][0], CODEC_LIST[codec][2]])
119
120 self.combobox_codec.set_model(codec_model)
121 self.combobox_codec.set_row_separator_func(self.is_separator, None)
122
123 def populate_audio_sources(self):
124 audio_source_model = Gtk.ListStore(str)
125 for source in prefs.audio_sources:
126 audio_source_model.append([source[2]])
127
128 self.combobox_audio.set_model(audio_source_model)
129 self.combobox_audio2.set_model(audio_source_model)
130
131 def populate_shutter_sounds(self):
132 for file in prefs.sound_files:
133 self.combobox_shutter_type.append(None, file[:-4])
134
135 def restore_UI(self):
136 logger.debug("Restoring UI.")
137
138 if prefs.sound:
139 self.combobox_audio.set_active(prefs.audio_source)
140 self.combobox_audio2.set_active(prefs.audio2_source)
141 else:
142 self.combobox_audio.set_sensitive(False)
143 self.combobox_audio2.set_sensitive(False)
144 self.volumebutton_audio.set_sensitive(False)
145 self.volumebutton_audio2.set_sensitive(False)
146
147 if prefs.countdown_splash:
148 self.switch_countdown_splash.set_active(True)
149 else:
150 self.switch_countdown_splash.set_active(False)
151
152 self.spinbutton_framerate.set_value(prefs.framerate)
153
154 if prefs.autosave_video:
155 self.switch_autosave_video.set_active(True)
156 self.filechooser_video.set_sensitive(True)
157 self.entry_autosave_video.set_sensitive(True)
158 else:
159 self.switch_autosave_video.set_active(False)
160 self.filechooser_video.set_sensitive(False)
161 self.entry_autosave_video.set_sensitive(False)
162
163 self.entry_autosave_video.set_text(prefs.autosave_video_file)
164
165 self.filechooser_video.set_current_folder(prefs.video_dest)
166
167
168 if prefs.shutter_sound:
169 self.switch_shutter_sound.set_active(True)
170 self.combobox_shutter_type.set_sensitive(True)
171 else:
172 self.switch_shutter_sound.set_active(False)
173 self.combobox_shutter_type.set_sensitive(False)
174
175 self.combobox_shutter_type.set_active(prefs.shutter_type)
176
177 if prefs.autosave_picture:
178 self.switch_autosave_picture.set_active(True)
179 self.filechooser_picture.set_sensitive(True)
180 self.entry_autosave_picture.set_sensitive(True)
181
182 else:
183 self.switch_autosave_picture.set_active(False)
184 self.filechooser_picture.set_sensitive(False)
185 self.entry_autosave_picture.set_sensitive(False)
186
187 self.entry_autosave_picture.set_text(prefs.autosave_picture_file)
188
189 self.filechooser_picture.set_current_folder(prefs.picture_dest)
190
191
192 #
193 # Crappy code below ... Can this be done some other way?
194 #
195 codec_model = self.combobox_codec.get_model()
196 cnt = 0
197 bingo = False
198 for entry in codec_model:
199 if prefs.codec == entry[0]:
200 bingo = True
201 break
202 cnt += 1
203 if not bingo:
204 cnt = 0
205
206 #
207 # No, I wasn't kidding ...
208 #
209 codec_iter = codec_model.get_iter(cnt)
210 self.combobox_codec.set_active_iter(codec_iter)
211 prefs.codec = codec_model.get_value(codec_iter, 0)
212
213 #
214 # General callbacks
215 #
216
217 def cb_delete_event(self, widget, user_data):
218 logger.debug("Deleteting preferences window")
219 self.emit("prefs-quit")
220
221 def cb_switch_countdown_splash(self, widget, user_data):
222 prefs.countdown_splash = widget.get_active()
223 logger.debug("Countdown splash: {0}.".format(prefs.countdown_splash))
224
225 def cb_audio_changed(self, widget):
226 logger.debug("Audio Changed.")
227 prefs.audio_source = self.combobox_audio.get_active()
228 logger.debug(" - A_1 {0}".format(prefs.audio_source))
229
230 pa_audio_idx = prefs.audio_sources[prefs.audio_source][0]
231 prefs.pa_q.set_source_mute_by_index(pa_audio_idx, 0)
232
233 logger.debug(" - PA Audio1 IDX: {0}".format(pa_audio_idx))
234 self.audio_source_info = prefs.pa_q.get_source_info_by_index(pa_audio_idx)
235 if len(self.audio_source_info) > 0:
236 val = prefs.pa_q.cvolume_to_dB(self.audio_source_info[2])
237 if math.isinf(val):
238 vol = 0
239 else:
240 vol = 60 + val
241 self.volumebutton_audio.set_value(vol)
242 else:
243 logger.debug("Error getting volume info for Audio 1")
244 if len(self.audio_source_info):
245 logger.debug("New Audio1: {0}".format(self.audio_source_info[3]))
246 else:
247 logger.debug("New Audio1: Error retrieving data.")
248
249 if prefs.audio_source == prefs.audio2_source:
250 if prefs.audio_source < len(prefs.audio_sources) - 1:
251 prefs.audio2_source += 1
252 else:
253 prefs.audio2_source = 0
254 self.combobox_audio2.set_active(prefs.audio2_source)
255
256 def cb_audio2_changed(self, widget):
257 logger.debug("Audio2 Changed.")
258
259 prefs.audio2_source = self.combobox_audio2.get_active()
260 logger.debug(" - A_2 {0}".format(prefs.audio2_source))
261
262 pa_audio2_idx = prefs.audio_sources[prefs.audio2_source][0]
263 prefs.pa_q.set_source_mute_by_index(pa_audio2_idx, 0)
264
265 logger.debug(" - PA Audio2 IDX: {0}".format(pa_audio2_idx))
266 self.audio2_source_info = prefs.pa_q.get_source_info_by_index(pa_audio2_idx)
267
268 if len(self.audio2_source_info) > 0:
269 val = prefs.pa_q.cvolume_to_dB(self.audio2_source_info[2])
270 if math.isinf(val):
271 vol = 0
272 else:
273 vol = 60 + val
274 self.volumebutton_audio2.set_value(vol)
275 else:
276 logger.debug("Error getting volume info for Audio 1")
277
278 if len(self.audio2_source_info):
279 logger.debug("New Audio2:\n {0}".format(self.audio2_source_info[3]))
280 else:
281 logger.debug("New Audio2:\n Error retrieving data.")
282
283 if prefs.audio_source == prefs.audio2_source:
284 if prefs.audio_source < len(prefs.audio_sources) - 1:
285 prefs.audio2_source += 1
286 else:
287 prefs.audio2_source = 0
288 self.combobox_audio2.set_active(prefs.audio2_source)
289
290 def cb_volume_changed(self, widget, value):
291 logger.debug("Volume 1 changed, new value: {0}".format(value))
292 idx = self.combobox_audio.get_active()
293 pa_idx = prefs.audio_sources[idx][0]
294 chn = self.audio_source_info[2].channels
295 cvol = prefs.pa_q.dB_to_cvolume(chn, value-60)
296 prefs.pa_q.set_source_volume_by_index(pa_idx, cvol)
297
298 def cb_volume2_changed(self, widget, value):
299 logger.debug("Volume 2 changed, new value: {0}".format(value))
300 idx = self.combobox_audio2.get_active()
301 pa_idx = prefs.audio_sources[idx][0]
302 chn = self.audio_source_info[2].channels
303 cvol = prefs.pa_q.dB_to_cvolume(chn, value-60)
304 prefs.pa_q.set_source_volume_by_index(pa_idx, cvol)
305
306 #
307 # Screencasting callbacks
308 #
309
310 def cb_spinbutton_framerate_change(self, widget):
311 prefs.framerate = widget.get_value_as_int()
312 logger.debug("Framerate now: {0}".format(prefs.framerate))
313
314 def cb_codec_changed(self, widget):
315 i = widget.get_active()
316 model = widget.get_model()
317 iter = model.get_iter(i)
318 prefs.codec = model.get_value(iter, 0)
319 logger.debug('Codec selected: {0} - {1}'.format(get_codec(prefs.codec)[2], prefs.codec))
320
321 def cb_switch_autosave_video(self, widget, user_data):
322 prefs.autosave_video = widget.get_active()
323 logger.debug("Autosave for Video: {0}.".format(prefs.autosave_video))
324
325 if prefs.autosave_video:
326 self.filechooser_video.set_sensitive(True)
327 self.entry_autosave_video.set_sensitive(True)
328 else:
329 self.filechooser_video.set_sensitive(False)
330 self.entry_autosave_video.set_sensitive(False)
331
332 def cb_filechooser_video(self, widget):
333 prefs.video_dest = self.filechooser_video.get_current_folder()
334 logger.debug("Video folder set to: {0}".format(prefs.video_dest))
335
336 def cb_entry_autosave_video(self, widget):
337 prefs.autosave_video_file = widget.get_text()
338 logger.debug("Video autosave file set to: {0}".format(prefs.autosave_video_file))
339
340 #
341 # Screenshot callbacks
342 #
343
344 def cb_switch_shutter_sound(self, widget, user_data):
345 prefs.shutter_sound = widget.get_active()
346 logger.debug("Shutter sound: {0}.".format(prefs.shutter_sound))
347
348 if prefs.shutter_sound:
349 self.combobox_shutter_type.set_sensitive(True)
350 else:
351 self.combobox_shutter_type.set_sensitive(False)
352
353 def cb_shutter_type(self, widget):
354 prefs.shutter_type = self.combobox_shutter_type.get_active()
355 logger.debug("Shutter type set to: {0} - {1}".format(prefs.shutter_type, prefs.shutter_sound_file))
356
357 def cb_switch_autosave_picture(self, widget, user_data):
358 prefs.autosave_picture = widget.get_active()
359 logger.debug("Autosave for Picture: {0}.".format(prefs.autosave_picture))
360
361 if prefs.autosave_picture:
362 self.filechooser_picture.set_sensitive(True)
363 self.entry_autosave_picture.set_sensitive(True)
364 else:
365 self.filechooser_picture.set_sensitive(False)
366 self.entry_autosave_picture.set_sensitive(False)
367
368 def cb_filechooser_picture(self, widget):
369 prefs.picture_dest = self.filechooser_picture.get_current_folder()
370 logger.debug("Picture folder set to: {0}".format(prefs.picture_dest))
371
372 def cb_entry_autosave_picture(self, widget):
373 prefs.autosave_picture_file = widget.get_text()
374 logger.debug("Picture autosave file set to: {0}".format(prefs.autosave_picture_file))
375
0376
=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/save_dialog.py'
--- build/lib.linux-x86_64-2.7/kazam/frontend/save_dialog.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/frontend/save_dialog.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,62 @@
1# -*- coding: utf-8 -*-
2#
3# save_dialog.py
4#
5# Copyright 2012 David Klasinc <bigwhale@lubica.net>
6# Copyright 2010 Andrew <andrew@karmic-desktop>
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21# MA 02110-1301, USA.
22
23import os
24import logging
25logger = logging.getLogger("Save Dialog")
26
27from gi.repository import Gtk
28from gettext import gettext as _
29from datetime import datetime
30from kazam.backend.prefs import *
31from kazam.backend.constants import *
32
33def SaveDialog(title, old_path, codec, main_mode=MODE_SCREENCAST):
34 logger.debug("Save dialog called.")
35 dialog = Gtk.FileChooserDialog(title, None,
36 Gtk.FileChooserAction.SAVE,
37 (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
38 _("Save"), Gtk.ResponseType.OK))
39
40
41 dt = datetime.today().strftime("%Y-%m-%d %H:%M:%S")
42 if main_mode == MODE_SCREENCAST:
43 dialog.set_current_name("{0} {1}{2}".format(_("Screencast"), dt, CODEC_LIST[codec][3]))
44 elif main_mode == MODE_SCREENSHOT:
45 dialog.set_current_name("{0} {1}.png".format(_("Screenshot"), dt))
46
47 dialog.set_do_overwrite_confirmation(True)
48
49 if old_path and os.path.isdir(old_path):
50 dialog.set_current_folder(old_path)
51 else:
52 if main_mode == MODE_SCREENCAST:
53 dialog.set_current_folder(prefs.video_dest)
54 elif main_mode == MODE_SCREENSHOT:
55 dialog.set_current_folder(prefs.picture_dest)
56
57
58 dialog.show_all()
59 result = dialog.run()
60 old_path = dialog.get_current_folder()
61 return dialog, result, old_path
62
063
=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/widgets.py'
--- build/lib.linux-x86_64-2.7/kazam/frontend/widgets.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/frontend/widgets.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,60 @@
1# -*- coding: utf-8 -*-
2#
3# widgets.py
4#
5# Copyright 2012 David Klasinc <bigwhale@lubica.net>
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 3 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20# MA 02110-1301, USA.
21
22from gi.repository import Gtk, Gdk, Pango, GObject, GdkPixbuf
23
24class _Tile(object):
25 def __init__(self):
26 self.set_focus_on_click(False)
27 self.set_relief(Gtk.ReliefStyle.NONE)
28 self.box = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
29 self.box.set_size_request(62, -1)
30 self.add(self.box)
31
32 def create_default(self, label, icon):
33 if icon is not None:
34 if isinstance(icon, Gtk.Image):
35 self.image = icon
36 else:
37 self.image = Gtk.Image()
38 self.box.pack_start(self.image, True, True, 0)
39
40 self.label = Gtk.Label.new(label)
41 self.box.pack_start(self.label, True, True, 0)
42
43class TileToggleButton(Gtk.RadioButton, _Tile):
44 def __init__(self):
45 Gtk.RadioButton.__init__(self)
46 self.set_mode(False)
47 _Tile.__init__(self)
48
49class ModeButton(TileToggleButton):
50 def __init__(self, label, icon):
51 TileToggleButton.__init__(self)
52 html = "<small>%s</small>" % label
53 self.create_default(html, icon)
54 self.label.set_use_markup(True)
55 self.label.set_justify(Gtk.Justification.CENTER)
56
57 #def do_draw(self, cr):
58 #for child in self:
59 # self.propagate_draw(child, cr)
60
061
=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/window_area.py'
--- build/lib.linux-x86_64-2.7/kazam/frontend/window_area.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/frontend/window_area.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,202 @@
1# -*- coding: utf-8 -*-
2#
3# window_select.py
4#
5# Copyright 2012 David Klasinc <bigwhale@lubica.net>
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 3 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20# MA 02110-1301, USA.
21
22import time
23import cairo
24import logging
25logger = logging.getLogger("Window Select")
26
27from gettext import gettext as _
28
29from gi.repository import Gtk, GObject, Gdk, Wnck, GdkX11
30
31from kazam.backend.constants import *
32class AreaWindow(GObject.GObject):
33
34 __gsignals__ = {
35 "area-selected" : (GObject.SIGNAL_RUN_LAST,
36 None,
37 (),
38 ),
39 "area-canceled" : (GObject.SIGNAL_RUN_LAST,
40 None,
41 (),
42 ),
43 }
44
45 def __init__(self):
46 super(AreaWindow, self).__init__()
47 logger.debug("Initializing select window.")
48
49 self.startx = 0
50 self.starty = 0
51 self.endx = 0
52 self.endy = 0
53 self.height = 0
54 self.width = 0
55
56 self.window = Gtk.Window()
57 self.box = Gtk.Box()
58 self.drawing = Gtk.DrawingArea()
59 self.box.pack_start(self.drawing, True, True, 0)
60 self.drawing.set_size_request(500, 500)
61 self.window.add(self.box)
62
63 self.window.connect("delete-event", Gtk.main_quit)
64 self.window.connect("key-press-event", self.cb_keypress_event)
65
66 self.drawing.connect("draw", self.cb_draw)
67 self.drawing.connect("motion-notify-event", self.cb_draw_motion_notify_event)
68 self.drawing.connect("button-press-event", self.cb_draw_button_press_event)
69 self.drawing.connect("leave-notify-event", self.cb_leave_notify_event)
70 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)
71
72 self.window.set_border_width(0)
73 self.window.set_app_paintable(True)
74 self.window.set_has_resize_grip(False)
75 self.window.set_resizable(True)
76 self.window.set_decorated(False)
77 self.window.set_property("skip-taskbar-hint", True)
78 self.window.set_keep_above(True)
79 self.screen = self.window.get_screen()
80 self.visual = self.screen.get_rgba_visual()
81
82 self.disp = GdkX11.X11Display.get_default()
83 self.dm = Gdk.Display.get_device_manager(self.disp)
84 self.pntr_device = self.dm.get_client_pointer()
85
86 if self.visual is not None and self.screen.is_composited():
87 logger.debug("Compositing window manager detected.")
88 self.window.set_visual(self.visual)
89 self.compositing = True
90 else:
91 self.compositing = False
92
93 (scr, x, y) = self.pntr_device.get_position()
94 cur = scr.get_monitor_at_point(x, y)
95 self.window.move(HW.screens[cur]['x'],
96 HW.screens[cur]['y'])
97 self.window.fullscreen()
98
99 crosshair_cursor = Gdk.Cursor(Gdk.CursorType.CROSSHAIR)
100 self.last_cursor = Gdk.Cursor(Gdk.CursorType.LEFT_PTR)
101 self.gdk_win = self.window.get_root_window()
102 self.gdk_win.set_cursor(crosshair_cursor)
103
104 def cb_draw_motion_notify_event(self, widget, event):
105 (state, x, y, mask) = event.window.get_device_position(self.pntr_device)
106 if mask & Gdk.ModifierType.BUTTON1_MASK:
107 self.endx = int(event.x)
108 self.endy = int(event.y)
109 self.width = self.endx - self.startx
110 self.height = self.endy - self.starty
111 widget.queue_draw()
112 return True
113
114 def cb_draw_button_press_event(self, widget, event):
115 self.startx = int(event.x)
116 self.starty = int(event.y)
117 self.endx = 0
118 self.endy = 0
119 self.width = 0
120 self.height = 0
121
122 def cb_leave_notify_event(self, widget, event):
123 (scr, x, y) = self.pntr_device.get_position()
124 cur = scr.get_monitor_at_point(x, y)
125 self.window.unfullscreen()
126 self.window.move(HW.screens[cur]['x'],
127 HW.screens[cur]['y'])
128 self.window.fullscreen()
129 logger.debug("Move to X: {0} Y: {1}".format(HW.screens[cur]['x'], HW.screens[cur]['y']))
130 return True
131
132 def cb_keypress_event(self, widget, event):
133 (op, keycode) = event.get_keycode()
134 self.gdk_win.set_cursor(self.last_cursor)
135 if keycode == 36 or keycode == 104: # Enter
136 self.window.hide()
137 self.width = abs(self.width)
138 self.height = abs(self.height)
139 self.emit("area-selected")
140 elif keycode == 9: # ESC
141 self.window.hide()
142 self.emit("area-canceled")
143
144 def cb_draw(self, widget, cr):
145 (w, h) = self.window.get_size()
146
147 if self.compositing:
148 cr.set_source_rgba(0.0, 0.0, 0.0, 0.45)
149 else:
150 cr.set_source_rgb(0.5, 0.5, 0.5)
151
152 cr.set_operator(cairo.OPERATOR_SOURCE)
153 cr.paint()
154
155 cr.set_operator(cairo.OPERATOR_SOURCE)
156
157 # Draw the selection area
158 cr.move_to(self.startx, self.starty)
159 cr.set_source_rgb(1.0, 0.0, 0.0)
160 cr.rectangle(self.startx, self.starty, self.width, self.height)
161 cr.stroke()
162
163 if self.compositing:
164 cr.set_source_rgba(0.0, 0.0, 0.0, 0.0)
165 else:
166 cr.set_source_rgb(0.0, 0.0, 0.0)
167
168 cr.rectangle(self.startx, self.starty, self.width, self.height)
169 cr.fill()
170
171 cr.set_operator(cairo.OPERATOR_OVER)
172
173 self._outline_text(cr, w, h, 30, _("Select an area by clicking and dragging."))
174 self._outline_text(cr, w, h + 50, 26, _("Press ENTER to confirm or ESC to cancel"))
175
176 self._outline_text(cr, w, h + 100, 20, "({0} x {1})".format(abs(self.height), abs(self.height)))
177 cr.set_operator(cairo.OPERATOR_SOURCE)
178
179 def _outline_text(self, cr, w, h, size, text):
180 cr.set_font_size(size)
181 try:
182 cr.select_font_face("Ubuntu", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
183 except:
184 pass
185 te = cr.text_extents(text)
186 cr.set_line_width(2.0)
187 cx = w/2 - te[2]/2
188 cy = h/2 - te[3]/2
189 if self.compositing:
190 cr.set_source_rgba(0.4, 0.4, 0.4, 1.0)
191 else:
192 cr.set_source_rgb(0.4, 0.4, 0.4)
193
194 cr.move_to(cx, cy)
195 cr.text_path(text)
196 cr.stroke()
197 if self.compositing:
198 cr.set_source_rgba(1.0, 1.0, 1.0, 1.0)
199 else:
200 cr.set_source_rgb(1.0, 1.0, 1.0)
201 cr.move_to(cx, cy)
202 cr.show_text(text)
0203
=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/window_countdown.py'
--- build/lib.linux-x86_64-2.7/kazam/frontend/window_countdown.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/frontend/window_countdown.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,140 @@
1# -*- coding: utf-8 -*-
2#
3# window_countdown.py
4#
5# Copyright 2012 David Klasinc <bigwhale@lubica.net>
6# Copyright 2010 Andrew <andrew@karmic-desktop>
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21# MA 02110-1301, USA.
22
23import cairo
24
25from gettext import gettext as _
26from gi.repository import Gtk, GObject
27from kazam.backend.constants import *
28
29class CountdownWindow(GObject.GObject):
30
31 __gsignals__ = {
32 "counter-finished" : (GObject.SIGNAL_RUN_LAST,
33 None,
34 (),
35 ),
36 }
37
38 def __init__(self, indicator, number = 5, show_window = True):
39 super(CountdownWindow, self).__init__()
40 self.indicator = indicator
41 self.number = number
42 self.canceled = False
43 self.show_window = show_window
44
45 self.window = Gtk.Window()
46 self.window.connect("delete-event", Gtk.main_quit)
47 self.window.connect("draw", self.cb_draw)
48 self.width = 600
49 self.height = 240
50 self.window.set_default_geometry(self.height, self.width)
51 self.window.set_default_size(self.width, self.height)
52 self.window.set_position(Gtk.WindowPosition.CENTER)
53 self.window.set_app_paintable(True)
54 self.window.set_has_resize_grip(False)
55 self.window.set_resizable(True)
56
57 self.window.set_decorated(False)
58 self.window.set_property("skip-taskbar-hint", True)
59 self.window.set_keep_above(True)
60 self.screen = self.window.get_screen()
61 self.visual = self.screen.get_rgba_visual()
62
63 if self.visual is not None and self.screen.is_composited():
64 self.window.set_visual(self.visual)
65
66
67 def run(self, counter):
68 if counter > 0:
69 self.number = counter + 1
70 if self.show_window:
71 self.window.show_all()
72 else:
73 self.number = 0
74 self.countdown()
75
76 def countdown(self):
77 if not self.canceled:
78 if self.number < 5:
79 self.indicator.blink_set_state(BLINK_FAST)
80 if self.number > 1:
81 self.window.queue_draw()
82 GObject.timeout_add(1000, self.countdown)
83 self.number -= 1
84 else:
85 self.window.destroy()
86 GObject.timeout_add(400, self.counter_finished)
87
88 def cancel_countdown(self):
89 self.indicator.blink_set_state(BLINK_STOP)
90 self.canceled = True
91 self.window.destroy()
92 self.number = 0
93
94 def counter_finished(self):
95 self.emit("counter-finished")
96 return False
97
98 def cb_draw(self, widget, cr):
99 w = self.width
100 h = self.height
101 cr.set_source_rgba(1, 1, 1, 0)
102 cr.set_operator(cairo.OPERATOR_SOURCE)
103 cr.paint()
104 self._draw_rounded(cr, 1, 1, w - 10, h - 10, 20)
105 cr.set_line_width(1.0)
106 cr.set_source_rgba(0.0, 0.0, 0.0, 0.4)
107 cr.stroke_preserve()
108 cr.fill()
109 cr.set_operator(cairo.OPERATOR_OVER)
110 self._outline_text(cr, w, h, 36, _("Recording will start in ..."))
111 self._outline_text(cr, w, h + 70, 36, _("{0}".format(self.number)))
112
113 def _draw_rounded(self, cr, x, y, w, h, r = 20):
114 cr.move_to(x + r, y)
115 cr.line_to(x + w - r, y)
116 cr.curve_to(x + w,y,x+w,y,x+w,y+r)
117 cr.line_to(x + w,y+h-r)
118 cr.curve_to(x + w, y + h, x + w, y + h, x + w - r, y + h)
119 cr.line_to(x + r, y + h)
120 cr.curve_to(x, y + h, x, y + h, x, y + h - r)
121 cr.line_to(x, y + r)
122 cr.curve_to(x, y, x, y, x + r, y)
123
124 def _outline_text(self, cr, w, h, size, text):
125 cr.set_font_size(size)
126 try:
127 cr.select_font_face("Ubuntu", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
128 except:
129 pass
130 te = cr.text_extents(text)
131 cr.set_source_rgba(0.4, 0.4, 0.4, 1.0)
132 cr.set_line_width(2.0)
133 cx = w/2 - te[2]/2
134 cy = h/2 - te[3]/2
135 cr.move_to(cx, cy)
136 cr.text_path(text)
137 cr.stroke()
138 cr.set_source_rgba(1.0, 1.0, 1.0, 1.0)
139 cr.move_to(cx, cy)
140 cr.show_text(text)
0141
=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/window_region.py'
--- build/lib.linux-x86_64-2.7/kazam/frontend/window_region.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/frontend/window_region.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,200 @@
1# -*- coding: utf-8 -*-
2#
3# window_region.py
4#
5# Copyright 2012 David Klasinc <bigwhale@lubica.net>
6# Copyright 2010 Andrew <andrew@karmic-desktop>
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21# MA 02110-1301, USA.
22
23import cairo
24import logging
25logger = logging.getLogger("Window Region")
26
27from gettext import gettext as _
28
29from gi.repository import Gtk, GObject, Gdk
30
31class RegionWindow(GObject.GObject):
32
33 __gsignals__ = {
34 "region-selected" : (GObject.SIGNAL_RUN_LAST,
35 None,
36 (),
37 ),
38 "region-canceled" : (GObject.SIGNAL_RUN_LAST,
39 None,
40 (),
41 ),
42 }
43
44 def __init__(self, region = None):
45 super(RegionWindow, self).__init__()
46 logger.debug("Initializing region window.")
47 self.window = Gtk.Window()
48 self.window.connect("configure-event", self.cb_configure_event)
49 self.window.connect("delete-event", Gtk.main_quit)
50 self.window.connect("draw", self.cb_draw)
51 self.window.connect("key-press-event", self.cb_keypress_event)
52 self.window.connect("button-press-event", self.cb_button_press_event)
53
54 if region:
55 logger.debug("Old region defined at: X: {0}, Y: {1}, W: {2}, H: {3}".format(region[0],
56 region[1],
57 region[2],
58 region[3]))
59 self.startx = region[0]
60 self.starty = region[1]
61 self.endx = region[2]
62 self.endy = region[3]
63 self.window.move(self.startx, self.starty)
64 else:
65 self.startx = 0
66 self.starty = 0
67 self.endx = 640
68 self.endy = 480
69 self.window.set_position(Gtk.WindowPosition.CENTER)
70
71 self.width = self.endx - self.startx
72 self.height = self.endy - self.starty
73 self.window.set_default_geometry(self.width, self.height)
74
75 self.window.set_border_width(30)
76 self.window.set_app_paintable(True)
77 self.window.set_has_resize_grip(False)
78 self.window.set_resizable(True)
79 self.window.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
80 self.window.set_decorated(False)
81 self.window.set_property("skip-taskbar-hint", True)
82 self.window.set_keep_above(True)
83 self.screen = self.window.get_screen()
84 self.visual = self.screen.get_rgba_visual()
85 self.recording = False
86
87 self.window.set_visual(self.visual)
88 if self.visual is not None and self.screen.is_composited():
89 self.window.show_all()
90
91 def cb_button_press_event(self, widget, event):
92 (op, button) = event.get_button()
93 if button == 1:
94 if int(event.x) in range(0, 15) and int(event.y) in range(0,15):
95 self.window.begin_resize_drag(Gdk.WindowEdge.NORTH_WEST, button,
96 event.x_root, event.y_root, event.time)
97
98 elif int(event.x) in range(self.width-15, self.width) and int(event.y) in range(0,15):
99 self.window.begin_resize_drag(Gdk.WindowEdge.NORTH_EAST, button,
100 event.x_root, event.y_root, event.time)
101
102 elif int(event.x) in range(self.width-15, self.width) and int(event.y) in range(self.height-15,self.height):
103 self.window.begin_resize_drag(Gdk.WindowEdge.SOUTH_EAST, button,
104 event.x_root, event.y_root, event.time)
105
106 elif int(event.x) in range(0, 15) and int(event.y) in range(self.height-15, self.height):
107 self.window.begin_resize_drag(Gdk.WindowEdge.SOUTH_WEST, button,
108 event.x_root, event.y_root, event.time)
109
110 else:
111 self.window.begin_move_drag(button, event.x_root, event.y_root, event.time)
112
113 def cb_keypress_event(self, widget, event):
114 (op, keycode) = event.get_keycode()
115 if keycode == 36 or keycode == 104: # Enter
116 self.window.set_default_geometry(self.width, self.height)
117 (self.startx, self.starty) = self.window.get_position()
118 self.endx = self.startx + self.width - 1
119 self.endy = self.starty + self.height - 1
120 self.recording = True
121 self.window.input_shape_combine_region(None)
122 #
123 # When support for masked input is back, remove the hide() call.
124 #
125 self.window.hide()
126 # self.window.queue_draw()
127 self.emit("region-selected")
128 elif keycode == 9: # ESC
129 self.window.hide()
130 self.emit("region-canceled")
131
132
133 def cb_configure_event(self, widget, event):
134 self.width = event.width
135 self.height = event.height
136
137 def cb_draw(self, widget, cr):
138 w = self.width
139 h = self.height
140 #
141 # Drawing a red rectangle around selected area would be extremely nice
142 # however, cairo.Region is missing from GIR and from pycairo and
143 # it is needed for input_shape_combine_region().
144 # See: https://bugs.freedesktop.org/show_bug.cgi?id=44336
145 #
146 #if self.recording:
147 # cr.set_source_rgba(0.0, 0.0, 0.0, 0.0)
148 # cr.set_operator(cairo.OPERATOR_SOURCE)
149 # cr.paint()
150 # surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w , h)
151 # surface_ctx = cairo.Context(surface)
152 # surface_ctx.set_source_rgba(1.0, 1.0, 1.0, 0.0)
153 # surface_ctx.set_operator(cairo.OPERATOR_SOURCE)
154 # surface_ctx.paint()
155 # reg = Gdk.cairo_region_create_from_surface(surface)
156 # widget.input_shape_combine_region(reg)
157 # cr.move_to(0, 0)
158 # cr.set_source_rgb(1.0, 0.0, 0.0)
159 # cr.set_line_width(2.0)
160 # cr.rectangle(0, 0, w, h)
161 # cr.stroke()
162 # cr.set_operator(cairo.OPERATOR_OVER)
163 #else:
164 cr.set_source_rgba(0.0, 0.0, 0.0, 0.4)
165 cr.set_operator(cairo.OPERATOR_SOURCE)
166 cr.paint()
167 cr.set_source_rgba(1.0, 1.0, 1.0, 1.0)
168 cr.set_line_width(1.0)
169 cr.move_to(0, 0)
170 cr.rectangle(0, 0, 15, 15)
171 cr.rectangle(w-15, 0, w, 15)
172 cr.rectangle(0, h-15, 15, h)
173 cr.rectangle(w-15, h-15, w, h)
174 cr.fill()
175 cr.set_source_rgb(0.0, 0.0, 0.0)
176 cr.rectangle(0, 0, w, h)
177 cr.stroke()
178 cr.set_operator(cairo.OPERATOR_OVER)
179 self._outline_text(cr, w, h, 24, _("Select region by resizing the window"))
180 self._outline_text(cr, w, h + 50, 24, _("Press ENTER to confirm or ESC to cancel."))
181 self._outline_text(cr, w, h + 80, 12, "({0} x {1})".format(w, h))
182
183
184 def _outline_text(self, cr, w, h, size, text):
185 cr.set_font_size(size)
186 try:
187 cr.select_font_face("Ubuntu", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
188 except:
189 pass
190 te = cr.text_extents(text)
191 cr.set_line_width(2.0)
192 cx = w/2 - te[2]/2
193 cy = h/2 - te[3]/2
194 cr.set_source_rgba(0.4, 0.4, 0.4, 1.0)
195 cr.move_to(cx, cy)
196 cr.text_path(text)
197 cr.stroke()
198 cr.set_source_rgba(1.0, 1.0, 1.0, 1.0)
199 cr.move_to(cx, cy)
200 cr.show_text(text)
0201
=== added file 'build/lib.linux-x86_64-2.7/kazam/frontend/window_select.py'
--- build/lib.linux-x86_64-2.7/kazam/frontend/window_select.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/frontend/window_select.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,181 @@
1# -*- coding: utf-8 -*-
2#
3# window_select.py
4#
5# Copyright 2012 David Klasinc <bigwhale@lubica.net>
6# Copyright 2010 Andrew <andrew@karmic-desktop>
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21# MA 02110-1301, USA.
22
23import time
24import cairo
25import logging
26logger = logging.getLogger("Window Select")
27
28from gettext import gettext as _
29
30from gi.repository import Gtk, GObject, Gdk, Wnck, GdkX11
31
32from kazam.backend.constants import *
33
34class SelectWindow(GObject.GObject):
35
36 __gsignals__ = {
37 "window-selected" : (GObject.SIGNAL_RUN_LAST,
38 None,
39 (),
40 ),
41 "window-canceled" : (GObject.SIGNAL_RUN_LAST,
42 None,
43 (),
44 ),
45 }
46
47 def __init__(self):
48 super(SelectWindow, self).__init__()
49 logger.debug("Initializing select window.")
50
51 self.xid = None
52
53 self.window = Gtk.Window()
54 self.window.connect("delete-event", Gtk.main_quit)
55 self.window.connect("draw", self.cb_draw)
56 self.window.connect("key-press-event", self.cb_keypress_event)
57 self.window.connect("button-press-event", self.cb_button_press_event)
58 self.window.connect("leave-notify-event", self.cb_leave_notify_event)
59
60 self.window.set_border_width(30)
61 self.window.set_app_paintable(True)
62 self.window.set_has_resize_grip(False)
63 self.window.set_resizable(True)
64 self.window.add_events(Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.LEAVE_NOTIFY_MASK)
65 self.window.set_decorated(False)
66 self.window.set_property("skip-taskbar-hint", True)
67 self.window.set_keep_above(True)
68 self.screen = self.window.get_screen()
69 self.visual = self.screen.get_rgba_visual()
70 self.recording = False
71
72 self.disp = GdkX11.X11Display.get_default()
73 self.dm = Gdk.Display.get_device_manager(self.disp)
74 self.pntr_device = self.dm.get_client_pointer()
75
76 if self.visual is not None and self.screen.is_composited():
77 logger.debug("Compositing window manager detected.")
78 self.window.set_visual(self.visual)
79 self.compositing = True
80 else:
81 self.compositing = False
82
83 (scr, x, y) = self.pntr_device.get_position()
84 cur = scr.get_monitor_at_point(x, y)
85 self.window.unfullscreen()
86 self.window.move(HW.screens[cur]['x'],
87 HW.screens[cur]['y'])
88 self.window.fullscreen()
89 crosshair_cursor = Gdk.Cursor(Gdk.CursorType.CROSSHAIR)
90 self.last_cursor = Gdk.Cursor(Gdk.CursorType.LEFT_PTR)
91 self.gdk_win = self.window.get_root_window()
92 self.gdk_win.set_cursor(crosshair_cursor)
93
94 def cb_leave_notify_event(self, widget, event):
95 (scr, x, y) = self.pntr_device.get_position()
96 cur = scr.get_monitor_at_point(x, y)
97 self.window.unfullscreen()
98 logger.debug("Move to X: {0} Y: {1}".format(HW.screens[cur]['x'], HW.screens[cur]['y']))
99 self.window.move(HW.screens[cur]['x'],
100 HW.screens[cur]['y'])
101 self.window.fullscreen()
102
103 def cb_button_press_event(self, widget, event):
104 self.geometry = None
105 self.win_name = None
106 self.xid = None
107 # TODO: Error handling
108 (op, button) = event.get_button()
109 if button == 1:
110 screen = Wnck.Screen.get_default()
111 screen.force_update()
112 workspace = screen.get_active_workspace()
113 wins = screen.get_windows_stacked()
114
115 for win in reversed(wins):
116 if win.is_visible_on_workspace(workspace) and win.is_in_viewport(workspace):
117 self.win_name = win.get_name()
118 if not (self.win_name.lower().startswith("kazam") or self.win_name.lower().startswith("desktop")):
119 geometry = win.get_client_window_geometry()
120 self.geometry = geometry
121 if geometry[0] <= event.x_root <= (geometry[0] + geometry[2]) and geometry[1] <= event.y_root <= (geometry[1] + geometry[3]):
122 self.xid = win.get_xid()
123 break
124 self.gdk_win.set_cursor(self.last_cursor)
125 self.window.hide()
126 if self.xid:
127 self.emit("window-selected")
128 else:
129 self.emit("window-canceled")
130
131 def cb_keypress_event(self, widget, event):
132 (op, keycode) = event.get_keycode()
133 if keycode == 36 or keycode == 104 or keycode == 9: # Enter or Escape
134 self.gdk_win.set_cursor(self.last_cursor)
135 self.window.hide()
136 self.emit("window-canceled")
137
138 def cb_draw(self, widget, cr):
139 (w, h) = self.window.get_size()
140
141
142 if self.compositing:
143 cr.set_source_rgba(0.0, 0.0, 0.0, 0.45)
144 else:
145 cr.set_source_rgb(0.5, 0.5, 0.5)
146
147 cr.set_operator(cairo.OPERATOR_SOURCE)
148 cr.paint()
149 if self.compositing:
150 cr.set_source_rgba(1.0, 1.0, 1.0, 1.0)
151 else:
152 cr.set_source_rgba(1.0, 1.0, 1.0)
153
154 cr.set_operator(cairo.OPERATOR_OVER)
155 self._outline_text(cr, w, h, 30, _("Select a window by clicking on it."))
156 self._outline_text(cr, w, h + 50, 26, _("Press ENTER or ESC to cancel"))
157
158 def _outline_text(self, cr, w, h, size, text):
159 cr.set_font_size(size)
160 try:
161 cr.select_font_face("Ubuntu", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
162 except:
163 pass
164 te = cr.text_extents(text)
165 cr.set_line_width(2.0)
166 cx = w/2 - te[2]/2
167 cy = h/2 - te[3]/2
168 if self.compositing:
169 cr.set_source_rgba(0.4, 0.4, 0.4, 1.0)
170 else:
171 cr.set_source_rgb(0.4, 0.4, 0.4)
172
173 cr.move_to(cx, cy)
174 cr.text_path(text)
175 cr.stroke()
176 if self.compositing:
177 cr.set_source_rgba(1.0, 1.0, 1.0, 1.0)
178 else:
179 cr.set_source_rgb(1.0, 1.0, 1.0)
180 cr.move_to(cx, cy)
181 cr.show_text(text)
0182
=== added file 'build/lib.linux-x86_64-2.7/kazam/instant.py'
--- build/lib.linux-x86_64-2.7/kazam/instant.py 1970-01-01 00:00:00 +0000
+++ build/lib.linux-x86_64-2.7/kazam/instant.py 2012-11-15 10:17:01 +0000
@@ -0,0 +1,142 @@
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4# instant.py
5#
6# Copyright 2012 David Klasinc <bigwhale@lubica.net>
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 3 of the License, or
11# (at your option) any later version.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License
19# along with this program; if not, write to the Free Software
20# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21# MA 02110-1301, USA.
22
23import sys
24import logging
25from gettext import gettext as _
26from gi.repository import Gtk, GObject
27
28from kazam.utils import *
29from kazam.backend.prefs import *
30from kazam.backend.constants import *
31from kazam.backend.grabber import Grabber
32
33logger = logging.getLogger("Instant")
34
35class InstantApp(GObject.GObject):
36
37 def __init__(self, datadir, dist, debug, mode, preferences=False):
38 GObject.GObject.__init__(self)
39 logger.debug("Setting variables.{0}".format(datadir))
40
41 self.mode = mode
42 self.take = 0
43
44 prefs.datadir = datadir
45 prefs.debug = debug
46 prefs.dist = dist
47 prefs.get_sound_files()
48
49 if preferences:
50 logger.debug("Preferences requested.")
51 from kazam.frontend.preferences import Preferences
52 from kazam.pulseaudio.pulseaudio import pulseaudio_q
53 prefs.pa_q = pulseaudio_q()
54 prefs.pa_q.start()
55 prefs.get_audio_sources()
56
57 self.preferences_window = Preferences()
58 self.preferences_window.connect("prefs-quit", self.cb_prefs_quit)
59 self.preferences_window.open()
60
61 else:
62 self.old_path = None
63
64 if HW.combined_screen:
65 self.video_source = HW.combined_screen
66 else:
67 screen = HW.get_current_screen()
68 self.video_source = HW.screens[screen]
69
70 self.grabber = Grabber()
71 self.grabber.connect("flush-done", self.cb_flush_done)
72 self.grabber.connect("save-done", self.cb_save_done)
73
74 if self.mode == MODE_AREA:
75 logger.debug("Area ON.")
76 from kazam.frontend.window_area import AreaWindow
77 self.area_window = AreaWindow()
78 self.area_window.connect("area-selected", self.cb_area_selected)
79 self.area_window.connect("area-canceled", self.cb_area_canceled)
80 self.area_window.window.show_all()
81 elif self.mode == MODE_ALL:
82 self.grabber.setup_sources(self.video_source, None, None)
83 logger.debug("Grabbing screen")
84 self.grabber.grab()
85 elif self.mode == MODE_ACTIVE:
86 self.grabber.setup_sources(self.video_source, None, None, active=True)
87 logger.debug("Grabbing screen")
88 self.grabber.grab()
89 elif self.mode == MODE_GOD:
90 logger.debug("Grabbing in god mode.")
91 self.grabber.setup_sources(self.video_source, None, None, god=True)
92 self.grabber.grab()
93 self.grabber.setup_sources(self.video_source, None, None, active=True, god=True)
94 self.grabber.grab()
95 else:
96 sys.exit(0)
97
98 def cb_area_selected(self, widget):
99 logger.debug("Area selected: SX: {0}, SY: {1}, EX: {2}, EY: {3}".format(
100 self.area_window.startx,
101 self.area_window.starty,
102 self.area_window.endx,
103 self.area_window.endy))
104 prefs.area = (self.area_window.startx,
105 self.area_window.starty,
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches