=== mRy is now known as Guest92858 === mRy is now known as Guest78285 === mRy is now known as Guest18185 === mRy is now known as Guest74526 === mRy is now known as Guest28633 === rmrf|NA is now known as rmrf === _LibertyZero is now known as LibertyZero === mRy is now known as Guest90119 === Atlan is now known as bulldog98_konv === mRy is now known as Guest83516 === mRy is now known as Guest69628 === jhernandez_afk is now known as jhernandez === mRy is now known as Guest7849 === mRy is now known as Guest56374 === mRy is now known as Guest91948 === yofel_ is now known as yofel === bregma_ is now known as bregma === mRy is now known as Guest38306 === boulabiar is now known as boulabiar| === CodeBlock is now known as CodeBlock_ [14:52] hi [15:10] time === teckfatt_ is now known as teckfatt [16:51] Ubuntu App Developer Week - Day 2 starting in ~10 minutes! :-) [16:54] ClassBot: good day to you! [16:55] hi pitti [16:55] * cdbs was waiting for this session for a really really long time [17:00] Welcome everyone to a new and exciting day of the Ubuntu App Developer Week! [17:00] Lots of interesting sessions lined up for today [17:01] Bringing you the best content from the best speakers === ChanServ changed the topic of #ubuntu-classroom to: Welcome to the Ubuntu Classroom - https://wiki.ubuntu.com/Classroom || Support in #ubuntu || Upcoming Schedule: http://is.gd/8rtIi || Questions in #ubuntu-classroom-chat || Event: Ubuntu App Developer Week - Current Session: PyGTK is dead, long live PyGI! Using gobject-introspection in Python - Instructors: pitti [17:01] Check out http://ubuntu-news.org/2011/04/12/off-to-a-great-start-ubuntu-app-developer-week-day-1/ if you missed any of the sessions yesterday [17:01] Logs for this session will be available at http://irclogs.ubuntu.com/2011/04/12/%23ubuntu-classroom.html following the conclusion of the session. [17:02] Next up is Martin Pitt, one of the persons who know Ubuntu and its technologies inside out [17:02] He's going to be talking about porting your old PyGTK applications to the new PyGI framework, [17:02] so that they can make use of all the awesomeness of introspection. [17:02] Let's hand him the mike... [17:03] * pitti clears throat [17:03] Hello everyone! I am Martin Pitt from the Canonical Ubuntu Desktop Team. [17:03] Python is a very important and popular language in Ubuntu, we have a lot of applications written in Python for GTK and Qt/KDE. Most prominent examples are our installer Ubiquity, Software Center, our driver installer "Jockey", and our bug/crash reporting system "Apport" (shameless plug!). [17:03] By way of Quickly we also encourage application developers to use Python and GTK, as these allow you to write GUI applications both conveniently, fast, and still rather robust. [17:03] So far the package of choice for that has been PyGTK, a manually maintained Python binding for GTK, ATK, Pango, Glade, and a few other things. However, a few months ago, with the advent of GTK3, PyGTK was declared dead, so it's time to bring the banner of the great new world of its successor -- gobject-introspection -- to the world! [17:04] Tomeu Vizoso already explained what gobject-introspection (commonly abbreviated "GI") is, why we need it, and how library developers can use it to provide a machine readable and complete API/ABI description. So I'll just do a very brief summary here. [17:04] I'll concentrate on the app developer side, i. e. how to use GI typelibs in Python. [17:04] Porting existing PyGTK2 code is a topic that will keep many of us busy in the next months, so I'll explain the process and common pitfalls with that. [17:04] Finally I'll give some pointers to documentation, and will be available for some Q&A. [17:05] Everyone ready to dive in? Please let me know (here or in #-chat) when I become too fast. If I am being totally unclear, please yell and I'll handle that immediately. If you just have a followup question, let's handle these at the end. [17:05] == Quick recap: What is GI? == [17:05] So far a lot of energy was spent to write so-called "bindings", i. e. glue code which exposes an existing API such as GTK for a target language: PyGTK, libnotify-cil, or Vala's .vapi files. [17:05] This both leads to a combinatorial explosion (libraries times languages), as well as many bindings which don't exist at all, or being of low quality. In addition it is also an almost insurmountable barrier for introducing new languages, as they would need a lot of bindings before they become useful. [17:05] GI is a set of tools to generate a machine parseable and complete API/ABI description of a library, and a library (libgirepository) which can then be used by a language compiler/interpreter to automatically provide a binding for this library. [17:06] With GI you can then use every library which ships a typelib in every language which has GI support. [17:06] GI ABI/API descriptions come in two forms: [17:06] * An XML file, called the "GIR" (GI repository). These are mainly interesting for developers if they need to look up a particular detail of e. g. a method argument or an enum value. These are not actually used at runtime (as XML would be too costly to interpret every time), and thus they are shipped in the library's -dev package in Ubuntu and Debian. For example, libgtk2.0-dev ships [17:06] /usr/share/gir-1.0/Gdk-2.0.gir. [17:07] * A compiled binary form for efficient access, called the "typelib". These are the files that language bindings actually use. Ubuntu/Debian ship them in separate packages named gir--, for example, gir1.2-gtk-2.0 ships /usr/lib/girepository-1.0/Gdk-2.0.typelib. [17:07] (Yes, it's confusing that the gir1.2-* package does _not_ actually ship the .gir file; don't ask me why they were named "gir-", not "typelib-"). [17:07] == How does it work in Python? == [17:07] pygobject is the piece of software which provides Python access to GI (amongst other things, like providing the glib and GObject bindings). [17:08] The package name in Ubuntu/Debian is "python-gobject", and it should already be installed on all but the most manually trimmed down installations. [17:08] Initial GI support was added to pygobject in version 2.19.0 (August 2009), but the entire GI/pygobject/annotations stack really only stabilized in the last couple of months, so that in practice you will need at least pygobject 2.28 and the corresponding latest upstream releases of GTK and other libraries you want to use. [17:08] This means that you can only really use this with distros which are less than about three months old. For Debian/Ubuntu this means you'll need to use the current development versions, i. e. Ubuntu Natty (beta-1) or Debian experimental (most of this wasn't uploaded to unstable yet after the squeeze release). [17:09] pygobject provides a "gi.repository" module namespace which generates virtual Python modules from installed typelibs on the fly. [17:09] For example, if you install gir1.2-gtk-2.0 (it's already installed by default in Ubuntu Natty), you can do: [17:09] $ python -c 'from gi.repository import Gtk; print Gtk' [17:09] [17:10] and use it just like any other Python module. [17:10] I bet that this first example comes as an absolutely unexpected surprise to you: [17:10] $ python -c 'from gi.repository import Gtk; Gtk.MessageDialog(None, 0, Gtk.MessageType.INFO, Gtk.ButtonsType.CLOSE, "Hello World").run()' [17:10] * pitti gives everyone a minute to try this [17:11] Let's look at the corresponding C declaration: [17:11] GtkWidget* gtk_message_dialog_new (GtkWindow *parent, GtkDialogFlags flags, GtkMessageType type, GtkButtonsType buttons, const gchar *message_format, ...); [17:12] and the C call: [17:12] GtkMessageDialog* msg = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, "Hello World"); [17:12] msg.run() [17:12] So what do we see here? [17:12] (1) The C API by and large remains valid in Python (and other languages using the GI bindings), in particular the structure, order, and data types of arguments. [17:13] There are a few exceptions which are mostly due to the different way Python works, and in some cases to make it easier to write code in Python. I'll speak about details below. But this means that you can (and should) use the normal API documentation for the C API of the library. devhelp is your friend! [17:13] (2) As Python is a proper object oriented language, pygobject (and in fact the GI typelib already) expose a GObject API as proper classes, objects, methods, and attributes. [17:13] I. e. in Python you write [17:13] b = Gtk.Button(...) [17:13] b.set_label("foo") [17:13] instead of the C gobject syntax [17:13] GtkWidget* b = gtk_button_new(...); [17:13] gtk_button_set_label(b, "foo"); [17:14] The class names in the typelib (and thus in Python) are derived from the actual class names stated in the C library (like "GtkButton"), except that the common namespace prefix ("Gtk" here) is stripped, as it becomes the name of the module. [17:14] (3) Global constants would be a heavy namespace clutter in Python, and thus pygobject exposes them in a namespaced fashion as well. [17:14] I. e. if the MessageDialog constructor expects a constant of type "GtkMessageType", then by above namespace split this becomes a Python class "Gtk.MessageType" with the individual constants as attributes, e. g. Gtk.MessageType.INFO. [17:15] (This is actually something that pygtk gets quite wrong, the constant names are quite arbitrary there) [17:15] (4) Data types are converted in a rather obvious fashion. E. g. when the C API expects an int* array pointer, you can supply a normal Python array [0, 1, 2]. A Python string "foo" will match a gchar*, Pythons None matches NULL, etc. [17:16] So the GObject API actually translates quite naturally into a real OO language like Python, and after some time of getting used to above transformation rules, you should have no trouble translating the C API documentation into their Python equivalents. [17:16] When in doubt, you can always look for the precise names, data types, etc. in the .gir instead, which shows the API broken by class, method, enum, etc, with the exact names and namespaces as they are exposed in Python. [17:16] s I mentioned above, this is in no way restricted to GTK, GNOME, or UI. For example, if you handle any kind of hardware and hotplugging, you almost certainly want to query udev, which provides a nice glib integration (with signals) through the gudev library. [17:17] This example lists all block devices (i. e. hard drives, USB sticks, etc.): [17:17] (You need to install the gir1.2-gudev-1.0 package for this) [17:17] $ python [17:17] >>> from gi.repository import GUdev [17:17] >>> c = GUdev.Client() [17:18] >>> for dev in c.query_by_subsystem("block"): [17:18] ... print dev.get_device_file() [17:18] ... [17:18] /dev/sda [17:18] /dev/sda1 [17:18] /dev/sda2 [17:18] [...] [17:18] See http://www.kernel.org/pub/linux/utils/kernel/hotplug/gudev/GUdevClient.html#g-udev-client-query-by-subsystem for the corresponding C API. [17:19] GI is not even restricted to GObject, you can annotate any non-OO function based API with it. E. g. there is already a /usr/share/gir-1.0/xlib-2.0.gir (although it's horribly incomplete). These will behave as normal functions in Python (or other languages) as well. [17:20] == Other API differences == [17:20] I said above in (1) that the structure of method arguments is by and large the same in C and in GI/Python. There are some notable exceptions which you must be aware of. [17:20] === Constructors === [17:20] The biggest one is constructors. There is actually two ways of calling one: [17:20] * Use the real constructor implementation from the library. Unlike in normal Python you need to explicitly specify the constructor name: [17:21] Gtk.Button.new() [17:21] Gtk.Button.new_with_label("foo") [17:21] * Use the standard GObject constructor and pass in the initial property values as named arguments: [17:21] Gtk.Button(label="foo", use_underline=True) [17:22] The second is actually the recommended one, as it makes the meaning of the arguments more explicit, and also underlines the GObject best practice that a constructor should do nothing more than to initialize properties. But otherwise it's pretty much a matter of taste which one you use. [17:23] === Passing arrays === [17:23] Unlike C, higher level languages know how long an array is, while in the C API you need to specify that explicitly, either by terminating them with NULL or explicitly giving the length of the array in a separate argument. [17:23] Which one is used is already specified in the annotations and thus in the typelib, so Python can automatically provide the right format without the developer needing to append an extra "None" or a separate len(my_array) argument. [17:23] For example, in C you have [17:23] gtk_icon_theme_set_search_path (GtkIconTheme *icon_theme, const gchar *path[], gint n_elements) [17:24] In Python you can just call this as [17:24] my_icon_theme.set_search_path(['/foo', '/bar']) [17:24] and don't need to worry about the array size. [17:24] === Output arguments === [17:24] C functions can't return more than one argument, so they often use pointers which the function then fills out. Conversely, Python doesn't know about pointers, but can easily return more than one value as a tuple. [17:25] The annotations already describe which arguments are "out" arguments, so in Python they become part of the return tuple: first one is the "real" return value, and then all out arguments in the same order as they appear in the declaration. For example: [17:25] GdkWindow* gdk_window_get_pointer (GdkWindow *window, gint *x, gint *y, GdkModifierType *mask) [17:25] In Python you would call this like [17:25] (ptr_window, x, y, mask) = mywindow.get_pointer() [17:26] === GDestroyNotify === [17:26] Some GLib/GTK functions take a callback method and an extra "user_data" argument that is passed to the callback. [17:26] In C they often also take a "GDestroyNotify" function which is run once all callbacks are done, in order to free the memory of user_data. [17:26] As Python has automatic memory management, pygobject will take care of all this by itself, so you simply don't specify the GDestroyNotify argument. [17:26] For example: [17:27] void gtk_enumerate_printers (GtkPrinterFunc func, gpointer user_data, GDestroyNotify destroy, gboolean wait) [17:27] In Python you call this as [17:27] Gtk.enumerate_printers(my_callback, my_user_data, True) [17:27] === Non-introspectable functions/methods === [17:28] When you work with PyGI for a longer time, you'll inevitably stumble over a method that simply doesn't exist in the bindings. These usually are marked with introspectable="0" in the GIR. [17:28] In the best case this is because there are some missing annotations in the library which don't have a safe default, so GI disables these to prevent crashes. They usually come along with a corresponding warning message from g-ir-scanner, and it's usually quite easy to fix these. [17:28] So please do file upstream bugs against the relevant library when you find these [17:28] Another common case are functions which take a variable number of arguments, such as gtk_cell_area_add_with_properties(). [17:29] Varargs cannot be handled safely by libgirepository. In these cases there are often alternatives available (such as gtk_cell_area_cell_set_property()). For other cases libraries now often have a ..._v() counterpart which takes a list instead of variable arguments. [17:29] == Overrides == [17:29] A specialty of pygobject is the possibility of replacing functions, methods, or classes of the introspected library with custom code, called "overrides". [17:30] As the goal is to stay very close to the original API, they should be used and written sparsely, though. [17:30] One major use case is to provide replacements for unintrospectable methods. For example, Gtk.Menu.popup() is not introspectable in GTK, but the GTK override implements this method in terms of Gtk.Menu.popup_for_device(), so in this case the override actually helps to get closer to the original API again. [17:30] Another important case is automatic data type conversion, most prominently to allow passing unicode objects to methods which expect an UTF-8 encoded gchar*. This also actually helps to prevent workarounds in application code and maintain a clean API. [17:31] Thirdly, overrides are useful if they help to massively ease development. For example it is quite laborious to do GDBus calls or GVariant constructions with the native Gio/GLib API. [17:31] pygobject offers convenience overrides to make these a lot simpler and more Pythonic, but of course without actually breaking the original API. [17:32] Overrides are shipped in /usr/share/pyshared/gi/overrides/, and should be quite easy to understand. [17:32] e. g. in /usr/share/pyshared/gi/overrides/Gtk.py you see the "def popup()" method for Menu that I mentioned above [17:32] In general you should not even be required to know about it, as most of them really just fix stuff to work as expected. [17:33] But for the GDBus/GVariant cases it is useful to know them, as you can safe yourself a ton of extra work [17:33] == Migrating pygtk2 code == [17:33] A big task that we in Ubuntu already started in the Natty cycle, and which will continue to keep us and all other PyGTK app developers busy for a while is to port PyGTK2 applications to GTK3 and PyGI. [17:33] Note that this is really two migrations in one step, but is recommended as GTK2 still has a lot of breakage with PyGI, although I did a fair amount of work to backport fixes from GTK3 (the six applications that we ported in Natty run with PyGI and GTK2, after all). [17:34] The GTK2 → GTK3 specifics are documented at http://developer.gnome.org/gtk3/stable/gtk-migrating-2-to-3.html and I don't want to cover them here. [17:34] If we compare the PyGTK vs. PyGI code for a "Hello" message box, we see that it's actually very similar in structure: [17:34] $ python -c 'from gi.repository import Gtk; Gtk.MessageDialog(None, 0, Gtk.MessageType.INFO, Gtk.ButtonsType.CLOSE, "Hello World").run()' [17:34] (^ pygi) [17:34] $ python -c 'import gtk; gtk.MessageDialog(None, 0, gtk.MESSAGE_INFO, gtk.BUTTONS_CLOSE, "Hello World").run()' [17:34] (^ pygtk) [17:35] So PyGTK also already did the representation of the C functions as proper classes and methods, thus if you port from PyGTK instead of from C, it'll be a lot easier. [17:35] === Step 1: The Great Renaming === [17:35] The biggest part in terms of volume of code changed is basically just a renaming exercise. [17:35] E. g. "gtk.*" now becomes "Gtk.*", and "gtk.MESSAGE_INFO" becomes "Gtk.MessageType.INFO". [17:35] Likewise, the imports need to be updated: "import gtk" becomes "from gi.repository import Gtk". [17:35] Fortunately this is is a mechanical task which can be automated. The pygobject git tree has a script "pygi-conver.sh" which is a long list of perl -pe 's/old/new/' string replacements. You can get it from http://git.gnome.org/browse/pygobject/tree/pygi-convert.sh. [17:36] It's really blunt, but surprisingly effective, and for small applications chances are that it will already produce something which actually runs. [17:36] Note that this script is in no way finished, and should be considered a collaborative effort amongst porters. So if you have something which should be added there, please don't hesitate to open a bug or ping me or someone else on IRC (see below). We pygobject devs will be happy to improve the script. [17:36] When you just run pygi-convert.sh in your project tree, it will work on all *.py files. [17:36] If you have other Python code there which is named differently (such as bin/myprogram), you should run it once more with all these file names as argument. [17:37] === Step 2: Wash, rinse, repeat === [17:37] Once the mechanical renamings are out of the way, the tedious and laborious part starts. As Python does not have a concept of "compile-time check" and can't even check that called methods exist or that you pass the right number of parameters, you now have to enter a loop of "start your program", "click around until it breaks", "fix it", "goto 1". [17:37] The necessary changes here are really hard to generalize, as they highly depend on what your program actually does, and this will also involve the GTK 2 → 3 parts. [17:37] One thing that comes up a lot are pack_start()/pack_end() calls. [17:38] In PyGTK they have default values for "expand", "start", and "padding", but as GTK does not have them, you won't have them in PyGI either. [17:38] There even was a patch once for providing an override for them, but it was rejected as it would cement the API incompatibility. [17:38] ted as it would cement the API incompatibility. [17:38] One thing you need to be aware of is that you can't do a migration halfway: If you try to import both "gtk" and "gi.repository.Gtk" hell will break lose and you'll get nothing but program hangs and crashes, as you are trying to work with the same library in two different ways. [17:39] You can mix static and GI bindings of _different_ libraries, such as using dbus-python and GTI-GI. [17:39] erm, Gtk-GI, sorry [17:39] === Step 3: Packaging changes === [17:39] After you have your code running with PyGI and committed it to your branch and released it, you need to update the dependencies of your distro package for PyGI. [17:39] This section will be Debian/Ubuntu specific due to the involved package names, sorry. It is not be fundamentally different on other distros, though. [17:40] You should grep your code for "gi.repository" and collect a list of all imported typelibs, and then translate them into the appropriate package name. [17:40] For example, if you import "Gtk, Notify, Gudev" you need to add package dependencies to gir1.2-gtk-3.0, gir1.2-notify-0.7, and gir1.2-gudev-1.0. [17:40] At the same time you should drop the old static bindings, like python-gtk2, python-notify, etc. [17:40] Finally you should also bump the version of the python-gobject dependency to (>= 2.28) to ensure that you run with a reasonably bug free PyGI. [17:41] == RTFM & Links == [17:41] I'd like to give a list of useful links for this topic here. [17:41] This has a good general overview about GI's architecture, annotations, etc: [17:41] https://live.gnome.org/GObjectIntrospection [17:41] The interview with Jon Palmieri and Tomeu Vizoso is also an interesting read about its state: [17:41] http://www.gnomejournal.org/article/118/pygtk-gobject-and-gnome-3 [17:41] The GI/PyGI developers hang out on IRC here: [17:42] #introspection / #python on irc.gnome.org [17:42] pygobject's git tree has a very comprehensive demo showing off pretty much all available GTK widgets in PyGI: [17:42] http://git.gnome.org/browse/pygobject/tree/demos/gtk-demo [17:42] Description of the Python overrides for much easier GVariant and GDBus support [17:42] http://www.piware.de/2011/01/na-zdravi-pygi/ [17:42] Examples of previously done pygtk → pyGI ports: [17:42] Apport: http://bazaar.launchpad.net/~apport-hackers/apport/trunk/revision/1801 [17:42] Jockey: http://bazaar.launchpad.net/~jockey-hackers/jockey/trunk/revision/679 [17:42] gtimelog: http://bazaar.launchpad.net/~pitti/gtimelog/pygi/revision/181 [17:42] system-config-printer (work in progress): http://git.fedorahosted.org/git/?p=system-config-printer.git;a=shortlog;h=refs/heads/pygi [17:42] The gtimelog one is interesting because it makes the code work with *both* PyGTK and PyGI, whichever is available. [17:43] finally, I plan to turn this talk into a proper wiki page below https://live.gnome.org/GObjectIntrospection, so that it's more useful for posterity [17:43] == Q & A == [17:43] Thanks everyone for your attention! I'm happy to answer questions now. [17:44] toabctl asked: why is it git1.2 but girepository-1.0? [17:44] 1.0 is the ABI version of libgirepository, i. e. the client side library for gjs, pygojbect, etc. to create bindings [17:45] 1.2 is the binary format version for the .typelibs [17:45] toabctl asked: what about structs like eg GDate/GDateTime? [17:45] these actually do get exported [17:46] have a look at /usr/share/gir-1.0/GLib-2.0.gir [17:46] [17:46] [17:46] [17:46] [17:46] etc. [17:46] so as long as they are relatively simple, they do work [17:47] JanC asked: does GI support named parameters & default values, so that in Python method/function calls we can leave some parameters out? [17:48] not right now [17:48] I hear that there is a plan to support default values which are specified in the C code/annotations themselves [17:48] but otherwise you'll need an override for cases where it makes sens [17:48] e [17:49] rr0hit asked: the hello world example in pygi gives me error: TypeError: __init__() takes at most 5 arguments (6 given) . What am I doing wrong [17:49] rr0hit: I suppose you are using Ubuntu 10.10? [17:49] as I said above, I'm afraid this is all pretty new, and you need 11.04 beta [17:49] crazedpsyc asked: why did pygtk not work out well? wxpython seems just fine, and it is a C wrapper as well. [17:50] well, it did work well for years [17:50] but as I said, someone would need to maintain it, and port it to GTK3, and keep that up to date, etc. [17:50] and provide missing bindings for all other GNOMEish libraries (which were often missing) [17:51] chadadavis asked: If other distros are not using the latest GI yet, is Ubuntu planning to maintain their own GI-ported version of all these apps? [17:51] no, that would be quite crazy [17:51] There are 10 minutes remaining in the current session. [17:51] so far we just ported a lot of our Ubuntu specific stuff [17:51] and I ported gtimelog, but proposed that upstream first [17:52] so likewise, if we port upstream software, we do that upstream [17:52] e. g. GNOME will certainly appreciate these patches, it's a GNOME goal to port their pygtk stack, etc. [17:52] not sure if that answered chadadavis question? [17:52] toabctl asked: how can i create a instance of GDate/GDatetime with python? and how to map these types to the python types(datetime.date/datetime.datetime) ? [17:53] $ python -c 'from gi.repository import GLib; GLib.Date()' [17:53] etc. [17:53] (not really tested much) [17:53] but that's the idea [17:54] note that structs have always been a bit fiddly, as often GI doesn't have enough type information about members [17:54] so this only works for simple structs [17:54] the more complex ones should be turned into proper GObjects (that was necessary and done in GTK3 in some cases) [17:54] the most common case is probably the Events struct, which works good enough [17:55] zinga60 asked: can I use Python introspection like dir() for the dynamically created modules? [17:55] not right now, I'm afraid [17:55] it is possible in principle, the typelib has all necessary information [17:55] but it doesn't work right now [17:55] zinga60 asked: so as a beginner with gtk, etc. (without the need of porting from pygtk to pygi) I should use the official C API docs (to look up function signatures, etc.) and the gir-xml files to see the corresponding Python name spaces? [17:56] usually the C API docs (libgtk-3-doc etc.) should suffice [17:56] with the appropriate transformation rules that I mentioned above [17:56] There are 5 minutes remaining in the current session. [17:56] so usually you should be able to easily derive the according Python call [17:56] if not, you can look in the gir, but I seldomly found that necessary myself [17:56] out of questions :) [17:56] so, thanks everyone! [17:57] I hang out in #ubuntu-desktop, #ubuntu-devel, and also #python/#introspection on the GNOME IRC, so feel free to ask me there later [17:58] dpm: clearing the floor then [17:58] for manish_ [17:59] thanks a lot for a great session pitti! [17:59] excellent participation as well [18:01] Next up are m4n1sh (or m4n1sh_) and seiflotfy from the Zeitgeist project, who are going to talk about integrating Zeitgeist to your application === ChanServ changed the topic of #ubuntu-classroom to: Welcome to the Ubuntu Classroom - https://wiki.ubuntu.com/Classroom || Support in #ubuntu || Upcoming Schedule: http://is.gd/8rtIi || Questions in #ubuntu-classroom-chat || Event: Ubuntu App Developer Week - Current Session: Zeitgeist API & Zeigeist Application Integration - Instructors: m4n1sh, seiflofty [18:01] Logs for this session will be available at http://irclogs.ubuntu.com/2011/04/12/%23ubuntu-classroom.html following the conclusion of the session. [18:02] Hello everyone [18:02] My name is Manish Sinha [18:02] and seiflotfy is Seif Lotfy [18:02] we both work in Zeitgeist team [18:02] I am just giving a small introduction [18:03] Seif is the founder of Zeitgeist [18:03] and I work on integration and some engine work [18:03] Let us start seiflotfy :) [18:03] first a basic introduction [18:03] Zeitgeist is an event logger [18:03] which logs the events which happens on your computer [18:03] events can be opening files [18:03] closing files [18:03] creating files [18:04] connecting to internet [18:04] receiving a call [18:04] all the event logging doesnt happen automagically === ChanServ changed the topic of #ubuntu-classroom to: Welcome to the Ubuntu Classroom - https://wiki.ubuntu.com/Classroom || Support in #ubuntu || Upcoming Schedule: http://is.gd/8rtIi || Questions in #ubuntu-classroom-chat || Event: Ubuntu App Developer Week - Current Session: Zeitgeist API & Zeigeist Application Integration - Instructors: m4n1sh, seiflofty, manish [18:04] zeitgeist is a daemon running on your computer [18:04] Logs for this session will be available at http://irclogs.ubuntu.com/2011/04/12/%23ubuntu-classroom.html following the conclusion of the session. [18:04] whose work is to get events [18:04] means log them [18:05] when some application sends the data to it [18:05] and applications can also query events from the daemon [18:05] it is like a event store [18:05] when we talk about integration, we mean creating small plugins/extensions/addons/addins which sends the relevant events to the daemon [18:06] so basically it is the plugins which push data [18:06] all the plugins which push events are called dataproviders [18:06] their work is to only push data [18:07] like whenever you open a note, a tomboy extension tells zeitgeist that the user opened the note [18:07] this extension is called an Event [18:07] the most important part of Zeitgeist is called an event [18:07] event is a packet of information which tells the daemon of "What happened" [18:07] take the literal meaning of event [18:08] each event instance has metadata contained with it [18:08] like timestamp [18:08] what happened [18:08] how it happened [18:08] any payload [18:08] which application was involved in the event etc [18:08] zeitgeist runs as a daemon and exposes an API via DBus [18:09] DBus is an interprocess communication software [18:09] it helps applications talk to each other [18:09] to inspect the zeitgeist API [18:09] you can install d-feet from the repositories [18:09] and open it [18:09] and search for zeitgeist [18:09] you will get something like this [18:09] http://i.imgur.com/DKx0G.png [18:09] the zeitgeist API looks like this [18:09] http://zeitgeist-project.com/docs/0.5.2/dbus_api.html#org-gnome-zeitgeist-log [18:10] let us start with the basic building block of zeitgeist [18:10] an Event [18:10] how event looks like is given here [18:10] http://zeitgeist-project.com/docs/0.6/dbus_api.html#index-0 [18:10] the first thing is an event Id [18:10] which recognizes it uniquely [18:10] 2nd is Timestamp telling when it happened [18:11] 3rd is interpretation [18:11] which means [18:11] “what happened” [18:11] 4th is Manifestation [18:11] which means [18:11] “how did this happen” [18:11] then we have an actor which looks like application://tomboy.desktop [18:11] which tells which application was involved in the event [18:12] this is the metadata for an event [18:12] each event can then contain something called as Subject [18:12] each event can have more than one subject [18:12] now we should go to what is subject contained of [18:12] URI which is something like file:///tmp/my.txt [18:13] Interpretation - the abstract notion of what the subject [18:13] Manifestation - the abstract notion of how the subject is stored or available [18:13] like the subject is stored as a File [18:13] Origin - the URI where the user accessed the subject from [18:13] Mimetype [18:13] which is something like text/plain [18:13] image/png [18:14] Text - a descriptive explanation [18:14] Storage - how it is stored [18:14] I know all these were a bit boring, but it is important for a developer to understand what an event actually is [18:14] to access Zeitgeist API [18:14] you have Python bindings [18:14] C/Vala bindings [18:14] C# bindings [18:15] so you can choose your language [18:15] if you are working on a application which needs zeitgeist integration and it is coded in Python then you can use the python binding of zeitgeist [18:15] you lets move to the API [18:15] this is the API [18:15] http://zeitgeist-project.com/docs/0.5.2/dbus_api.html#org-gnome-zeitgeist-log [18:16] lets not go so deep in the API [18:16] only a few methods [18:16] like InsertEvents [18:16] which inserts events in the daemon [18:17] GetEvents - which gets events from the daemon when you specify the event ids [18:17] And 3rd [18:17] FindEventIds - you can search for events [18:17] and get back the event Ids [18:17] FindEvents - you can search for events, and get the actual events instead of just the ID [18:18] when searching for an event you use the event template [18:18] it is like a pattern [18:18] the best part is that event template are events themselves [18:18] they are represented the same way [18:18] let me take you people to an example which will clear all the doubts [18:18] we will take a working example [18:19] our example uses python API [18:19] git.gnome.org/browse/rhythmbox/tree/plugins/rbzeitgeist/rbzeitgeist/__init__.py [18:19] please open this file [18:20] now I am teaching how to push events [18:20] not pulling [18:20] check line 36 and 37 of the link I have [18:20] *gave [18:20] from zeitgeist.client import ZeitgeistClient [18:20] from zeitgeist.datamodel import Event, Subject, Interpretation, Manifestation [18:21] we imported Evebt, Subject, Manifestation and Interpretation [18:21] now we have to determine the Interpretation for Event and Subject [18:21] similarly Manifestation for Event and Subject [18:22] Event Interpretation is either LEAVE_EVENT or ACCESS_EVENT [18:22] which means "what happened" [18:23] ACCESS_EVENT means that the track started [18:23] we are at the start of the event [18:23] means we started playing the track [18:23] LEAVE_EVENT means we left the track [18:23] means track finished [18:23] Event Manifestation: USER_ACTIVITY/SCHEDULED_ACTIVITY : 120/122 - "how did this happen" [18:23] How did it happen? [18:23] It happened via User Activity or Scheduled Activity [18:24] UserActivity means that the user himself pressed Next track [18:24] Scheduled means the next track in the queue started itself [18:24] check line 120 and 122 [18:25] the list of interprerations is here http://zeitgeist-project.com/docs/0.6/ontology.html#symbol-interpretation [18:25] and list of Manifestation http://zeitgeist-project.com/docs/0.6/ontology.html#symbol-manifestation [18:25] please choose one from these list [18:25] next is Subject Interpration [18:25] Subject Interpretation: AUDIO : 135 - "what is this" [18:25] check line 135 [18:25] What is this? It is Audio :) [18:26] akshatj asked: Are there guides available on how to write a dataprovider or plugin? [18:26] akshatj: there are definitive guide. This session is meant for that :) [18:26] next is Subject Manifestation [18:26] check line 62 [18:26] Manifestion for subject asks [18:26] "how does this item exist" === jhernandez is now known as jhernandez_afk [18:26] it exists as FILE_DATA_OBJECT [18:27] all these values are from the list of Manifestation [18:27] I will give you people one more example to study yourself [18:27] It is EOG Plugin [18:27] the file is [18:27] http://bazaar.launchpad.net/~zeitgeist-dataproviders/zeitgeist-dataproviders/trunk/view/head:/eog/zeitgeist_plugin.py [18:27] Hints are [18:27] Event Interpretation: MODIFY_EVENT/LEAVE_EVENT : 69/87 - "what happened" [18:27] Event Manifestation: USER_ACTIVITY : 70/88 - "how did this happen" [18:27] Subject Interpretation: IMAGE : 61 - "what is this" [18:27] Subject Manifestation: FILE_DATA_OBJECT : 62 - "how does this item exist" [18:28] Keep the questions coming people [18:28] More examples [18:28] Tomboy: [18:28] http://bazaar.launchpad.net/~zeitgeist-dataproviders/zeitgeist-dataproviders/trunk/files/head:/tomboy/ [18:28] Banshee: https://gitorious.org/banshee-community-extensions/banshee-community-extensions/blobs/master/src/ZeitgeistDataprovider/Banshee.ZeitgeistDataprovider/ZeitgeistDataprovider.cs [18:28] I would also like to defuse a few myths [18:28] Zeitgeist is not a file search engine [18:28] it does not track files [18:29] there can be events for zeitgeist which might not need a file [18:29] like you got disconnected from internet [18:29] or you recieved a call [18:29] I would like to recieve some feedback from you people before I advance to next part of the session [18:29] you can keep them coming on -chat channel [18:30] moving to next part [18:31] we have to search for events [18:31] for searching for events [18:31] we can look at the method [18:31] FindEvents [18:31] it contains [18:32] murphy asked: Can you please give an example of some context sensitive situation Zeitgeist helps with? [18:32] murphy: as seiflotfy gave you the link on -chat [18:32] http://www.youtube.com/watch?v=U6YOvVaRWh4 [18:32] this is an example [18:32] it contains [18:32] time_range [18:33] which tells you the range of time when you want to search [18:33] like you want to search for events only between today and 3 days back [18:33] event_templates [18:33] you can create event instances and pass it [18:33] the daemon will compare these templates to the stored events [18:34] and provide you with the results [18:34] storage_state [18:34] it is [18:34] Enumeration class defining the possible values for the storage state of an event subject. [18:34] http://zeitgeist-project.com/docs/0.5.2/datamodel.html#zeitgeist.datamodel.StorageState [18:34] contains 3 values [18:34] StorageState.NotAvailable [18:34] The storage medium of the events subjects must not be available to the user. (Integer value: 0) [18:34] StorageState.Available [18:34] The storage medium of all event subjects must be immediately available to the user. (Integer value: 1) [18:34] StorageState.Any [18:34] The event subjects may or may not be available. (Integer value: 2) [18:35] then we have [18:35] num_events [18:35] maximal amount of returned events [18:35] last one is [18:35] order [18:35] which asks in which order the results have to be returned [18:36] result type is an enumration [18:36] http://zeitgeist-project.com/docs/0.5.2/datamodel.html#zeitgeist.datamodel.ResultType [18:36] it has many values [18:36] have a look [18:36] this contains the full list of events [18:36] http://zeitgeist-project.com/docs/0.5.2/dbus_api.html#org-gnome-zeitgeist-log [18:37] now we have an example of how we can pull the events [18:37] we have a gedit plugin [18:37] here [18:37] http://paste.ubuntu.com/593228/ [18:37] written by seiflotfy and others [18:37] seiflotfy: can you explain this [18:37] sure [18:37] so [18:37] template = Event() [18:37] template.actor = "application://gedit.desktop" [18:37] here you can see an Event being created [18:38] and the actor of the event is being set to "gedit" [18:38] we then ask Zeitgeist for [18:38] "Get me most used files with gedit" [18:38] this will look like this [18:38] CLIENT.find_events_for_templates([template], handle_most, num_events = 100, result_type = ResultType.MostUsed) [18:38] where handle_most is a method for the callback [18:39] and then you get the "most used" files with gedit === ChanServ changed the topic of #ubuntu-classroom to: Welcome to the Ubuntu Classroom - https://wiki.ubuntu.com/Classroom || Support in #ubuntu || Upcoming Schedule: http://is.gd/8rtIi || Questions in #ubuntu-classroom-chat || Event: Ubuntu App Developer Week - Current Session: Zeitgeist API & Zeigeist Application Integration - Instructors: m4n1sh, seiflofty, manish, seiflotfy [18:39] Logs for this session will be available at http://irclogs.ubuntu.com/2011/04/12/%23ubuntu-classroom.html following the conclusion of the session. [18:39] the whole code can be found http://paste.ubuntu.com/593238/ [18:40] if you people want a documentation of zeitgeist for mono/C# it can be found here [18:40] http://launchpad.net/zeitgeist-sharp/0.1/0.1.0.1/+download/zeitgeist-sharp-0.1-api-doc.tar.gz [18:41] and for C/Vala library [18:41] documentation is here http://people.canonical.com/~kamstrup/projects/libzeitgeist/doc [18:41] akshatj asked: So, dataprovider is used for pushing data to zg and plugin is used for pulling from it? [18:42] akshatj: dataprovider is out term for those plugins which only push events to the daemon [18:42] they dont pull [18:42] dataproviders are a subset of plugins [18:42] we have many dataproviders already [18:42] they are hosted here [18:42] https://launchpad.net/zeitgeist-dataproviders [18:43] you can see the list here [18:43] http://bazaar.launchpad.net/~libzeitgeist-developers/libzeitgeist/trunk/files [18:43] sorry [18:43] wrong link [18:43] http://bazaar.launchpad.net/~zeitgeist-dataproviders/zeitgeist-dataproviders/trunk/files [18:43] like [18:43] bzr, chrome, emacs, eog, firefox, chrome, geany, gedit, rhythmbox, telepathy, tomboy [18:44] vim xchat [18:44] banshee [18:44] banshee is upstream [18:44] not in this repo [18:44] we need more dataproviders [18:44] to make more sensible logging [18:44] or say more detailed logging [18:45] then we can have plugins which pull information [18:45] example.. I can show a snapshot [18:45] of how gedit source code you checked actually looks like [18:45] http://wiki.zeitgeist-project.com/images/2/2b/GEditOpenZeitgeist.png [18:45] if you use synapse [18:45] it shows results from zeitgeist [18:46] it asks zeitgeist for info [18:46] asked : this may be a silly question but, what is the purpose of zietguiest, and how is it different than syslog? [18:46] syslog logs system events [18:46] it does not log that you opened a file [18:46] syslog contains things like [18:47] Apr 12 23:17:01 Foo CRON[4852]: (root) CMD ( cd / && run-parts --report /etc/cron.hourly) [18:47] how much sense did it make to you :) [18:47] it stores info in unstructured format [18:47] does not have any dedicated API (as far as I know) [18:48] so what all you can do via Zeitgeist [18:48] you can have a complete list [18:48] of which file you opened when, closed when, saved when [18:48] started from when it was created [18:48] you can have a list of all the calls you recieved via empathy [18:48] when you recieved, when you dropped [18:48] when you got a call [18:48] the whole list [18:49] we people are still working in that area [18:49] we have telepathy work in progress [18:49] we need to integrate it even more [18:49] you can even list down all recent used files [18:49] sort them based on [18:49] 1) Application [18:50] 2) Which all were related to file creation [18:50] 3) Time Range [18:50] etc etc [18:50] Windows has a logging facility that was originally an attempt to store more structured log data that could be better parsed. Is that about the same idea here? So the idea is to replace .xsession-errors with a more structured log system? [18:50] psusi asked this question [18:50] I don't remember if windows had such a thing [18:50] I think it is there somewhere in Control Panel [18:50] I dont think anyone uses it [18:51] it is about Logs [18:51] same like we have in Linux [18:51] syslog, messages, kern.log etc [18:51] but zeitgeist is meant not only for storing data [18:51] There are 10 minutes remaining in the current session. [18:51] but having a nice API such that any application can get back the data [18:52] Zeitgeist is a thing under development [18:52] and its development is very fast [18:52] we all are learning a lot [18:52] so if you want to learn a lot, you can come to our channel #zeitgeist [18:52] try out some examples [18:52] and get your hands dirty [18:53] I am always there after 16UTC on that channel by this same nick [18:53] murphy asked: So if I copied a file to a server using nautilus I would be able to discover which server and what I copied a few days later (assuming nautilus informed zg)? Stuff for which there is usually no log... What about bash? [18:53] murphy: sadly bash events are not logged now [18:53] since we use GtkRecentManager for logging where plugins are not available [18:53] it is fallback logging [18:54] AFAIK bash doesnt inform GtkRecentManager [18:54] so it is not logged [18:54] we need a dataprovider for bash too [18:54] wrt nautilus [18:54] the source file is surely logged [18:54] nautilus does inform zeitgeist [18:54] using GtkRecentManager [18:54] and it gets logged to zeitgeist [18:54] you can come to know about it [18:55] wrt to "which server" depends on the URI [18:55] which is stored [18:55] zinga60 asked: how does the zeitgeist daemon store the events? in some db I guess? is it going to be more slow with more and more data providers and the longer the daemon runs (over months/years)? [18:55] zinga60: events are stored in sqlite database in ~/.local/share/zeitgeist/activity.sqlite [18:55] please dont try to open it maually [18:55] it is locked by the daemon [18:56] it *might* become slow and slow as millions of events fill up [18:56] but it will take lot of time [18:56] dataproviders dont make it slow [18:56] There are 5 minutes remaining in the current session. [18:56] as dataproviders run with the application [18:56] daemon can run for months and years [18:56] it is perfectly fine for it to work for long time [18:57] it doesnt leak memory [18:57] if it leaks memory, please inform us on #zeitgeist [18:57] yea, sounds like what MS originally intended the windows logging service to be, but it never really caught on and so nobody uses it today... only they had it apply to both system logging and user application logging. Zeitgeist has no intention of handling syslog events as well? Only desktop events? Or will there be a version on the system dbus as well as the session? [18:57] we handle mostly desktop events [18:57] which helps the *user* [18:57] our area of focus is desktop events [18:57] depends what apps push into it [18:58] even though zeitgeist can log any event [18:58] even system events [18:58] exactly [18:58] a user doesnt care much about system events [18:58] ubuntu one uses zeitgeist to log sync events [18:58] :) [18:58] closing time [18:58] please join us at #zeitgeist channel [18:58] we are happy to mentor anyone who wants to work with us [18:59] zeitgeist team is an extremely rocking and close-knit team [18:59] if you join us, you will really enjoy [18:59] take my word :) [18:59] we have a list of things we need to get done [18:59] so feel free to join [18:59] so there is no instance running on the system wide dbus? [18:59] zeitgeist runs as SessionBus which is user based [18:59] instead of SystemBus which is system wide [19:00] makes sense to run on per user basis [19:00] we have many many more things to do [19:00] lots of applications needs to be touched [19:00] we have a rush of adrenalin whenever we get something done :) [19:00] just for info.. if anyone of you know django we have a good work for you :) [19:00] feel free to poke me [19:01] esp if you know django-piston then you can start contributing to us very easily === ChanServ changed the topic of #ubuntu-classroom to: Welcome to the Ubuntu Classroom - https://wiki.ubuntu.com/Classroom || Support in #ubuntu || Upcoming Schedule: http://is.gd/8rtIi || Questions in #ubuntu-classroom-chat || Event: Ubuntu App Developer Week - Current Session: GStreamer+Python: Multimedia Swiss Army Machete - Instructors: jderose [19:01] thanks seiflotfy and m4n1sh for a great session! Next up: jderose will tell us all about using python and gstreamer in many interesting ways :) [19:01] Logs for this session will be available at http://irclogs.ubuntu.com/2011/04/12/%23ubuntu-classroom.html following the conclusion of the session. [19:01] Thanks everyone [19:03] okay, should i start? [19:03] yes :) [19:03] Hi everyone, hope you're having a great Ubuntu App Developer Week so far! [19:03] Okay, lets get started... [19:03] I have a short prepared intro to get you pumped up about GStreamer + Python. [19:03] Then we'll spend rest of the hour getting our hands dirty with real code, and I'll do my best to answer all of your questions. [19:04] During the intro, why don't you make sure the packages needed for the code examples are installed: [19:04] sudo apt-get install gstreamer0.10-tools python-gst0.10 gstreamer0.10-plugins-good [19:04] Aside from `gstreamer0.10-tools`, you probably already have the rest installed, but it's good to make sure we're on the same page package-wise. [19:04] I'm running Natty, but the examples should work fine under Maverick and Lucid too, and even older release. [19:05] == INTRO == [19:05] First, I'm going to share why I think GStreamer is *the* multimedia framework, is going to totally dominate in *everything* from simple playback to big production video editing. [19:05] I hope you're a bit surprised as to why I think this, because it's exciting, and I want to get you exited! [19:05] If I don't surprise you, then I assume you're already as excited as I am :) [19:05] Second, I'm going to share why I think Python is *the* language for building GStreamer apps, and correct some misconceptions I frequently hear about Python threading and GStreamer. [19:06] -- Why GStreamer? -- [19:06] Ah, I should introduce myself. My name is Jason Gerard DeRose, and I started writing pygst apps 7 years ago, back when gstreamer0.8 was the hot newness. [19:06] So I have a longtime love affair with GStreamer. [19:06] But recently I had to pick the multimedia framework for Novacut, my distributed (ala bzr/git/hg) video editor project. [19:07] Novacut isn't just a project, it's a startup, so I needed to pick something that makes good longterm strategic sense. [19:07] GStreamer was my gut feeling, but I played devils advocate with myself and looked at a number of other options. [19:07] I looked most seriously at Media Lovin' Toolkit (MLT), as Jonathan Thomas originally was using GStreamer + Gnonlin for OpenShot, and then switched to MLT out of frustration. [19:07] I believe Jonathan pointed out some legitimate weaknesses in Gnonlin, and the OpenShot development pace has been impressively quick, so you can't argue with that. [19:07] However, I still chose GStreamer without hesitation. Why? [19:08] * jderose makes "drumroll" sounds... [19:08] * GStreamer is on the Kindle [19:08] * GStreamer is on the Nokia N900 [19:08] * GStreamer is on webos phones and tablets [19:08] * GStreamer is what's getting attention from those wonderful Linaro folks [19:08] * GStreamer is on every Ubuntu desktop, along with most other desktop Linux distros [19:08] In short, I choose GStreamer because of it's economy of scale. [19:09] GStreamer is already running on everything from small to medium, and although running it at industrial scale (big) might not be that common right now... it's inevitable. [19:09] And doesn't that sound strikingly similar to something? [19:09] It does to me: the Linux kernel, running on everything from smart phones to supercomputers, everything from consumer grade to pro grade. [19:09] Once you reach that economy of scale, you're pretty unbeatable. And I believe that over the past several years GStreamer has reached that tipping point. [19:09] Nonlinear editing is easily exercising 90% of the same code paths as playback. [19:09] And from a business perspective, I'd choose something where I knew that 90% would be getting serious investment across the industry... [19:10] even if the other 10% might currently have some shortcomings compared to other options. [19:10] I believe Edward Hervey has built an excellent foundation in Gnonlin. It just needs more developers, more apps uses it, more users abusing it. [19:10] -- Why Python? -- [19:11] Why not? GStreamer gives you a lot of power, you can build arbitrarily complex pipelines. [19:11] And that's exactly the place when a simple, clear language like Python is perfect. [19:11] You want to be able to iterate quite, and write tons of tests without a lot of friction. [19:11] Now if you want to write new GStreamer plugins (say some new video filter), those should of course be written in C. [19:12] But the job of assembling a GStreamer Pipeline can get surprisingly complex, and that's a great place for Python. [19:12] Q: But wont Python make my GStreamer application slow because Python only allows on thread to run at once because of the Global Interpreter Lock (GIL)? [19:12] A: No :) [19:12] The Python GIL means only one thread at a time can *manipulate Python state*. [19:12] But an arbitrary number of threads can run at once assuming those threads are't manipulating Python state (aka pretty much everything GStreamer does). [19:13] So repeat after me: [19:13] "Python wont make my GStreamer application slow, because after I assemble and start the pipeline, Python just sits there waiting for signals from GStreamer, and GStreamer with exactly the same performance it would have it the pipeline were assembled and started in C!" [19:13] :) [19:14] == LEARNING BY DOING == [19:14] okay, is everyone ready to play with some code? [19:15] anyone needs a moment to catch up, at any point, please say so in #ubuntu-classroom-chat, which is also where you ask questions [19:15] QUESTION: So, that's because the threads are just running code from an external lib, then, rather then Python code? [19:15] chadadavis: basically, yes. [19:16] gstreamer can/will create quite a few different threads, say for video playback [19:17] and unless you wrote gstreamer plugins in python (which is possible, and handy for prototyping) [19:17] python wont actually be doing anything in any of those threads [19:17] python will just be sitting idle waiting for events from gstreamer [19:17] the normal way to use gstreamer is all asyncronous [19:18] okay, do doing stuff with multimedia, you always need a test video to work with: [19:18] http://cdn.novacut.com/jorge.ogv [19:18] :) [19:19] everyone go ahead and grab the example code here: [19:19] bzr branch lp:~jderose/+junk/machete [19:20] or you can browse it here - http://bazaar.launchpad.net/~jderose/+junk/machete/files [19:20] i didn't quite have time to get all the minimal python examples together i wanted, so i'm ganna wing it a bit, but thats okay :) [19:21] gstreamer is a graph based pipeline, very genric at it's core [19:22] the `gst-launch-0.10` command is very handy for quickly testing a pipeline, so lets look at ex1-audio-flac.sh - http://bazaar.launchpad.net/~jderose/+junk/machete/view/head:/ex1-audio-flac.sh === kevin7060 is now known as seidos [19:23] i know, not python yet, but this is a good way to see what gstreamer is going conceptually :) [19:23] so the first element in this pipeline is `filesrc`... which reads from a file, in this case "jorge.ogv" [19:24] the next element is `oggdemux`... ogg is a containing that can contain many different types of data inside: theroa video, vp8 video, vorbis audio, flac audio, etc [19:25] so a demuxer will take a container as split out individual elementary streams [19:25] in this example, were just going to split out the vorbis audio, transcode to flac [19:26] now gst-launch has some magic it dose behind the scences, so it's a bit more complex from python, where you're doing everything very explicity [19:27] now, let me introduce you to handy cool you'll use all the time if you do much with gstreamer [19:27] in a terminal, run: [19:27] gst-inspect-0.10 vorbisdec [19:28] sudo apt-get install gstreamer0.10-tools [19:28] you might have to install that ^^^ [19:28] that work for everyone? [19:29] if you scroll up in the output, you'll see something like this: [19:29] SINK template: 'sink' [19:29] Availability: Always [19:29] Capabilities: [19:29] audio/x-vorbis [19:30] vorbisdec can receive 'audio/x-vorbis', only [19:31] gstreamer has "caps" (capabilities) that describe what an element can consume (at its src pads), and what an element can produce (at its sink pads) [19:31] so when you assemble and start a pipeline, the elements do some pretty amazing dynamic negotiation [19:32] okay, back to example - http://bazaar.launchpad.net/~jderose/+junk/machete/view/head:/ex1-audio-flac.sh [19:33] the `audiorate` rate element will duplicate or drop samples in order to make the buffer timestamps match whatever the global clock of the pipeline is [19:33] it can also correct badly constructed files, or deal with issues where on formats idea of time is different than anothers [19:34] this stuff gets trick to make work all the time because so many of the media files in the wild are often slightly broken, don't comply with a spec totally [19:34] `audioconvert`, okay, now we go back to gst-inspect-0.10 [19:35] gst-inspect-0.10 vorbisdec [19:35] SRC template: 'src' [19:35] Availability: Always [19:35] Capabilities: [19:35] audio/x-raw-float [19:35] rate: [ 1, 2147483647 ] [19:35] channels: [ 1, 256 ] [19:35] endianness: 1234 [19:35] width: 32 [19:35] gst-inspect-0.10 flacenc [19:35] SINK template: 'sink' [19:35] Availability: Always [19:35] Capabilities: [19:35] audio/x-raw-int [19:35] endianness: 1234 [19:35] signed: true [19:35] width: 8 [19:35] depth: 8 [19:35] rate: [ 1, 655350 ] [19:35] channels: [ 1, 8 ] [19:36] so vorbisdec produces audio/x-raw-float, but flacenc consumes audio/x-raw-int [19:36] you might try removing the `audioconvert` from that pipeline, and you'll see that things wont work [19:37] so audioconvert sees that on one side there is audio/x-raw-flow, the other audio/x-raw-int, and it converts between the two [19:37] make sense? [19:38] http://bazaar.launchpad.net/~jderose/+junk/machete/view/head:/ex2-transcode.py [19:38] i didn't have time to trim this down, but here we go [19:39] http://bazaar.launchpad.net/~jderose/+junk/machete/view/head:/ex2-transcode.py#L236 [19:39] look at the AudioTranscoder class [19:39] this is a common pattern in pygst [19:40] there is a step you need, like trancoding audio, and you want it to me reusuable [19:40] so you but the only process into a gst.Bin, and use that element abstractly [19:40] very handy [19:40] gst.element_factory_make('queue') [19:40] this deserves special mention [19:41] when you have something like a jorge.ogv, which has audio and video, you need to use queues like this: [19:42] audio side: demux => inq => dec => enc => outq => mux [19:42] video side: audio side: demux => inq => dec => enc => outq => mux [19:43] this is because the audio and video are interleaved in the container, and if you don't do this, things will just hang because there wont be exactly enough to keep all the consumers happy [19:44] -- Getting Signals/Events from pygst -- [19:44] http://bazaar.launchpad.net/~jderose/+junk/machete/view/head:/ex2-transcode.py#L308 [19:45] chadadavis: QUESTION: So, a queue can be a mux or a demux, How does it know what's what? [19:45] will, a queue itself is neither, a queue is a type of gstreamer element [19:45] gst-inspect-0.10 queue [19:46] a queue just means that buffers can be added before the last was consumed [19:46] most of the gstreamer elements are 1-to-1: consume a buffer, do stuff, produce a buffer [19:47] self.bus = self.pipeline.get_bus() [19:47] you get messages from pygst using a "bus" [19:47] this is quite nice because it takes care of a threading issue that can be a pain... [19:48] messages from the bus are only emitted in the main thread [19:48] so your UI code can always safely manipulate the UI state based on the signal [19:49] self.bus.connect('message::eos', self.on_eos) [19:49] this signal is fired when the pipeline has completed, when say an entire file has been transcoded, rendered, played back, etc [19:49] self.bus.connect('message::error', self.on_error) [19:50] and this one when gstreamer encounters an error.... any time you build a pipeline, you'll probably have those two signals [19:50] at least those two, that is [19:50] http://bazaar.launchpad.net/~jderose/+junk/machete/view/head:/ex2-transcode.py#L331 [19:51] a Pipeline is sort of the main containing for all the gstreamer elements you chain together [19:51] There are 10 minutes remaining in the current session. [19:51] so any element that is linked into the chain *must* be in the pipeline [19:52] murphy: QUESTION: what about progress events? [19:52] good question :) [19:52] so gstreamer doesn't have intrinsic progress events [19:53] so what you do is great a gobject timeout that fires every 1 second or whatever [19:53] and then you query gstreamer to figure out where it is the the pipeline [19:53] you would to this for a seek bar for audio/video playback [19:53] or to get progress for transcoding [19:54] http://bazaar.launchpad.net/~jderose/+junk/machete/view/head:/ex2-transcode.py#L348 [19:54] i know the times about up, but i want to talk about states a bit [19:54] gst.STATE_NULL - no resources have been alocated at all [19:55] gst.STATE_READY - plugins are ready, but they haven't actually touched any data, allocated buffers [19:56] gst.STATE_PAUSED - the first buffers have been consumed, pipeline is negotiated [19:56] There are 5 minutes remaining in the current session. [19:56] gst.STATE_PLAYING - the loop is running, all the elements are consuming, producing, doing their thing [19:57] so to query the pipeline at all, it must be in at least gst.STATE_PAUSED [19:57] well, that's about time [19:57] sorry if this was a bit rough - this is my first time doing a session like this :) [19:58] i'm going to continue to work on that example repo, make it more useful [19:58] so thanks everyone, and enjoy all the rest of the sessions! :) === ChanServ changed the topic of #ubuntu-classroom to: Welcome to the Ubuntu Classroom - https://wiki.ubuntu.com/Classroom || Support in #ubuntu || Upcoming Schedule: http://is.gd/8rtIi || Questions in #ubuntu-classroom-chat || Event: Ubuntu App Developer Week - Current Session: KDE Development Intro: Q+A - Instructors: apachelogger [20:01] Logs for this session will be available at http://irclogs.ubuntu.com/2011/04/12/%23ubuntu-classroom.html following the conclusion of the session. [20:05] hey everyone, we're up for a slight change of schedule on the next session [20:05] First of all a big applause to jderose for a great session [20:06] Originally we scheduled a talk on writing KDE applications with KdeAppTemplate [20:06] but the speaker could not make it this time [20:06] however... [20:07] fear not, we've got some cool KDE topics as a replacement for you [20:07] Please welcome apachelogger and Riddell, who are going to do a quick intro and Q+A session on how to get started with KDE development [20:08] All yours apachelogger and Riddell! [20:08] thank you dpm [20:08] hi everyone [20:08] (And everyone, line up your questions on #ubuntu-classroom-chat!) [20:08] so, this session is highly dependent on your questions, the more you ask the better :) [20:10] One of the best resources for KDE development related topics is the KDE techbase [20:10] http://techbase.kde.org/ [20:10] you can find just about anything there [20:10] dpm asked: which tools do you recommend for getting started developing KDE applications? [20:11] It really depends on what you personally prefer. If you like IDEs there are 2 KDE (and Qt) centric ones. Namely KDevelop and QtCreator. [20:11] They are both very powerful and easy to use. [20:12] Of course you can also use any editor and command line tools :) [20:12] bulldog98_konv asked: whom to poke to get help? [20:12] No one :P [20:12] Usually it is best to just go to #kde-devel and ask your question [20:13] kate is great for development without being filled with options [20:13] Most of the time someone will be around to answer it. [20:13] the kde-devel mailing list is also good for questions [20:13] If that fails there is also a mailing list kde-devel@kde.org :) [20:13] if you already have some code then reviewboard.kde.org is the place to post it to get feedback [20:13] styx_ asked: Which language is recommended? Can i use java? [20:14] Good question indeed. As with Qt itself, one can write applications in a number of languages. [20:14] C++ being the (most) native language, but also Ruby, Python and C# are options [20:15] There used to be Java bindings but I think they disappeared (actually I believe they are just unmaintained, so if someone wants to pick that up... I am sure there are plenty of people who would love to write KDE magic in Java :)) [20:15] I'm a big fan of Python [20:15] PyQt is well maintained and supported, PyKDE is popular and easy to use [20:16] and none of the caring about memory stuff you get in C++ [20:16] although it can be easier to trip yourself up since there's no compiler to check all the syntax [20:16] Also a number of Kubuntu and KDE tools are written in PyKDE. [20:16] Like the Kubuntu installer, or the KDE print applet [20:17] bulldog98_konv asked: is kparts recomended for a new application or should I try not to use them? [20:17] That is a very good question indeed. For all those that do not know what a kpart is .... simply put it is a GUI plugin [20:18] Nokia dropped funding for the Java bindings so they're unmaintained indeed [20:18] For example the HTML view frame of Konqueror is a KPart and as such could be easily integrated into any application (without build time dependency on it). [20:19] So, while KParts are very powerful, as they move a couple of build time decisions to runtime, they are also a bit of a complicated thing. [20:19] My advise is to think carefully about the advantages. [20:19] If you have none, you should not use a kpart. [20:20] most applications don't need KParts, I remember when I was developing Umbrello we'd get occational suggestions to turn it into a KPart but nobody could tell us why it was just a buzz word [20:20] yeah [20:20] but they're great for e.g. rekonq where you can embed okular to read PDFs or Calligra where you can embed a spreadsheet in a word processing document [20:20] Creating a kpart is pretty easy, so turning things into a kpart as a use case arises is mostly no problem (given appropriate code design ;)) [20:21] bulldog98_konv asked: is it also possible to develop in JavaScript like Plasmoids? [20:21] I do not think you can write actual applications in javascript (not yet). [20:22] you can consider QML a form of javascript and write in that [20:22] However, as Qt recently grew new GUI magic called QML (which is based on JavasScript) it is entirely possible that in the not too far future you can indeed create apps using javascript. [20:22] At this point if you were using QML you would not have the desktop integration advantages that KDE has over Qt-only software. [20:23] though, generally you can do it already as Riddell suggested [20:23] sera10 asked: what is the state of QT/KDE integration into the Gnome desktop? (gstreamer, notifications, unity, ...) [20:23] Now, this might sounds silly ... but it is spelled Qt, and pronnouced "cute" :) [20:24] Qt (and thus KDE) can visually integrate into GNOME/GTK+ such as that you would not notice they are not actually GTK applications [20:25] http://labs.qt.nokia.com/2008/09/05/qgtkstyle-now-part-of-qt/ [20:25] that's a nice feature of Qt, it goes out of its way to integrate with gnome. I wish the equivalent was true with GTK [20:26] KDE and Canonical are working together on the notification API, unfortunately GNOME itself is not contributing to the effort (not yet anyway). [20:26] sera10: I hope this answers the question more or less, if not please ask more precisely :) [20:26] dpm asked: we've heard a lot about introspection in the GNOME world in this App Developer Week (GObject Introspection, PyGI, etc.). Is there any similar move planned in the KDE world? [20:27] KDE's Plasma team created the status notifier spec to replace the old systray protocol, that got adopted by Canonical for Unity where it's called app indicators [20:27] Canonical also worked on the dbus menu spec which it helped bring to KDE, so that's some nice cross desktop work [20:28] I am not particularly aware of what GObject Introspection is [20:28] Riddell: do you know? [20:28] gstreamer is a library for audio and video, nothing directly to do with the desktop, it's used by gnome applications and is a backend to Qt's multimedia API Phonon, so that's shared too [20:29] Ah, so regarding GObject introspection :D ... https://wiki.ubuntu.com/MeetingLogs/appdevweek1104/GObjectIntrospection [20:29] notifications have had a shared spec for a while, canonical changed that a bit by removing action from it which has since been picked up by KDE so its notifications work when running on unity [20:29] reading the first 3 lines I can say, KDE has sort of such a thing [20:29] Qt has had introspection for over 15 years, I'm glad that gtk is catching up :) [20:30] it is called smoke and basically responsible for generating almost all available KDE language bindings [20:30] when you compile Qt code the classes get read through a programme called moc which adds introspection, signals/slots and other handy features [20:32] http://quickgit.kde.org/?p=smokegen.git&a=summary <-- smoke is actually based on C++, thus faster than runtime introspection which is what QObjects (the Qt object type) have [20:33] dpm asked: what are the main technologies I should know about if I want to get started developing in KDE? === seidos is now known as saytwo [20:33] You will of course have to know the language you want to program in :) [20:34] Additionally some basic stuff about Qt (such as signals and slots). [20:34] http://doc.qt.nokia.com/4.7/signalsandslots.html [20:35] Other than that I can't think of much you would need to know really. [20:35] Riddell: anything you would like to add? [20:35] well it depends on what you want to code of course [20:35] if you want to code plasmoids then you need to know the plasma widgets [20:36] if you're using traditional widgets you want to know about designer to create the UI and the main classes from QtCore and QtGUI to do stuff with them [20:36] then you probably want to look at some of the KDE classes which add and improve on the Qt ones [20:37] Qt has many good tutorials on its docs site and there's plenty of KDE ones on techbase [20:37] sera10 asked: How should I make an app that integrates in both the KDE and the Gnome environment, regarding menu integration, notifications, default applications registered with mime-types, etc. ? [20:38] Depends on the menu you mean, if you mean the application menus, then that is actually a specification from freedesktop.org and implemented in both KDE and GNOME alike, so as long as you obey the spec you are good. [20:39] http://standards.freedesktop.org/desktop-entry-spec/latest/ === EvilPhoenix is now known as TheEvilPhoenix [20:40] If you mean the in-application menu (which for example is dragged out of the application in Unity, then you need to be in luck currently. Generally on Ubuntu all GTK apps can do that in KDE and all Qt apps (including KDE ones) can do it in Unity. [20:40] On other distributions it might or might not work equally well. === saytwo is now known as kevin4896 [20:41] default applications registered with mimetypes is part of the aforementioned desktop entry spec (in addition KDE has an overriding initial priority system, as KDE in general supports a couple more keys outlined by this specification) [20:43] Any more questions? [20:44] Very useful resources for development using the KDE platform: tutorials: http://techbase.kde.org/Development/Tutorials the API documentat: http://api.kde.org/ Qt documentation and examples: http://doc.qt.nokia.com/4.7/index.html [20:44] KDE is an exciting community to be in just now, you can read on planet.kde.org about Plasma Active which is the new inititive to take KDE software to all sorts of devices [20:45] and with innovative technologies like Nepomuk and Akonadi finally coming to fruition there's a lot of nice features becoming available and useable [20:46] and it's pleasingly stable to use as a developer and user, no rewrites are happening underneith you [20:47] sera10 asked: regarding Nepomuk, is there a standard spec for search in the works? [20:47] I do not think so. [20:49] I would imagine breaking search API down to a common denominator would be rather crippling, usually if you want to do search in an application you do not only want to search some random file on the user's file system [20:50] at least I could not imagine a use case for that :) [20:50] bulldog98_konv asked: what’s about the exapmels module? [20:50] I suppose you mean http://quickgit.kde.org/?p=kdeexamples.git&a=summary [20:51] which is indeed a very great resource of examples regarding KDE and KDE related technologies. [20:51] There are 10 minutes remaining in the current session. [20:51] like attica, which is a library for the open collaboration service [20:51] http://freedesktop.org/wiki/Specifications/open-collaboration-services [20:52] And as I mentioned earlier, the KDE techbase simply contains everything you would want to know. [20:52] For example how to contribute to the KDE community: http://techbase.kde.org/Contribute [20:53] Which is a worthwhile effort really :) [20:54] With 6 minutes left in this session.... any final questions? [20:55] bulldog98_konv asked: is DesktopSummit worth coming to learn about KDE and KDE programming? [20:55] maybe [20:56] There are 5 minutes remaining in the current session. [20:56] There are 2 days of talks, which are worthwhile if you already have an idea about Qt and KDE [20:57] desktop summit is more about getting involved in the community, knowing who all the faces are, and working on ideas for future development [20:57] going there without knowing anything about it is probably a waste of time though .... except you are bound to meet interesting, nice and possibly even famous people (somtimes they are even all 3 of them, such as Riddell :*) [20:58] * Riddell bats eyelids at apachelogger [20:58] Well. [20:59] Thanks everyone for coming and have fun developing awesome new KDE software :D [20:59] I belive m_conley is up in a few minutes [20:59] Thunderbird + Unity = Awesome, and How JCStypes Lets You Get to the Candy [21:00] Next up is Mike Conley telling us about Thunderbird and Unity and how the combination of them results in pure awesomeness :) === ChanServ changed the topic of #ubuntu-classroom to: Welcome to the Ubuntu Classroom - https://wiki.ubuntu.com/Classroom || Support in #ubuntu || Upcoming Schedule: http://is.gd/8rtIi || Questions in #ubuntu-classroom-chat || Event: Ubuntu App Developer Week - Current Session: Thunderbird + Unity = Awesome, and How JCStypes Lets You Get to the Candy - Instructors: m_conley [21:01] Logs for this session will be available at http://irclogs.ubuntu.com/2011/04/12/%23ubuntu-classroom.html following the conclusion of the session. [21:02] hey everybody! [21:02] My name is Mike Conley, and I work for Mozilla as a developer on the Thunderbird e-mail client. I was hired about 3 months ago, so I'm still learning my way around the Thunderbird codebase, but I think I'm starting to get the hang of it. [21:02] I've never given one of these sessions before, so I'm just going to play it by ear. I have my talk more or less planned, but I might run short, seeing as I don't really know how much written material fits into an hour. [21:03] So please, feel free to ask questions if you have any in #ubuntu-classroom-chat. I'll try to answer as many as I can. [21:03] Also, let me know if I'm going too fast or too slow. I'll adjust my speed accordingly. :D [21:03] First, I'm going to talk about what I've been working on over the past few months. Second, I'm going to show you some of the code I've written, and walk you through how it more or less works. Then I'll try to answer any questions you all might have. [21:04] == INTRO == [21:04] So, over the past 3 months, I've been working on ways for Thunderbird to integrate nicely into the shiny new Ubuntu Unity interface. There are three integration points that I've been working on: [21:04] 1) The Messaging Menu: we want quick access to compose and address book functions here, as well as indications for when new messages arrive. [21:04] 2) The Unity Launcher: we want to display the number of new, unread messages overtop of the Thunderbird icon in the launcher. [21:04] 3) Ubuntu One: we want Ubuntu One contacts synchronization support baked into Thunderbird [21:05] For additional reading, here's a blog post discussing my work for #1 and #2, in case you want to know a little more about those projects: http://mikeconley.ca/blog/2011/01/11/starting-work-on-mozilla-thunderbird/ [21:05] #3 is a relatively new project, and I only mention it for buzz. :) I won't be covering it today. [21:06] #1 and #2 are the furthest along, and the ones I want to focus on today. Extensions to integrate those features are available in Mozilla Labs for you to try if you'd like: http://mzl.la/unitylauncher http://mzl.la/messagingmenu . [21:06] Note that both require Thunderbird 3.3, and assume that you're running Ubuntu Natty. Instructions for installing Thunderbird 3.3 are here: http://www.liberiangeek.net/2011/03/install-latest-version-thunderbird-ubuntu-10-10-maverick-meerkat/ [21:06] (I know the instructions are for Maverick, but they'll work in Natty too, once you get to the Software Center) [21:06] Before I continue, it's possible that some of you might not know what an extension for Thunderbird is made up of. I'm going to go through that real quick. [21:07] == What is a Thunderbird Extension Made Of? == [21:07] I'm going to blast through this. More deep, detailed documentation is available here: Thunderbird extensions: https://developer.mozilla.org/en/Extensions/Thunderbird [21:07] It might surprise you to know that large parts of Thunderbird are written in Javascript and a mark-up language called XUL (which is strikingly similar to HTML), and styled with CSS. [21:08] The Javascript/XUL/CSS is then executed/rendered by the C++ engine (called "Gecko"), and boom: Thunderbird. [21:08] Imagine my surprise when I opened up the Thunderbird source code and saw Javascript staring back at me. :D Not what I expected. [21:08] Thunderbird extensions also use Javascript, XUL and CSS. This means that if you have web development skills, chances are you can build a Thunderbird extension. [21:09] It's also possible to add C++ code to an extension to access more low-level libraries (such as libunity, or libindicate-gtk). That's how I started with my Messaging Menu and Unity Launcher extensions - I wrote chunks of C++, and launched them from the Javascript portion of my extension. [21:09] As far as I knew, this was the only way to do things: I mean, how else am I supposed to talk to C libraries from a Thunderbird extension? [21:09] == Introducing: JS-Ctypes == [21:09] And here is where JS-Ctypes comes in: https://developer.mozilla.org/en/js-ctypes [21:09] JS-Ctypes allows add-on developers to access and call C libraries from within the safety of Javascript. And of course, this is Chrome-level Javascript - not the Javascript that is executed on webpages. [21:10] Don't worry - we're not letting web-site owners access system libraries here - we don't want an ActiveX fiasco. :p [21:10] So now I'm going to show you how I interact with the Unity Launcher. First, note the Unity Launcher API here: https://wiki.ubuntu.com/Unity/LauncherAPI . I used the Python example as a skeleton in order to set up the way my Javascript implementation works. [21:11] The basic idea is, get the launcher entry for a particular application, set properties on it (like the count), and make sure those properties are visible (set count_visible to true). That's all it takes to get the count up on the Launcher icon. [21:11] So, next I'm going to show you some of the code I wrote... [21:11] This is UnityLauncherLib.jsm: http://www.pastie.org/1785131 [21:12] (Note the .jsm extension - this is a Javascript Module. See https://developer.mozilla.org/en/JavaScript_code_modules/Using) [21:12] UnityLauncherLib.jsm is responsible for wrapping up all of the C library stuff for me. The init and shutdown function do (as you've probably gathered) the set-up and teardowns for the library connection. [21:12] You can look at that stuff later - what I'm interested in showing you starts on line 71 (the _declare function). [21:13] The first thing you need to do when working with JS-Ctypes is to declare the types you're working with. Using library calls like unity_launcher_entry_get_for_desktop_file and unity_launcher_entry_set_count means manipulating UnityLauncherEntry objects. We have to tell JS-Ctypes about those objects in order to manipulate them - the same way you'd declare a struct or class in a C++ header. [21:13] But that'd mean declaring every single member of every single object that we'd have to manipulate, right? [21:13] Wrong! [21:14] The good news is that, with the way the Unity Launcher API is set up, I just have to pass a pointer to a UnityLauncherEntry to various functions. I don't need to do any direct manipulation of the UnityLauncherEntry - I just pass it around. [21:14] So on line 73 of http://www.pastie.org/1785131, I declare an empty StructType called UnityLauncherEntry, and then a pointer type called UnityLauncherEntryRef. UnityLauncherEntryRef is all I'll be passing around. I suppose I also could have also used the type ctypes.voidptr_t. That probably would work too. [21:15] Ok, now I can declare the various functions I'm going to use, like unity_launcher_entry_set_count. Line 91 is where I declare that function. [21:16] The structure for that declaration is: I provide the name of the function call, the type of function (we're not on Windows, so it's default_abi), the return type (void), and then the argument types (UnityLauncherEntryRef and an unsigned integer). [21:16] The following is then possible inside Javascript: [21:16] mLauncher = UnityLauncherLib.ULEntryGetForDesktopFile("/usr/share/applications/thunderbird.desktop"); [21:16] UnityLauncherLib.ULEntrySetCount(mLauncher, 1234); [21:16] UnityLauncherLib.ULEntrySetCountVisible(mLauncher, true); [21:17] And that would display a count of 1234 overtop of the Thunderbird icon in the Unity launcher. [21:17] Similar manipulation can be done to show a progress bar over the Unity launcher icon. It's easy to imagine a progress bar to show how far along inbox syncing is. [21:18] And that's how I can interact with things like the Unity Launcher from the safety of Javascript. [21:18] Any questions so far? [21:18] Am I going too fast? Am I breezing past things that you all want to talk about? [21:19] No? [21:19] Ok. :) [21:19] So that's an example of how I can interact with things like the Unity Launcher from the safety of Javascript. [21:20] So we can call C function from within Javascript - but can we call Javascript functions from C? Yes we can! [21:20] When indicators in the Messaging Menu are clicked, we want a callback function to be run. In C/C++ this is done by using g_signal_connect to connect a function to the "user-display" event for an indicator. [21:21] I was able to use JS-Ctypes to wrap several GObject functions, including g_signal_connect (which is actually just a macro wrapping g_signal_connect_data). Here's the GObjectLib.jsm file: http://www.pastie.org/1787573 [21:21] Once again, the interesting stuff is in _declare. On line 42, I am able to define what the structure of a callback function looks like, and I use that in the definition of GSignalConnectData. [21:22] So, in my Messaging Menu extension code, with my GObjectLib loaded, I'm able to do this: [21:22] var myCallback = function myCallback(aInstance, aTimestamp, aUserData) { [21:22] alert("Hello, callback world!"); [21:23] } [21:23] myCallbackFunction = GObjectLib.GCallbackFunction(myCallback); [21:23] GObjectLib.GSignalConnect(indicator, "user-display", myCallbackFunction, null); [21:23] Where "indicator" is some indicator that's been spawned using a wrapped indicate_indicator_new. (See http://www.pastie.org/1787649) [21:24] Now, when that indicator is clicked, the Javascript callback will be fired, and we'll get our alert box. [21:24] This is pretty powerful stuff. You get the full power of the system libraries, while staying within the managed environment of Javascript. [21:26] So that's how I'm using JS-Ctypes. [21:27] I suppose I'll talk about my work integrating with Ubuntu One next. [21:28] So, a bunch of you probably know this already, but Canonical offers a service called Ubuntu One [21:28] Among other things, Ubuntu One offers contacts synchronization support [21:30] Currently, Thunderbird allows users to connect to LDAP address books, and local storage address books. On OSX, there's a system address book that we also connect to. [21:30] I'm working on adding an Ubuntu One Contacts address book to Thunderbird, to show the contacts that are stored via the Ubuntu One service [21:30] So, imagine this: [21:31] You've been using Thunderbird for a while now on your laptop, and you've built up quite a large address book, with all of your friends and workmates organized into their groups [21:31] and then you go and drop your laptop into a lake [21:32] Thankfully, once we've got Ubuntu One contacts support baked in, all you'd need to do is log into your Ubuntu One account on your new computer (because you'd probably get a new computer after that...) [21:32] magic synchronization happens, and bam: your contacts are back in Thunderbird. [21:32] The other nice thing about Ubuntu One contacts, is that it's built for *sharing* [21:32] and by sharing, I mean, sharing between applications [21:33] Evolution, for example, has the option of storing contacts via the Ubuntu One contacts synchronization service [21:33] If you want to migrate from Evolution to Thunderbird, you just need to make sure all of your contacts are synchronized, and that's it. [21:34] Thunderbird will start up, find your Evolution contacts, and away you go. [21:36] So that's what I'm working on, for Thunderbird + Unity integration [21:37] Going back to JS-Ctypes - this doesn't just work in Thunderbird [21:37] it works in Firefox as well [21:38] In fact, JS-Ctypes has been shipping in Firefox for quite a while. So, some pretty powerful extensions are now possible. [21:39] Imagine, for example, connecting the download manager to an Arduino via JS-Ctypes [21:39] You could get a big light to flash once all of your downloads are completed. [21:39] That's just off of the top of my head. [21:40] So, I guess I'll go into the declaration of types for a little bit. [21:41] So, JS-Ctypes wraps up the platform-specific fuzziness of types, and gives you a set of platform agnostic ones: for example: [21:41] ctypes.unsigned_int is your basic unsigned integer. Cross-plat. [21:42] Similarly, ctypes.unsigned_char is your basic unsigned_char. [21:42] You can declare entire objects with JS-Ctypes too, for example: [21:44] Suppose we're attempting to work with a C library that manipulates a struct called Person, with a Name and an Age [21:44] we can define this using: [21:44] var Person = new ctypes.StructType("Person", [{'name': ctypes.unsigned_char.ptr}, {'age': ctypes.unsigned_int}]); [21:45] We could then pass that structure to the library, and it'll treat it just like it would if it was called from C or C++ [21:46] Of course, once we start dealing C / C++ libraries, we get back into the issue of memory management [21:46] In my Indicator library, for example, I create indicators using indicate_indicator_new [21:47] After instantiation, I'm responsible for freeing that memory. I therefore had to wrap g_object_unref in my GObjectLib [21:48] and it works as you'd expect - I pass it a pointer to something I've allocated for (using the handy ctypes.voidptr_t - which is the equivalent of void *), and it'll do the rest. [21:48] It's also important to close the connections to the libraries once you're finished with them [21:49] For example, if I open up libgobject, like so: lib = ctypes.open("libgobject-2.0.so"), I have to close it via lib.close(). [21:49] It's again worth emphasizing that JS-Ctypes is cross-platform. That means that you can connect to Windows libraries and OSX libraries as well. [21:50] I don't use OSX myself, and I don't imagine most of you either (this *is* #ubuntu-classroom afterall), but I thought this was kind of neat: [21:50] https://developer.mozilla.org/en/js-ctypes/Examples/Add_to_iPhoto [21:51] This example is for a Firefox extension that adds a context menu item to images [21:51] There are 10 minutes remaining in the current session. [21:51] The extension makes it so that right clicking on an image gives you the option to send that image directly to the built in photo program. [21:52] Something similar could be done with F-Spot, for example - though you might not need JS-Ctypes to do it. I'm not familiar enough with the F-Spot API (if it has one) to say for certain. [21:53] So that's my talk. I'll stick around for the next 10 minutes to answer any questions you might have. Thanks for listening/reading! [21:56] There are 5 minutes remaining in the current session. [21:59] Alright, I'll assume there aren't any questions. Thanks for listening everyone! Enjoy the rest of the talks! === ChanServ changed the topic of #ubuntu-classroom to: Welcome to the Ubuntu Classroom - https://wiki.ubuntu.com/Classroom || Support in #ubuntu || Upcoming Schedule: http://is.gd/8rtIi || Questions in #ubuntu-classroom-chat || Event: Ubuntu App Developer Week - Current Session: Story: Unity, hacking on a real-world app - Instructors: Trevinho [22:01] Logs for this session will be available at http://irclogs.ubuntu.com/2011/04/12/%23ubuntu-classroom.html following the conclusion of the session. [22:03] Hi all! [22:03] I'm Marco Trevisan, also known in the Ubuntu Community as Treviño or 3v1n0 [22:04] just for giving few informations about me, I'm a 25 years old student in Computer Science and I'm an Ubuntu user since the release of (K)ubuntu Breezy Badger (well, I started as a kubuntu user in fact) [22:04] My first approaches to the hUbuntu core were done as a 3rd party packager: I started packagin a lot of extra software in my "3v1n0" repository [22:05] that was also for a certain period of time the main community reference for the ubuntu Compiz (Fusion) packages and loader scripts. [22:05] In recent times I've been involved in projects like Openmoko, Freesmartphone and SHR (www.openmoko.org, www.freesmartphone.org, www.shr-project.org, all related to the free phone development), Enlightenment (http://enlightenment.org with some elementary widget library work), Vala (the new GObject based language). [22:07] Few months ago when Unity was announced to be the future of Ubuntu, also for the "standard" distribution, I was so excited since for me it was the first great step that ubuntu was doing for becoming something of really different, but using an open way. [22:08] This decision surely shown a great courage of the "Ubuntu headquarters", but I found that it have to be supported by the community to become real [22:09] Now, Unity of course can't be considered just as the simple "lp:"unity" branch that basically includes the Compiz plugin that is able to creat the deskopt environment that we all known as "unity" [22:09] Unity is more [22:10] unity is a new ecosystem made of many applications and libraries which cooperates in various ways allowing to get what you see as an "united" interface. [22:10] Also if it should be quite known, the unity architecture is based basically on: [22:11] * Compiz, which is the basic windows manager upon the unity interface is built [22:11] * unity-window-decorator, the windows decorator based on libmetacity [22:12] * libindicator, which is a library that factorizes some common features of an indicator, allowing to load one or a set of indicators into the unity panel [22:13] * BAMF, the Application Matching Framework which allows to associate each window to an application witha related .desktop file (if it exists) [22:13] Going more in the deep you can see unity (the compiz plugin) as the painter of the items that its sub-libraries and services allows to manage and connect [22:14] If you look at the main parts of the unity interface you can consider the Panel, the Launcher and the Dash [22:15] The Panel is, in the current implementation, basically fully populated by indicators; excluding the window title and controls, in fact, that bar is populated with (when installed): [22:15] libappmenu (indicator-appmenu, the indicator showing the menu) [22:15] libapplication (the indicator which loads and shows all the libappindicator's) [22:15] libsoundmenu (indicator-sound) [22:15] libnetworkmenu (indicator-network) [22:15] libmessaging (indicator-messages) [22:16] libdatetime (indicator-datetime) [22:16] libme (indicator-me) [22:16] libsession (indicator-session) [22:17] The unity-panel-service (see unity/services) is the daemon which loads the indicators and tells to the unity pllugin tho to show them. [22:17] the unity Launcher is used for showing the icons used both for loading the dash lenses and the new application instances by type [22:19] Its role is quite easy to understand, but its implmenetation is quite complex due to the fact that in the X11 system there's not a direct link between an XWindow and a desktop file, or between more windows (of the same level / hierarchy) coming from the same application. [22:19] Here's where BAMF comes. [22:19] That framework has been written to export any window to an higher level and to associate them to a desktop file and a "dummy" application object. [22:20] All the informations that BAMF catches and organizes are finally exported via DBus to be used bu the unity launcher to understand what is happening in the desktop and to draw/manage correctly the launcher items/icons [22:21] Finally the dash is the place where any unity loaded lens is shown, but I won't go more in deep here since there are some other sessions related to it. [22:22] Now, to go back to my story which entitled the session, I've to say that I'm an advanced PC user and so I need that the tools I use are able to do what I expect from them; that's why every time I find and interesting project that needs some tuning I work on it to get what I'm missing... [22:23] That's in practice my application of the Eric S. Raymond famous motto «Every good work of software starts by scratching a developer's personal itch» that he states in "The Cathedral and the Bazaar". [22:24] Few montsh ago, my first "unity" related "itch" appeared when I found this article by OMGubuntu ( http://go.3v1n0.net/eMRF4l ) showing a way to customiz the ubuntu clock panel applet. [22:25] Since I was (as I still am) a great fan of the application indicators, also in Maverick I always used the indicator-applet-complete gnome-panel applet, to reduce to the minimum the usage of the other gnome applets. [22:26] So, when I found this nice trick, I looked a way to get it working in indicator-datetime too... I knew that indicator-datetime would be the future, so I decided to improve it. [22:27] I never hacked the sources of an Ubuntu internal project (excluding patches), so I had to learn something about it [22:28] I generally I don't use too much IRC or mailing lists, until I don't need to do that (for issues, or for RFCs), so I started my work by my own [22:29] So, the basic of bazaar usage are here: http://go.3v1n0.net/fDRS9Q and I guess that everyone here knows how to use it [22:32] So after branching it, I just had to work on it... And the hack I wanted to do was very easy so in few hours everything was on my branch at http://go.3v1n0.net/gwJkLo [22:33] For you informations, thanks to this clock-label-improvements for indicator-datetime [22:34] you can use any date/time style, included the ones you find in the OMGubuntu! article posted before with commands like: [22:34] gsettings set org.ayatana.indicator.datetime time-format "'custom'" [22:34] gsettings set org.ayatana.indicator.datetime custom-time-format "'%a %I:%M %p'" [22:35] However, after this hack... I found the process of the ubuntu development very quick and open to the community [22:35] so I decided to continue in my path working on other things that I missed in "my" ubuntu.... [22:37] A great itch I had about indicator-sound was that I wasn't able to see in aprecise way the new volume level of my system when using the scrolling hweel over the indicator icon to adjust the volume. [22:37] That was a very common operation for me and since indicators doesn't support, by design, any form of tooltips [22:38] I decided to implement it using a particular way, following what has already been done for the volume keys... [22:40] Basically I made possible to show a notify-osd bubble showing the new volume level [22:41] when a scroll-event was registerd over the indicator-sound icon; more informations about this implementation are available at the merge proposal: http://go.3v1n0.net/gNy0Qj [22:43] All this work lead to me to a greater work [22:43] which made me understand a lot of the unity infrastructure related to ubuntu indicators [22:44] or better, an ubuntu AppIndicator === Trevinho_ is now known as Trevinho [22:51] There are 10 minutes remaining in the current session. [22:52] Ok I'm back [22:52] sorry I had a network outage [22:52] and I wasn't able to get the permission to write back :P [22:53] jsjgruber89 asked: How do libapplication and unity-panel-service determine what to load? [22:53] Well, libappapplication is used by applications that want to add an AppIndicator [22:55] unity-panel-service is a service as the name states, that waits incoming DBus calls. These calls are perfomed by libappindicators [22:56] There are 5 minutes remaining in the current session. [22:58] However going back to the story.... I was telling about the libappindicator work I did... [22:59] Practically I added support for developers to catch the "scroll" events over an appindicator icont too. [22:59] But this work was quite complex as you can read in this bug report I did: https://bugs.launchpad.net/indicator-application/+bug/708180 === emma_ is now known as em [23:00] because an indicator-application is really a set of indicators [23:01] and there is a mix of DBus signals and methods and glib signals to perform operations from the lower level (the libindicator) to the higher one (the unity panel) [23:01] Logs for this session will be available at http://irclogs.ubuntu.com/2011/04/12/%23ubuntu-classroom.html === ChanServ changed the topic of #ubuntu-classroom to: Welcome to the Ubuntu Classroom - https://wiki.ubuntu.com/Classroom || Support in #ubuntu || Upcoming Schedule: http://is.gd/8rtIi || Questions in #ubuntu-classroom-chat || [23:02] So, the hour is finished, but I'll use bit of extra time to end the story :P [23:03] so, to make the long story short, Afther this first bounch of patches I continued with some others more unity related [23:04] work with some patches [23:04] to improve its look like [23:05] https://code.launchpad.net/~3v1n0/unity/fading-title (which cuts long window titles with fading, that then I've made also for metacity) [23:05] And the intellihide / autohide support https://code.launchpad.net/~3v1n0/unity/autohide-intellihide [23:07] However, I guess that you can read more about these patches in launchpad [23:09] the important thing that I want to explain is how to get there... The first part is study the sources and army yourself with the grep and few others development tools like gedit and some gedit-plugins you like [23:09] for managing the sources I've mostly used plain bazaar with the bzr-gtk plugin [23:10] to use tools like "bzr glog", "bzr gcommit", "bzr gdiff" (and so on) commands which could speed up your sources versioning process [23:10] Basically when you want to hack to an ubuntu project all you need to do is [23:10] * branch it wit bzr branch lp: [23:11] * work on it with your tools [23:11] when you're ready just push it as a your branch of that project with [23:11] bzr push lp:~YourLPname// [23:12] So you need to do a merge proposal [23:12] And you can do it with launchpad powerful merging tools [23:13] this is the key moment. [23:14] I've to say that in my experience the reviewers were always very fast to approve, and I got very few corrections (just typos), but it could happen that you get rejected or you need to rewrite something [23:15] however the ubuntu developers are and I guess that will always be very open to the community contributions [23:15] especially with unity coming, that is the creation of something new from the basis. [23:18] About contacting the developers, I'd suggest you to use the launchpad mails or the ayatana ML if you need to do augmented discussions, but for a very fast communication [23:18] it's better to use new channels as are the microblogs like twitter or identi.ca [23:19] many ubuntu developers are there (see https://twitter.com/list/3v1n0/ubuntu) and I think that it's the better way to keep them in touch. [23:20] Finally I remember you that if you want to start to work in Unity and related projects [23:20] the best way is to start from the bitesize bugs: https://wiki.ubuntu.com/Unity/Bitesize [23:21] read that wiki and the many castrojo's blogs about them go get started [23:21] and join the ubuntu development! [23:22] If there are no more questions (don't use the ClassBot, but just post them in #ubuntu-classroom-chat), I thank you all for the attention and who gave me this opportunity [23:23] Sorry for the network issues and my time overrun... [23:23] :) [23:26] Ok... Good bye all so :)