Search Results: "ag"

22 July 2012

Mark Brown: regmap updates in 3.5

A surprisingly large series of updates for regmap this time, mostly due to all the work Stephen Warren has done to add support for MMIO buses. This wasn t really the target for the framework but it turns out that there s a reasonable number of cases where it s very helpful to use the register cache support to allow the register map to remain available while the device is suspended.

Vasudev Kamath: Compiling Harfbuzz on Debian

Harfbuzz (more correctly harfbuzz-ng) is a Text Layout/shaping engine. Mostly supporting rendering of Text including complex scripts. A quote taken from Wikipedia which describes harfbuzz
HarfBuzz (in Persian: ) is a layout/shaping engine for OpenType fonts. Its purpose is to standardize text layout in FOSS; its code originally started as part of the FreeType project, was then developed separately in Qt and Pango, and finally merged back into a common repository. Both Qt and Pango currently use HarfBuzz; other standalone users include Firefox and Chromium, the open source project behind Google Chrome.
Coming directly to the point. You can get Harfbuzz from its Git repository hosted on Freedesktop. It requires following library and binary compilation
    1. ragel: Finite state machine code compiler
    2. libglib2.0-dev: Glib Development files
    3. libcairo2-dev : Cairo 2D graphics library development files
    4. libicu-dev: Development components for International components for Unicode
    5. libgraphite2-dev: Development files for libgraphite2
    6. libfreetype6-dev: Freetype 2 library development files
Once you install all the above package. Follow following commands to build the harfbuzz.
./autogen.sh
./configure --prefix=/usr
make
sudo make install
You can skip make install if you don't like it to be installed on system.I actually wanted to work on the Debian package of Harfbuzz but since there is some one already working on it. Probably I will wait till the guy completes package. I will write on testing the text rendering of your language using harfbuzz in my next post. Till then Cya.

21 July 2012

Petter Reinholdtsen: Free Culture in Norwegian - 5 chapters done, 74 percent left to do

I reported earlier that I am working on a norwegian version of the book Free Culture by Lawrence Lessig. Progress is good, and yesterday I got a major contribution from Anders Hagen Jarmund completing chapter six. The source files as well as a PDF and EPUB version of this book are available from github. I am happy to report that the draft for the first two chapters (preface, introduction) is complete, and three other chapters are also completely translated. This completes 26 percent of the number of strings (equivalent to paragraphs) in the book, and there is thus 74 percent left to translate. A graph of the progress is present at the bottom of the github project page. There is still room for more contributors. Get in touch or send github pull requests with fixes if you got time and are willing to help make this book make it to print. :) The book translation framework could also be a good basis for other translations, if you want the book to be available in your language.

Enrico Zini: Giving away distromatch

Giving away distromatch at last year's Fosdem I tried to inject a lot of energy into distromatch but shortly afterwards I've had to urgently rewrite the nm.debian.org website. After Lars Wirzenius GTDFH talks in Bologna and Varese I wrote a tool which, among other things, is able to scan my home dir and list how many projects I'm working on. The output was scary. Like, they are too many. Like, I couldn't even recite the list out of memory. And since I couldn't do that, I had no idea there were so many. And I kept being stressful because I couldn't manage to take care of them all properly. Now that I became conscious of the situation, it's time to deal with it like a grown up, and politely back off from some of my irresponsible responsibilities. Distromatch is one of them. It had just started as a proof of concept prototype, and I had the vision that it could be the basis for a fantastic culture of sharing and exchange of information across distributions. I need to distinguish the vision from the responsibility. I still have that vision for distromatch, but I cannot take responsibility for making it happen. So I am giving it up to anyone who has the time and resources to pick up that responsibility. Current status It works well enough as a prototype. I believe it can successfully map a large enough slice of packages, that one can prototype stuff based on it. I have for example used it to export the Debtags categories for other distros, and the resulting file looked big enough to be used for prototyping category-based features on distributions that don't have them yet. I think it also works well enough to support a few common use cases, like sharing screenshots, or doing most of the work of converting dependency lists from a distro to another. And finally, anyone can deploy it, and work on it. Existing data sources Everything I index in the Debian distromatch deployment is available at http://dde.debian.net/exports/distromatch/. The rpm-based data in there comes from an export script I wrote that runs on Sophie, but which I cannot maintain properly. This is an experimental export of Fedora and OpenSUSE data: http://tmp.vuntz.net/misc/distromatch/distromatch-opensuse-fedora.tar All existing export scripts are found in distromatch git repo on gitorious. Contacts I gathered at Fosdem At Fosdem I devoted quite some work to get contacts from all possible distributions and software repositories, so that distromatch could be hooked into them. Here is a dump of what I have collected: Some of those contacts may have "expired" in the meantime: I wouldn't assume all of them still remember talking with me, although most probably still do. My commitment for the time being I am happy to commit, at the moment, to maintaining a working data export for Debian data. I can take responsibility for making it so that the Debian data for it stays up to date, and to fix it asap if it isn't the case. I hope that now someone can take distromatch over from me, and make it grow to achieve its great potential.

Andrew Pollock: [life] Sarah sans gallbladder

I can't remember exactly when, it was either pre-Zoe heart-related diagnostic imaging or during her pregnancy with Zoe, that it became apparent that Sarah had gall stones. Apparently it's not uncommon for women to develop them after pregnancy, and it turns out that Sarah is slightly more genetically predisposed to getting them to boot. So it wasn't terribly surprising when she started having some pain recently. She had another ultrasound to confirm it, and went off to see a surgeon. Apparently they care more about the symptoms than the number of stones in the gallbladder, and they don't bother removing the stones and keeping the gallbladder, so she was booked in for a cholecystectomy last Thursday. It was a pretty straightforward procedure, she was out of the operating room in just under an hour, and awake a bit over an hour after that. I've had a few friends need to have a cholecystectomy, and the photos on Wikipedia have always fascinated me, particularly this one. It seems so freaky to have a gallbladder full of that much gravel. It can't be comfortable. We're going to be able to pick up Sarah's stones on Monday, so it'll be interesting to see what they look like. Sarah's recovering now. It's one of the few surgeries she's had under general anaesthesia where she hasn't been sick afterwards, so that was a good start. The procedure was done laparoscopically, using four incisions, and to give themselves room to work, they inflate the body with carbon dioxide gas, which then has to work its way out of her body over the following days. So she's dealing with some bloating, bruising and swelling at the moment, but not doing too badly. Apparently if you're vertical for too long, the gas can work its way up to your diaphragm, which causes some shoulder pain, so the trick has been to walk around a bit, then lie down for a bit, and then rinse and repeat. She's not allowed to lift Zoe for 3-4 weeks, which presents a few challenges for us, but nothing insurmountable (hopefully). We converted Zoe's crib to a toddler bed a week before the surgery, and Zoe thought that was just the best thing ever, and has taken to it really well. I'm around at home for breakfast and dinner, so I can take care of the lifting into and out of the high chair for those meals, and Zoe can eat lunch at her little table. Zoe's also pretty good about getting into and out of the car by herself (not that Sarah can drive until she's off the painkillers) and she's normally in daycare two days a week. She's in daycare again on Monday, so Sarah won't have to deal with Zoe on her own until Tuesday, and we have backup daycare arrangements we can fall back on if need be. Zoe's been very good about Sarah not being able to pick her up, and been very gentle. It helped with the explanation that Sarah could show her all of her "owwies". The surgeon was saying that only 1 in 400 people need to alter their diet after removing their gallbladder, so we're hopeful that Sarah will do just fine without it. She'll certainly be more comfortable in the long run.

Andrew Pollock: [debian] New audit package in experimental

Various security folks at work have been keen on a newer version of audit be in Ubuntu (preferably 12.04), but unfortunately the Debian maintainer has been too busy to package it for Debian, so I finally carved out some time recently to do an upload to experimental, with his permission. It would have been really nice to land it in unstable before Wheezy froze, but as it involved a library transition, and I didn't get a chance to talk to the release team about it until very close to the freeze, they said it was too late. That meant the grand plan of getting it into Ubuntu 12.10 and then trying to get it into precise-backports went up in smoke as well. Oh well. It was a fair bit of work to package. A lot of the patches were no longer relevant, and the remaining ones all needed to be refitted. It was also my first attempt at touching a library package where a SONAME bump was involved. I think I did everything correctly.

Julien Danjou: ERC notifications

Today, I've merged my erc notifications module inside Emacs trunk. This way, it will be available for everybody in Emacs 24.2. erc-notifications example This module allows you to be notified via notifications-notify (the Emacs implementation of the Freedesktop desktop notifications) on private message received on IRC, or when your nickname is mentioned on a channel. To enable it in Emacs > 24.1, you just have to add the following line to your configuration file:
(add-to-list 'erc-modules 'notifications)
If you want to download it and use it stand-alone for a previous Emacs version, you can fetch the latest file revision and load it before adding the previously given line.

Siegfried Gevatter: A gentle introduction to Zeitgeist s Python API

In this post I ll make a quick introduction by example on how to use Zeitgeist s Python API for good and profit. If you re interested in using Zeitgeist from C instead, see the libzeitgeist examples; to use it with C++/Qt, Trever s a web browser in 4 steps may be of interest. First things first In case you re not familiar with Zeitgeist, it may prove helpful to first read Mikkel s introduction to Zeitgeist post. If that s too much to read, just should know that Zeitgeist is an event log. Like the history in your browser, it keeps track of what websites you open at which point in time. It also keeps track of when you close them, and of what browser you used, since it s a system-wide service. Furthermore, it does the same for files, conversations, e-mails, and anything else you want to insert into it. So Zeitgeist is a database of events, and an event can be pretty much anything. But what does it look like? It s main attributes are the following: Additionally, each event has one or more subjects, which have the following attributes: Retrieving recent data Okay, so let s say you want to know the last song you ve listened to (if you have a Zeitgeist-enabled music player). It s a simple as:
from zeitgeist.client import ZeitgeistClient
from zeitgeist.datamodel import *
 
zeitgeist = ZeitgeistClient()
 
def on_events_received(events):
    if events:
        song = events[0]
        print "Last song: %s" % song.subjects[0].uri
    else:
        print "You haven't listened to any songs."
 
template = Event.new_for_values(subject_interpretation=Interpretation.AUDIO)
zeitgeist.find_events_for_template(template, on_events_received, num_events=1)
 
# Start a mainloop - note: the Qt mainloop also works
from gi.repository import GLib
GLib.MainLoop().run()
This may need some explaining. We start by importing the Zeitgeist client and some associated data structures (such as Event and Interpretation), and create an instance of the client. The ZeitgeistClient class is a wrapper around Zeitgeist s D-Bus API which not only makes it much nicer to use, but also makes it easy to install monitors (as we will see later) and provides convenient functionality such as automatic reconnection if the connection to the engine is lost. To query for the most recent song, we just need to create a template with the restrictions we want to impose and submit it to Zeitgeist using the find_events_for_template call. If you haven t read Mikkel s post yet, please do so, as it introduces the structure of events and subjects (in short: an event has a timestamp, some other properties, and one or more subjects representing the resources -files, websites, people - involved in the event). The Python API is inherently asynchronous (if for some reason you need a synchronous API, you may still use the lower level ZeitgeistDBusInterface class), so we need to define a callback function to handle the results we receive from the Zeitgeist engine. Finally, we need to create a main loop so the asynchronous functions can run.
Now this was a pretty simple example. Let s make it more interesting. One song isn t much, so let s get the 5 most recent songs. Also, now we want both songs and videos. The first part is pretty easy, we just need to change the num_events parameter. For the second extension, we have to change the event template. In fact, now we need two different event templates and the find_events_for_templates function, which takes an arbitrary number of event templates and ORs them. The result is as follows:
from zeitgeist.client import ZeitgeistClient
from zeitgeist.datamodel import *
 
zeitgeist = ZeitgeistClient()
 
def on_events_received(events):
    for event in events:
        print "- %s" % event.subjects[0].uri
 
tmpl1 = Event.new_for_values(subject_interpretation=Interpretation.AUDIO)
tmpl2 = Event.new_for_values(subject_interpretation=Interpretation.VIDEO)
zeitgeist.find_events_for_templates([tmpl1, tmpl2],
                                    on_events_received, num_events=5)
 
# Start a mainloop
from gi.repository import GLib
GLib.MainLoop().run()
This will work, but unless you re lucky you re likely to get some duplicate line. Why is this? Well, other than that you may have used the same file twice, don t forget that what you are requesting are actually events. If you ve started playing a given song, you probably also stopped playing it, so that s actually two of them (an AccessEvent and a LeaveEvent). Since this isn t what we want, we ll change the query a bit:
zeitgeist.find_events_for_templates(
    [tmpl1, tmpl2],
    on_events_received,
    num_events=5,
    result_type=ResultType.MostRecentSubjects,
    storage_state=StorageState.Available)
By requesting the most recent subjects, vs. the most recent events, we can filter out events with duplicate URI. See the ResultType documentation for other modes you can use. Note particularly the MostPopularSubjects result type. I also used the chance to introduce the storage_state parameter. This one will filter out events for files Zeitgeist knows aren t available (this mostly means online resources won t be shown if you don t have a network connnection; there s also support for handling external storage media, but because of problems with GIO this is currently disabled). Last but not least, the find_events_for_* methods also accept a timerange parameter. It defaults to TimeRange.until_now(), but you may change it to TimeRange.always() (if for some reason you re working with events in the future) or to any other time range of your choice. Here it s important to note that Zeitgeist s timestamps use millisecond precision.
For more advanced queries, you can use more complex combinations of events and subject templates. The rule to keep in mind here is that events are OR d and subjects are ANDed. Additionally, some field (actor, origin, mimetype, uri and current_uri) may be prefixed with an exclamation mark ( ! ) for NOT, or you may append an asterisc ( * ) to them for prefix search. You can even combine the two operators together. Here s an example of a template you could build:
subj1 = Subject.new_for_values(interpretation=Interpretation.SOURCE_CODE,
                               uri="file:///home/rainct/Development/*")
subj2 = Subject.new_for_values(uri="!file:///home/rainct/Development/zeitgeist/*")
tmpl1 = Event.new_for_values(interpretation=Interpretation.MODIFY_EVENT,
                             subjects=[subj1, subj2])
templates = [tmpl1]
In my case, this template would fetch a list of the source code files I modified most recently but excluding those related to the Zeitgeist project. Working with big sets of data In case you re trying to do something crazy, you may end up with a Zeitgeist query complaining that it exceeded the memory limit. You re not supposed to do that. Instead, we provide some methods for working with large collections of events.
from zeitgeist.client import ZeitgeistClient
from zeitgeist.datamodel import *
 
zeitgeist = ZeitgeistClient()
 
def on_events_received(events):
    for event in events:
        print '- %s' % event.subjects[0].uri
 
def on_ids_received(event_ids):
    print 'A total of %d source code files were found.' % len(event_ids)
    print 'Fetching the first 100...'
    zeitgeist.get_events(event_ids[:100], on_events_received)
 
tmpl = Event.new_for_values(subject_interpretation=Interpretation.SOURCE_CODE)
zeitgeist.find_event_ids_for_templates(
    [tmpl],
    on_ids_received,
    num_events=10000, # you can use 0 for "all events", but do you really need to?
    timerange=TimeRange.from_seconds_ago(3600*24*30*3),
    result_type=ResultType.MostPopularSubjects)
 
# Start a mainloop
from gi.repository import GLib
GLib.MainLoop().run()
And there you have the source code files you worked with during the last 3 months, ordered from most to least popular (popularity is measured counting the number of events; for more precision, maybe you could limit the results to events with interpretation AccessEvent). Why do we provide this mechanism instead of querying with a simple offset? Well, this avoids problems when the log changes (events are inserted or deleted). Have you ever been exploring the latest posts in some website, and as you change to the next page some of the results from the previous page show up again (because new posts have been added in the meantime)? With Zeitgeist this won t happen. Receiving information in real time At this point you re an expert at requesting all sorts of data from Zeitgeist, but now you want to show a list of the last kitten images you ve viewed, updated in real time. Don t worry, Zeitgeist can provide for this:
from zeitgeist.client import ZeitgeistClient
from zeitgeist.datamodel import *
 
zeitgeist = ZeitgeistClient()
 
def on_insert(time_range, events):
    # do awesome stuff with the events here
    print events
 
def on_delete(time_range, event_ids):
    # a previously inserted event was deleted
    print event_ids
 
templates = [Event.new_for_values(subject_uri='file:///home/user/kittens/*',
                                  subject_interpretation=Interpretation.IMAGE)]
zeitgeist.install_monitor(TimeRange.always(), templates, on_insert, on_delete)
 
# Start a mainloop
from gi.repository import GLib
GLib.MainLoop().run()
It s important to note that on_delete won t be called when an image is deleted (that d be a newly inserted event with interpretation=DELETE_EVENT); rather, it s called when a previously inserted event is deleted (for example, using the forget recent history option in Activity Log Manager). In case you re curious: for best performance, this doesn t actually use D-Bus signals. Instead, this little call will setup a D-Bus object behind the scenes and register it with the Zeitgeist engine, so it can notify said object when (and only when) an event of its interest is registered. To stop receiving notifications for a template, you ll need the save the object returned by the install_monitor call:
m = zeitgeist.install_monitor(TimeRange.always(), templates, on_insert, on_delete)
zeitgeist.remove_monitor(m)
Pro Tip: You can use the Zeitgeist Explorer GUI to quickly try out different queries (note: it s still work in progress, so much funcionality is missing, but it does work somewhat). Contextual awesomeness: finding related events By now you re familiar with retrieving events and keeping them up to date. Now it s time for a little secret:
import time
from zeitgeist.client import ZeitgeistClient
from zeitgeist.datamodel import *
 
zeitgeist = ZeitgeistClient()
 
def on_related_received(uris):
    print 'Related URIs:'
    for uri in uris:
        print ' - %s' % uri
 
query_templates = [Event.new_for_values(
    subject_interpretation=Interpretation.SOURCE_CODE,
    subject_uri='file:///home/rainct/Development/zeitgeist/*',
    subject_mimetype="text/x-vala")]
 
result_templates = [Event.new_for_values(
    subject_interpretation=Interpretation.WEBSITE,
    subject_manifestation=Manifestation.WEB_DATA_OBJECT)]
 
now = time.time()*1000
zeitgeist.find_related_uris_for_events(
    query_templates,
    on_related_received,
    time_range=TimeRange(now - 1000*3600*24*30*6, now),
    result_event_templates=result_templates,
    num_events=10)
 
# Start a mainloop
from gi.repository import GLib
GLib.MainLoop().run()
This little query example will return up to 10 websites I used at the same time as the Vala files inside my Zeitgeist directory, considering only data from the last 6 months. Nice, huh? This is an experimental feature, and it doesn t work well when operating on big inputs, so it s usually better to use the find_related_uris_for_uris variant (which replaces the first query_templates parameter with a list of URIs). Advanced searching: the FTS extension Some people think prefix searches aren t good enough for them, and this is why the Zeitgeist engine ships by default with a FTS (Full Text Search) extension. Using the methods provided by this extension you can perform more advanced queries against subjects current_uri and text properties (unlike the name may suggest, the FTS extension doesn t index the content of the files, but just the information in the event). This is exposed as zeitgeist_index_search in libzeitgeist (the C library), but unfortunately isn t currently available in the Python API. If you still need it, you ll have to fallback to pretty much using the D-Bus interface (you still get reconnection support, though). Here s an example:
from zeitgeist.client import ZeitgeistClient
from zeitgeist.datamodel import *
 
zeitgeist = ZeitgeistClient()
index = zeitgeist._iface.get_extension('Index', 'index/activity')
 
query            = 'hello' # search query
time_range       = TimeRange.always()
event_templates  = []
offset           = 0
num_events       = 10
result_type      = 100 # magic number for "relevancy" (ResultType.* also work)
 
def on_reply(events, num_estimated_matches):
    print 'Got %d out of ~%d results.' % (len(events), num_estimated_matches)
    events = map(Event, events)
    for event in events:
        print ' - %s' % event.subjects[0].uri
 
def on_error(exception):
    print 'Error from FTS:', exception
 
index.Search(query, time_range, event_templates,
             offset, num_events, result_type,
             reply_handler=on_reply, error_handler=on_error)
 
# Start a mainloop
from gi.repository import GLib
GLib.MainLoop().run()
The most interesting thing here is the query parameter. Quoting from the C documentation:
The default boolean operator is AND. Thus the query foo bar will
be interpreted as foo AND bar. To exclude a term from the result
set prepend it with a minus sign - eg foo -bar. Phrase queries
can be done by double quoting the string "foo is a bar". You can
truncate terms by appending a *.
There are a few keys you can prefix to a term or phrase to search
within a specific set of metadata. They are used like key:value.
The keys name and title search strictly within the text field of
the event subjects. The key app searches within the application
name or description that is found in the actor attribute of the
events. Lastly you can use the site key to search within the
domain name of the subject URIs.
You can also control the results with the boolean operators AND
and OR and you may use brackets, ( and ), to control the operator
precedence.
Modifying the log So far we ve only queried Zeitgeist for information, let s get a bit more active. You can delete events from Zeitgeist with the following query:
from zeitgeist.client import ZeitgeistClient
 
zeitgeist = ZeitgeistClient()
 
def on_deleted(timerange):
    print 'Deleted events going from %s to %s' % (timerange[0], timerange[1])
 
event_ids = [50] # put the IDs of the events you want to delete here
 
zeitgeist.delete_events(event_ids, on_deleted)
 
# Start a mainloop
from gi.repository import GLib
GLib.MainLoop().run()
The confirmation callback will receive a timerange going from the first to the last event. If no events were deleted (because they didn t exist), you ll get (-1, -1).
And now for the interesting part. If your application involves resources (files, websites, contacts, etc.) of any sort, you ll probably want to let Zeitgeist know that you re using them. It s time that you write a data-source! We start by registering the data-source. Here we go:
import time
from gi.repository import GLib
from zeitgeist.client import ZeitgeistClient
from zeitgeist.datamodel import *
 
zeitgeist = ZeitgeistClient()
 
def on_status_changed_callback(enabled):
    """ This method will be called whenever someone enables or disables
        the data-source. """
    if enabled:
        print 'Data-source enabled and ready to send events!'
    else:
        print 'Data-source disabled; don\'t send event, they\'ll be ignored.'
 
def register():
    # Always use the same unique_id. Name and description can change
    # freely.
    unique_id = 'com.example.your.data.source'
    name = 'user visible name (may be translated)'
    description = 'user visible description (may be translated)'
 
    # Describe what sort of events will be inserted (optional)
    subject_template = Subject()
    subject_template.interpretation = Interpretation.PLAIN_TEXT_DOCUMENT
    subject_template.manifestation = Manifestation.FILE_DATA_OBJECT
    templates = []
    for interp in (Interpretation.ACCESS_EVENT, Interpretation.LEAVE_EVENT):
        event_template = Event()
        event_template.interpretation = interp
        event_template.manifestation = Manifestation.USER_ACTIVITY
        event_template.append_subject(subject_template)
        templates.append(event_template)
 
    zeitgeist.register_data_source(unique_id, name, description, templates,
                                   on_status_changed_callback)
Once that s done (and if it is enabled), we are free to send our events:
def log(title, uri, opened):
    subject = Subject.new_for_values(
        uri=uri,
        interpretation=Interpretation.PLAIN_TEXT_DOCUMENT,
        manifestation=Manifestation.FILE_DATA_OBJECT,
        origin=GLib.path_get_dirname(uri),
        mimetype='text/plain',
        text=title)
    event = Event.new_for_values(
        timestamp=time.time()*1000,
        manifestation=Manifestation.USER_ACTIVITY,
        actor='application://your_application_name.desktop',
        subjects=[subject])
    if opened:
        event.interpretation = Interpretation.ACCESS_EVENT
    else:
        event.interpretation = Interpretation.LEAVE_EVENT
 
    def on_id_received(event_ids):
        print 'Logged %s (%d) with event id %d.' % (title, opened, event_ids[0])
 
    zeitgeist.insert_events([event], on_id_received)
 
if __name__ == '__main__':
    register()
 
    log('test.txt', 'file:///tmp/test.txt', opened=True)
    log('another_file.txt', 'file:///tmp/another_file.txt', opened=True)
    log('another_file.txt', 'file:///tmp/another_file.txt', opened=False)
    log('test.txt', 'file:///tmp/test.txt', opened=False)
 
    # Start a mainloop
    GLib.MainLoop().run()
If you don t know what interpretation and manifestation your subject should have, you can use the following utility methods:
from zeitgeist.mimetypes import *
 
print get_interpretation_for_mimetype('text/plain')
print get_manifestation_for_uri('file:///tmp/test.txt')
Event better, with Zeitgeist 0.9 you can just leave the subject (but not event!) interpretation and manifestation fields empty, and they ll be guessed the same way as if you used those utility methods. Pro Tip: You can examine all registered data-sources and toggle whether they are enabled or not using the zeitgeist-data-sources-gtk.py tool. Conclusion Wow, I m impressed if you ve got this far. By now you should have quite a good idea on how to use the Zeitgeist API, and I m looking forward to seeing what you do with it in your next awesome project. If you have any problem with Zeitgeist, feel free to visit us on IRC (#zeitgeist on irc.freenode.net), or join our mailing list. We ll also be at GUADEC next week, so if you re there make sure to say hi! In case you missed them, here are some useful links:
No comments
Siegfried-Angel Gevatter Pujals, 2012. Permalink License Post tags: ,
flattr this!

20 July 2012

Joey Hess: are there any gotchas with enabling the -threaded GHC runtime?

That's a seemingly simple question I started asking various people two weeks ago. I didn't get many useful answers, but now I have experience doing it myself, and so here's a blog post brain dump. I have been trying to convert git-annex to use GHC's threaded runtime, for a variety of reasons. Naively adding the -threaded option resulted in a git-annex command that seemed to randomly freeze, but only sometimes (and, infuriatingly, never when I straced it), and a test suite that froze at a random point almost every time I ran it. Not a good result, and lacking any knowledge about gotchas with using the threaded runtime, I was at a loss for a long time (most of DebConf) about how to fix it. I now know of at least three classes of problems that enabling the threaded runtime can turn up in programs that have been developed using the non-threaded runtime. accessing a MVar after forkprocess can hang MissingH has some code similar to this, which works ok with the non-threaded runtime:
forkProcess $ do
    debugM "about to run some command"
    executeFile ...
In the above example, debugM accesses a MVar. Doing that after forkProcess can result in a MVar deadlock, as it tries to access a MVar value, that is, apparently, not accessible to the forked process. (Bug report with test case) So, using System.Cmd.Utils from MissingH is asking for trouble. I switched all my code to the newer and, apparently, threaded runtime safe System.Process. forkProcess is a massively bad idea Even when not accessing a MVar after forkProcess, it's very unsafe to use. It's easy to miss the warning attached to forkProcess, when the code seems to work. But with the threaded runtime, I've found that most any call to forkProcess will sometimes succeed, and sometimes freeze the whole program. This might only happen around 1 time in 1000. Then you'll find this warning and do a lot of head-scratching about what it really means:
forkProcess comes with a giant warning: since any other running threads are not copied into the child process, it's easy to go wrong: e.g. by accessing some shared resource that was held by another thread in the parent.
The hangs I saw could be due to laziness issues deferring code to run after the forkProcess that you'd expect to have run before it ... or who knows what else. It's not clear to me that it's possible to use forkProcess safely in Haskell code. I think it's notable that System.Process runs the whole fork/exec in C code instead. unsafe FFI calls block According to most of the documentation you'll find in eg, the Haskell wiki, Real World Haskell, etc, the only difference between the safe and unsafe imports in the FFI is that unsafe is faster, and shouldn't be used for C code that calls back into Haskell code. But the documentation is out of date. Actually, if you're using the FFI, and the foreign function can block, you need to use safe. When using unsafe, a blocking foreign function can block all threads of the program. In my case, I was using kqueue to wait for changes to files, and this indeed blocked my whole program when linked with -threaded. Marking it safe fixed this. The details are well described in this paper: http://community.haskell.org/~simonmar/papers/conc-ffi.pdf Somewhat surprisingly, this blocking only happens when using the threaded runtime. If you're using the non-threaded runtime with unsafe blocking FFI functions, your other pseudo-threads won't be blocked. This is because the non-threaded runtime has an SIGALARM timer that interrupts (most) blocking system calls. This leads to other troubles of its own (like needing to restart interrupted FFI functions, or blocking the other pseudo-threads from running if the C code ignores SIGALARM), but that's offtopic for this post. summary Converting a large Haskell code base from the default, non-threaded runtime to the threaded runtime can be quite tricky. None of the problems are the sort of thing that Haskell helps to manage either. I will be developing new programs using the threaded runtime from the beginning from now on. By the way, don't take this post to say that threading in Haskell sucks. I've really been enjoying writing threaded Haskell code. The control Haskell gives over isolation of state to threads, and the excellent and wide-ranging suite of thread communications data types (MVar, Chan, QSemN, TMVar, SampleVar, etc) have made developing a complex threaded program something I feel comfortable doing for the first time, in any language.

David Paleino: Editable QComboBox with QAbstractTableModel

Dear Lazyweb, I'm working on a personal PyQt4 project for my parents' office, and I need to autocomplete an editable QComboBox. I can't use a standard Qt model (I need to store python objects in it), so I subclassed QAbstractTableModel. Here it is, it's a fairly generic subclass of QAbstractTableModel, with variable number of columns:
class QGenericTableModel(QAbstractTableModel):
    def __init__(self, columns, parent=None, *args):
        super(QGenericTableModel, self).__init__(parent, *args)
        self.columns = columns
        self.headers =  
        self.table = []
    def rowCount(self, parent=QModelIndex()):
        return len(self.table)
    def columnCount(self, parent):
        return self.columns
    def row(self, row):
        return self.table[row]
    def setData(self, index, value, role):
        if index.isValid() and role == Qt.EditRole:
            row = index.row()
            t = self.table[row]
            if index.column() >= self.columns:
                return False
            if isinstance(value, QVariant):
                t[index.column()] = value.toString().simplified()
            else:
                t[index.column()] = value
            self.emit(SIGNAL('dataChanged'), index, index)
            return True
        return False
    def data(self, index, role = Qt.DisplayRole):
        if not index.isValid():
            return QVariant()
        if (index.row() >= len(self.table)) or (index.row() < 0):
            return QVariant()
        if role == Qt.DisplayRole:
            return QVariant(self.table[index.row()][index.column()])
        return QVariant()
    def insertRow(self, row, parent=QModelIndex()):
        self.insertRows(row, 1, parent)
    def insertRows(self, row, count, parent=QModelIndex()):
        self.beginInsertRows(parent, row, row+count-1)
        for i in xrange(count):
            self.table.insert(row, ['',]*self.columns)
        self.endInsertRows()
        return True
    def removeRow(self, row, parent=QModelIndex()):
        self.removeRows(row, 1, parent)
    def removeRows(self, row, count, parent=QModelIndex()):
        self.beginRemoveRows(parent, row, row+count-1)
        for i in reversed(xrange(count)):
            self.table.pop(row+i)
        self.endRemoveRows()
        return True
    def flags(self, index):
        if not index.isValid():
            return Qt.ItemIsEnabled
        return super(QGenericTableModel, self).flags(index)   Qt.ItemIsEditable
    def headerData(self, column, orientation, role = Qt.DisplayRole):
        if role != Qt.DisplayRole:
            return QVariant()
        if orientation == Qt.Horizontal:
            if column >= self.columns:
                return QVariant()
            return self.headers[column]
        return QVariant()
    def setHeaderData(self, column, orientation, value, role = Qt.EditRole):
        self.headers[column] = value
It might not be perfect, but it works, and it's all that matters at the moment (since it's my first serious PyQt4 project). Oh, well, it worked until I tried to use it with an editable QComboBox. And here's the app code (for the full working code, insert the above class right after the imports):
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
app = QApplication(sys.argv)
model = QStandardItemModel()
for i, word in enumerate(['saluton', 'gxis la revido', 'hello', 'goodbye']):
    item = QStandardItem(word)
    model.setItem(i, 0, item)
#model = QGenericTableModel(1)
#for i, word in enumerate(['saluton', 'gxis la revido', 'hello', 'goodbye']):
#    model.insertRow(i)
#    index = model.index(i, 0)
#    model.setData(index, word, Qt.EditRole)
combo = QComboBox()
filterModel = QSortFilterProxyModel(combo)
completer = QCompleter(combo)
filterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
filterModel.setSourceModel(model)
filterModel.setFilterKeyColumn(0)
completer.setModel(filterModel)
completer.setCompletionColumn(0)
completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
combo.setEditable(True)
combo.setCompleter(completer)
combo.setModel(model)
combo.setModelColumn(0)
if combo.isEditable():
    app.connect(combo.lineEdit(), SIGNAL('textEdited(QString)'), filterModel.setFilterFixedString)
combo.setModel(model)
combo.setModelColumn(0)
combo.show()
sys.exit(app.exec_())
Now, try running it. It works well when I use a QStandardItemModel. Then, try decommenting the part where I use my subclassed model: it just doesn't work: clicking on any item makes the QComboBox not change its currentIndex, and this only happens if the combobox is editable. I suspect I'm forgetting to override some function in my model, but I don't know what exactly to override, and Google didn't help me. This is also backed up by the fact that the exact same behaviour shows up when, instead of a QComboBox, I try to autocomplete on a QLineEdit. So, dear readers: can anyone explain what is happening? Thanks in advance! UPDATE: it turned out that the culprit was the following bit inside data():
        if role == Qt.DisplayRole:
            return QVariant(self.table[index.row()][index.column()])
Adding also Qt.EditRole to the list of possible choices fixed the bug. YAY!

Neil McGovern: DebConf 2012 Nicaragua

After 4 flights, about 15,000 miles, a beach, some To a and cheese and lots of geeks, I'm able to update my Places I've Been map by adding Nicaragua to it. I was speaking at DebConf12, entitled Bits from the Release Team. In case you missed it, it's been recorded by the wonderful DebConf video team and is available in high and low quality. It was great to catch up with people again, and do quite a bit of work on Debian itself, mostly on the Wheezy release. I even found an hour to take a basic Spanish class, although I'm fairly sure I've forgotten most of it by now. As usual, there were a number of Collaborans present, and it was good to meet them. I suspect I'll be seeing a few more at GUADEC in a weeks time. My photos are available, should anyone be interested.

John Goerzen: A Linux-Based RFID Thing Finder

Sometimes I have things nicely organized. Power adapters for radios in one drawer, for cameras in the next. And sometimes not so much. Sometimes I m not sure if things are in the basement or the attic. It seems like technology should be able to help solve this problem, but as far as I can tell, no such solution exists yet. So I m planning to build one. Here s my general idea. Feedback, of course, is welcome. Each item to be tracked can have an RFID tag of some sort attached to it. These tags can be read by an RFID reader at a distance of somewhere between 1ft and 1m in typical conditions. The reader could then act as a proximity alert to an object being searched for a you re close beep, for instance. That helps, but is only part of the battle. It doesn t help if you don t even know which room to look in. So the second part of the plan is that the RFID reader is constantly talking to an object database. Besides the obvious association between RFID tag IDs and object descriptions, the database will also capture background reads of RFID tags. Logged with accurate timestamps, we can then conjecture that RFID reads that occurred within a few seconds of each other are probably physically nearby. If boxes have RFID tags on them, then I can probably get a reasonable idea, down to a box or two, of which box that elusive book is in. If I further put tags on certain immovable physical locations in the house, such as every few feet along shelving, then these will also be captured in the background and hopefully associated with objects nearby, giving a good physical idea of where things are. What s more, the simple act of looking for things using the RFID reader would help keep the proximity tables up-to-date, since it could of course log the RFID tags it sees on the way. The only discipline required to keep this info current is to periodically hover nearby storage areas when moving things around. I like this concept a lot. That doesn t mean it s necessarily simple. Implementation requirements Software side I m envisioning the software being split into two components. One would run on an embedded system with the RFID reader. Its job is simple transmitting of scanned RFIDs to the server, receiving instructions from the server, and generating a tone if it s in search mode and the item being searched is nearby. On the server lies a database. The database would contain descriptions for the objects that are tagged (so that the tag ID can be looked up). It would also contain the timestamped scan logs. I envision a simple CGI-based frontend to it that is mobile-friendly, so a laptop, phone, tablet, etc. could be the user interface for the thing saving the cost of a display and input device by reusing what most people already have. This is the part I feel most qualified to work on already. Hardware The first question is what kind of RFID tags to use. Optimizing for cost per tag, the 800/900MHz UHF tags (EPC gen 2) seem ideal. I have found them in costs approaching $0.10 per tag when bought in rolls of 500 or 1000 Avery RFID labels. That s reasonable. The RFID reader is the more complicated part. UHF RFID readers are a lot more costly than their HF or LF counterparts. So far, the cheapest solution I have found started with a post about an Arduino UHF reader. It used a SolidDigi UHF reader board with UART interface for $177. That same board is also available with a USB interface at the same cost. There is also the need for an antenna. There is a small 5dBi one rated 0-50cm for $8, or a $100 8dBi version rated 1-6m designed for wall mounting. They sell these in kit form that include power adapter, USB cables, etc. as well. The kit with the small antenna runs $192, including reader board. Next is the compute platform. A DreamPlug might work for this at $160, though both the cost and the power consumption (5VDC 3A) are high. A Raspberry Pi seems perfect, though for whatever reason seem to be backordered by months everywhere and don t include wifi. The Pi is $35, and the USB wifi is another $30, plus a cheap SD card, so we re around $80 of computing. The running total of the project, then, is at least $272. Add on provisions for batteries, some sort of case, etc. and we re probably past the $300 mark. That s a lot cheaper than the $1000 for handheld RFID readers. The final item is tags. Bulk tags can be found in the $100 to $200 range, making the total cost of the project $400 to $500. Higher than I d like, but providing some valuable experience building something. Risks There are a few major risks to the project. First among them is read distance. If it s not long enough, the usefulness of the project will be low. Fortunately, $100 gets a more high-gain antenna and I d only be out the $8 if the cheaper one doesn t pan out. But that s something of a cold comfort, as it s another, well, $100. Having a bunch of RFID hardware can be used for all sorts of other interesting things, though, so it could perhaps be reused or repurposed. Another risk is that RFID collisions wouldn t be handled as intelligently as I d like, meaning that the read range required to be useful would activate so many tags that collision algorithms break down. I don t know enough about RFID collision algorithms to know if this is a serious councern.

Jamie McClelland: Killing MySQL

MySQL is supposed to allow one + the max_connections from a super user so you can stop/restartmysql even when it is reporting too many connections. Unfortunately, for reasons I'm not entirely sure of, sometimes that connection seems to be in use. I've encountered this problem with web apps and now follow these steps:

Jamie McClelland: MySQL throwing the wrong error

I was running a routine CiviCRM installation when I was stopped by the error:
ERROR 1071 (42000) at line 2415: Specified key was too long; max key length is 1000 bytes
The line referred to a table that created two indexes. Each index combined a 512 byte varchar field with a 4 byte integer field (well below 1000 bytes). I then tried downloading the sql file to my local computer and it imported without a problem. So... I started the painstaking process of comparing the configurations on each computer. Eventually, I came to this setting that was causing the problem:
innodb_log_file_size = 268440000
In fact, it wasn't the setting causing the error. The error was caused because I added that setting without properly shutting down MySQL, removing /var/lib/mysql/iblogfile0 and /var/lib/mysql/iblogfile1 files and then restarting MySQL.

19 July 2012

Sylvestre Ledru: Interview in FLOSS for Science

A couple weeks ago, I have been interviewed by the news site "Free Libre open source software for science and engineering" about Scilab and my work in Scilab Enterprises.
I am happy to share it:
http://www.floss4science.com/scilab-an-interview-with-sylvestre-ledru/.

Andreas Metzler: Correcting Exif image orientation tags

Panasonic's G1, G2 and G3 micro four-thirds cameras are missing a dedicated orientation sensor. With a lens featuring image stabilisation the camera makes use of its sensor. Otherwise (e.g. with the Panasonic Lumix 20mm/1.7) the Exif image orientation tags are not correct for portrait format images. Here is how to write correct tags (compatible with the camera's preview function) with exiv2: Camera rotated anti-clockwise (shutter button on top):
exiv2 -k -M"set Exif.Image.Orientation 8" -M"set Exif.Panasonic.Rotation 8" -M"set Exif.Thumbnail.Orientation 8" P1020800.JPG Camera rotated clockwise (shutter button at bottom):
exiv2 -k -M"set Exif.Image.Orientation 6" -M"set Exif.Panasonic.Rotation 6" -M"set Exif.Thumbnail.Orientation 6" P1020800.JPG

Michal &#268;iha&#345;: Sponsoring phpMyAdmin

We've decided to accept sponsorships of phpMyAdmin in more official way. So if you or your company want to financially support this software, you now have great chance to do that. Time to time we've received offers for sponsoring, but we never got to point where we could easily handle these. In the past we were limited by sf.net requirements for no advertisement on website, but it got leveraged over the time and we did not change our policy much. For now the only benefit we are providing to our sponsors (besides good feeling that they are supporting good project) is logo and link on our website. In the future we might add some more, but at first we want to see how it works in this scale. Anyway if you are interested in sponsoring phpMyAdmin, you can do that on our website.

Filed under: English Phpmyadmin 0 comments Flattr this!

18 July 2012

Niels Thykier: Lintian-NG Accessing Lintian s collection data with 90 lines

 $ LINTIAN_ROOT=. perl lintian-ng ../lintian_2.5.10.dsc
 Successfully unpacked 1 packages
 Did you know that source:lintian/2.5.10 contains 3745 files or/and directories (excl. root dir)
 This useless information was brought to you by Lintian-NG
 $ git describe
 2.5.10-61-g7670427
 $ wc -l lintian-ng
 90 lintian-ng
This includes everything from creating a temporary lab, adding the packages to it and running all of Lintian s collections on it (parallelised, of cource). Writing this script yesterday would probably have required 250-300 lines of code to achieve the same. That said, 90 lines are still a bit much to copy/waste into this blog, so I won t do a $ cat lintian-ng . :) If you are interested in how it looks you can (for now) fetch it from http://people.debian.org/~nthykier/lintian-ng/lintian-ng Oh yeah, files or/and directories is actually any (extractable) entry in the tarball

Jon Dowland: Debian Day #3

Once again Debian day was somewhat compromised: this time by more DIY. I still managed a few bits and pieces, amortized over the rest of the week. I benefited from some train time this weekend. A new version of flactag and catching up the flactag packaging vcs repository. A maintainer endorsement for one of the flactag maintainers and a request to NM for another maintainer to be granted access to the collab-maint repository. More work on the musicbrainz 'transition': First, usertag tracking of packages to update, with upstream bugs where necessary. Tested and confirmed Michael Biebl's sushi patch; found and fixed a sushi bug along the way; wrote patches for sound-juicer ( merged upstream) and goobox.

Jon Dowland: Debian Days 4, 5 and 6 (round-up)

And we've frozen! How have we done on the musicbrainz stuff? I was really pleased to see Michael Biebl upload new sound-juicer (four bugs closed!), rhythmbox and gnome-sushi packages which move them up to musicbrainz5. I NMUed goobox (with the maintainer's permission) but sadly there was a build issue and the NMU was reversed with a second upload, so it's back to using libmusicbrainz3 in the freeze. that leaves two more packages. I haven't discussed or considered putting forward this 'transition' for freeze exceptions, but Pino Toscano raised a good point: upstream might not support the version 1 WS API (which libmusicbrainz3 depends on) throughout the wheezy lifetime. Some more research here is needed. What else? NMU of acpidump to resolve a trivial manpage error that I filed a patch for two years ago; the latest flactag upstream version; a new version of game-data-packager, incorporating stuff Joey Schmit patched last year, which fixes Heretic support and adds Hexen support; a new version of chocolate-doom. The last two are particularly interesting because I'm in Uploaders: despite having left the Games team last year: there have been no subsequent uploads before my latest ones. I removed myself from Uploaders: with these uploads, which technically means they are NMUs. What next? Typically I find the freeze time a hard one to work on Debian. I've never been very effective at chasing and resolving RC bugs. On the other hand, long, protracted freezes are demotivational for everyone. I'm going to try and focus on goals which hasten the release of wheezy and resist the urge to work on things that would not show up until wheezy+1.

Next.

Previous.