Python interface for librioutil

  • Emmanuel

    I'm working on a Python interface for librioutil. I've never done anything like this before, but it's coming along. I started doing this because I wanted to code a GUI using python/gtk2/glade. At first, I used the rioutil binary and parsed the output, but then I decided to try this exiting method. Basically it consists of a C Python extension module. All you do is load it and assuming permissions in /proc/bus/usb are adequate, you can run the functions in librioutil. All I've got so far is the open_rio() and it's not done yet because I'm still finishing up the data structures (rios_t, etc). Here's some example code of usage:

    #!/usr/bin/env python
    from librioutil import *
    import types
    def print_dic(dic):
            for key in dic:
                    if type(dic[key]) is types.DictType:
                            print key, "[]"
                            print key, "=", dic[key]
    rios_t = open_rio(0, 0, 1);

    The output looks like this:
    info []

    treble = 7
    version = 1.55999994278
    playlist = 0
    bass = 7
    eq_state = 2
    repeat_state = 0
    sleep_time = 1
    volume = 2
    random_state = 0
    total_memory_units = 1
    memory []

    total_time = 4627
    num_files = 19
    name = Internal Flash Memory
    free = 294912
    size = 67108864

    light_state = 3
    contrast = 4
    name = Rio 600

    debug = 0
    abort = 0
    lock = 0

    I think Id rather do this and have somene else write the actual GUI. What do you think?

    • Emmanuel

      I've made some changes, I call the extension pyrioutil instead of just librioutil. I've finished the functions that convert the C structures to Python equivalents. So You can gather just about all the data you can get out of rioutil. The only library function I've got implemented is open_rio() which returns a nest of dictionaries which resemble the structures in the library. I think you can access both memory units, but I can't test this since I only have one. Once I complete the Python-to-C conversion functions, I should be able to code the rest of the library functions. Here's sample code on how to list the files in the Rio (sorry, the tabs may missing):
      #!/usr/bin/env python

      import sys

      from pyrioutil import *

      def print_files(files):
              print "    Title: %s" % files["title"]
              print "    Artist: %s" % files["artist"]
              print "    Album: %s" % files["album"]
              print "    Length: %s sec" % files["time"]
              print "    Filename: %s" % files["name"]

              if(len(files["next"]) != 0):

      def memory_dump(rio):
              memory = rio["info"]["memory"]

              for mem_unit in memory:
                      print "Memory unit: %s." % mem_unit["name"]
                      print "  Number of files: %i" % mem_unit["num_files"]
                      print "  Size: %i" % mem_unit["size"]
                      print "  Free memory: %i" % mem_unit["free"]
                      print "  Total time: %i" % mem_unit["total_time"]
                      print "  Memory contents:"
      print "Opening rio..."
      rios_t = open_rio(0, 0, 1);
      Since I'm trying to code a thin layer above librioutil, I haven't created classes to make these functions easier to use. That could be a seperate pure-python module. Here's what the snippet output would look like (sort of):
      Opening rio...
      cannot open /proc/bus/usb/004/001, Permission denied (13)
      Memory unit: Internal Flash Memory.
        Number of files: 19
        Size: 67108864
        Free memory: 294912
        Total time: 4627

        Memory contents:
          Length: 0 sec
          Filename: preferences.bin

          Title: Dont Let It En
          Artist: Sty
          Album: Greatest Hit
          Length: 294 sec
          Filename: styx-greatest_hits-dont_let_it_end.mp3

          Title: Lady '9
          Artist: Sty
          Album: Greatest Hit
          Length: 186 sec
          Filename: styx-greatest_hits-lady_95.mp3

          Title: Lorele
          Artist: Sty
          Album: Greatest Hit
          Length: 202 sec
          Filename: styx-greatest_hits-lorelei.mp3
      Note: The missing character at the end of the the text is not my fault. For some reason they got stored like that. Oh, did you know hotplug can be used to correct the permission on the rio node within /proc/bus/usb? No more sticky rioutil of having to adjust it manually since the 'devgid' argument to usbfs get ignored :)

    • Nathan Hjelm
      Nathan Hjelm

      The missing character is my bad ;). I don't like id3lib so I wrote my own parser for id3v1/v2 tags. Anyway, there is a bug in the version with 1.4.4 which cuts off the last character sometimes :D.

      Will be fixed in the next version.

      • Emmanuel

        Ok, it's good to know where the missing character came from cause I thought it was Sound Juicer. I don't blame you for disliking id3lib, I've tried to use it once. Would you consider making you id3 tag parser a small seperate project? Maybe it could be used by other applications as an alternative. Oh, about rioutil, is it possible to move the code that prints "cannot open /proc/bus/usb/004/001, Permission denied (13)" out of the library and into main.c or something? Please don't take this the wrong way, let me explain. Looking at it as a library instead of an application, consider an ncurses app that uses librioutil. As the application scans for the rio, these permission messages can cover up the screen, destroying the user interface. Although this is not really a concern for a GUI app, my point is, unless debugging is specified, I think a library should not print messages to the console. The app is the one that should relay this info to the end user. Again, I don't have anything against rioutil :)

    • Emmanuel

      I have to admit, pyrioutil has been using the same disk blocks for a while. But so far, I created a Rio class. This class sits on top of the librioutil bindings. That way, apps can access a rio like this:
      import rio # I need to change this to
      r = rio.Rio()
      print r.getName()
      # and so on.

      It's quite easy to scroll through the files/tracks on the rio using the class. All you do is set the memory unit (the default is 0 - internal), and then loop through it like you would a dictionary:

      from rio import Rio
      rio = Rio()
      rio.setMemUnit(0) # Not really needed in this example.
      for file in rio:
           print file['title'], file['artist']

      I'm also working on a Python/GTK2 (with glade) interface.