Marco Islas Blog Python http://islascruz.org/html/ markuz@islascruz.org (Marco Antonio Islas Cruz) 2005-2008, Marco Antonio Islas Cruz Thu, 17 Jun 2010 03:28:01 -0500 JAWS 0.8.9 <![CDATA[ Have you ever had that feeling when you're not sure if you're awake or still dreaming? ]]> It's called #python - it's the only way to fly. ]]> http://islascruz.org/html/index.php/blog/show/Have-you-ever-had-that-feeling-when-you%27re-not-sure-if-you%27re-awake-or-still-dreaming%3F.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Have-you-ever-had-that-feeling-when-you%27re-not-sure-if-you%27re-awake-or-still-dreaming%3F.html Thu, 17 Jun 2010 03:19:56 -0500 <![CDATA[ Opening files from nautilus ]]>

Christine Dbus from Marco Antonio on Vimeo.


The trick is this, set nautilus to open files with christine, if christine si already opened, when nautilus launch christine and pass the file as argument christine will detect via dbus de running instance of christine, then, will send via dbus the name of the file to open :-). ]]>
http://islascruz.org/html/index.php/blog/show/Opening-files-fro-nautilus.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Opening-files-fro-nautilus.html Thu, 03 Jun 2010 12:13:08 -0500
<![CDATA[ Christine 0.7.0 Beta1 released ]]>
Christine running on win32

Just to let you know that Christine 0.7.0 Beta 1 has been released. This release include several improvements over Christine 0.6.1 and fixes some problems with the win32 build. The full you can read the full changelog Here.

You can download christine from Here

Remember, this is a beta, and many bugs are still there, tests and bug reports are very very appreciated

Update:

  • Win32 binaries are available Here
  • Ubuntu package is almost done, you can use this ppa
]]>
http://islascruz.org/html/index.php/blog/show/Christine-0.7.0-Beta1-released.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine-0.7.0-Beta1-released.html Mon, 31 May 2010 16:08:56 -0500
<![CDATA[ Compressed XMLRPC on python ]]> This post is about something I did on ICTC, we are developing some applications that communicate with each others on over the network and we thought on compressed XMLRPC. I have been looking about this on Google, but didn't really found something. So, I try by myself and this is the result.

First, allow me to explain a bit more about xmlrpc. XMLRPC is nothing more than a remote call using the HTTP protocol the POST method and XML as content, then, the server do its work and return something in the same way. THen the client parses this xml and create the result in a native way. Just like if that method where in your program. This offer a language independece (the server may be written in some language and several clients in many other languages).

Then, implementing compressed xml should not be that difficult, I mean.. HTTP support the "Accept-Encoding" header and that should do the job. But hey... xmlrpclib does not include gzip support, so, we are going to do it.

The server part should subclass SimpleXMLRPCServer and in the constructor we are going to create a inner class that will be a request Handler, this handler is based on SimpleXMLRCPRequestHandler and implements the do_POST method, this method is called everytime something is sent to the server (on every call).

In do_POST method we are responsible for fetching the data, decompress it, parse it, handle the response and then send the reply to the client. This isn't so hard (check the code). The important part here is that we check for the "accept-encoding" header and that the vale of that header (if exists) is "gzip", if this is true then use zlib to decompress the data and when we have the result of the call, compress it using zlib and send it to the client.

def do_POST(self):
        if self.headers.has_key('accept-encoding') and \
                        self.headers['accept-encoding'] == 'gzip':
                # check if the path ir right
                if not self.is_rpc_path_valid():
                        self.report_404()
                        return
                try: #Try to get the data
                        max_chunk_size = 10*1024*1024
                        size_remaining = int(self.headers["content-length"])
                        L = []
                        while size_remaining>0:
                                chunk_size = min(size_remaining, max_chunk_size)
                                L.append(self.rfile.read(chunk_size))
                                size_remaining -= len(L[-1])
                        data = ''.join(L)
                        data = zlib.decompress(data) #Decompress
                        response = self.server._marshaled_dispatch(
                                        data, getattr(self, '_dispatch', None)
                                        )
                except:
                        #Should be good to registre the exception somewhere
                        pass
                else:
                        #We have an answer...
                        #Let's compress it
                        response = zlib.compress(response)
                        self.send_response(200)
                        self.send_header("Content-type", "text/xml")
                        self.send_header("Content-length", str(len(response)))
                        #As the call was compressed, then we compress the
                        #Answer too. Be sure to set the compressed header.
                        self.send_header("Accept-Encoding","gzip")
                        self.end_headers()
                        self.wfile.write(response)
                        #Close the connection
                        self.wfile.flush()
                        self.connection.shutdown(1)
        else:
                return SimpleXMLRPCRequestHandler.do_POST(self)
 

This take us the the other part of the call, the client. The client must implement gzip compression too. The client part is a bit simplier, you just have to subclass xmlrpclib's Transport and and in the "request" method compress the request_body before sending it. Obviously you have to append the "accept-encoding" header to the http connection. Once you have the result you have to check for the "accept-encoding" header too, if it is there, decompress using zlib's methods.

def request(self, host, handler, request_body, verbose=0):
        '''
        Encargado de manejar los request, envia los datos y recibe
        las repuestas, por lo que aqui se hace la compresion de datos
        y posteriormente se envian los datos recibidos a
        la funcion self._parse_response o self._parse_gzipped_response
        de acuerdo al caso.
        Mas informacion:
        http://docs.python.org/library/xmlrpclib.html
        '
''
        h = self.make_connection(host)
        if verbose:
                h.set_debuglevel(1)
        self.send_request(h, handler, request_body)
        self.send_host(h, host)
        self.send_user_agent(h)
        #Compress if GZIP_ENCODED is true
        if GZIP_ENCODED:
                #Don't forget to set the header!
                h.putheader('Accept-Encoding','gzip')
                request_body = zlib.compress(request_body)
        self.send_content(h, request_body)
       
        errcode, errmsg, headers = h.getreply()
        if errcode != 200:
                raise ProtocolError(
                                host + handler,
                                errcode, errmsg,
                                headers
                                )
        self.verbose = verbose
        try:
                sock = h._conn.sock
        except AttributeError:
                sock = None
        # Revisar si la respuesta incluye los encabezados de
        # compresion y si este es gzip
        if headers.has_key('accept-encoding') and \
                        headers['accept-encoding'] == 'gzip':
                return self._parse_gzipped_response(h.getfile(), sock)
        return self._parse_response(h.getfile(), sock)
 
The whole code and a small example is here: ictcxmlrpc.tar.bz2 ]]>
http://islascruz.org/html/index.php/blog/show/Compressed-XMLRPC-on-python.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Compressed-XMLRPC-on-python.html Thu, 06 May 2010 14:30:14 -0500
<![CDATA[ Python MySQldb little trick ]]> MySQLdb has a way to set the charset for the connection but it is useless if you are using MySQL prior to 4.1. If you are having problems with this, then try doing this:
import MySQLdb
import sys
reload(sys)
sys.setdefaultencoding('latin-1')
 
Replace "latin-1" with your desired encoding and try it. ]]>
http://islascruz.org/html/index.php/blog/show/Python-MySQldb-little-trick.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Python-MySQldb-little-trick.html Fri, 05 Mar 2010 16:02:40 -0600
<![CDATA[ Playing with Nokia S60. ]]>


Me :-)

Originally uploaded by markuz



I've just started playing with Nokia S60v5. I'm currently using Python to develop some learning stuff. Remember, Symbian is now Open Source, a little bit late, but Open Source at the end.

]]>
http://islascruz.org/html/index.php/blog/show/Playing-with-Nokia-S60..html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Playing-with-Nokia-S60..html Mon, 08 Feb 2010 00:41:25 -0600
<![CDATA[ Right now ]]>


Right now

Originally uploaded by markuz



3:20 in the morning and I'm working, I need to finish a program that I wrote almost a year ago, that was a Demo program and in 4 days (right now just 2) should be production ready!... I'm gonna need a double Monster dosis.

]]>
http://islascruz.org/html/index.php/blog/show/Right-now.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Right-now.html Sat, 30 Jan 2010 04:29:48 -0600
<![CDATA[ Monster ]]>


Monster

Originally uploaded by markuz



Working :-)

]]>
http://islascruz.org/html/index.php/blog/show/Monster.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Monster.html Fri, 29 Jan 2010 13:08:55 -0600
<![CDATA[ Christine 0.6.1 ]]>
  • http://sourceforge.net/projects/christine/files/christine/0.6.1/christine-0.6.1.tar.bz2
  • http://sourceforge.net/projects/christine/files/christine/0.6.1/christine-0.6.1.tar.gz
  • Binary Packages
    • Ubuntu: https://launchpad.net/~markuz/+archive/ppa (if you already set the ppa in your apt sources list then wait for the update soon :-))
    • Windows: http://sourceforge.net/projects/christine/files/christine/0.6.1/Christine-0.6.1.exe ]]> http://islascruz.org/html/index.php/blog/show/Christine-0.6.1.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine-0.6.1.html Wed, 13 Jan 2010 22:01:02 -0600 <![CDATA[ Christine update for December 01 ]]> Tonight I have been working on Christine, in the GUI, IMO a media player that work fine should also look good and sometimes GTK just don't fit on that, why? it is because GTK is a general purpose graphical toolkit and everything is general, I wish GTK has some more widget options (like more buttons that fit a specific function, like those small rounded with a simple question sign help buttons)

      christine buttonsFortunately, you can write your own widgets and make them look as you want. Tonight I have been working on Christine's new buttons, just for the Previous, Play/Pause, Next. Creating custom buttons is not a complicated task, just subclass gtk.Button and connect your button "expose-event" signal to a custom function, remember at the end of this function return "True" in order to stop the signal emition. If you don't do this the gtk.Button will do its task and will redraw the button.


      Christine

      As usual, you can check out the source code from the svn

      ]]>
      http://islascruz.org/html/index.php/blog/show/Christine-update-for-December-01.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine-update-for-December-01.html Tue, 01 Dec 2009 07:29:36 -0600
      <![CDATA[ Python trick: How to make lazy objects? ]]> This time I'm about to talk about lazy object, I called like that because they are more or less similar to what we use in lazy treeviews (In Gtk) where the Tree shows expanders but didn't load the child nodes until you expand the node). What I want to do is create objects and count them, but don't load any data until I need it.

      Why would I need this?. Well. I'm currently writing a program for my employer, this program load a list of customers and shows how many accounts it has. As this accounts are kind of complex I create an object for them. This object is responsible for load/save the data for it, and any data you need is accessed via properties.

      In my first approach, the object was loading the data as soon as the constructor was called, but sometimes I never access to any info in that object, remember, a customer may have many (and I mean really many) accounts, then why load all the data if there is a chance that I'll never use it?. Well, that is because there is a chance that I have to use that data.

      Then how could I create the object and then load the data when somebody require it?. That may be easy, may not. :-). One approach is making use of python properties. Just create the object and when someone want to use a "value" from the object use the property to retrieve the data, process it and then return a value. A simple property may be defined like this:

      class demo(object):
          def get_some_property(self):
              #Here you can make use of whatever you want to retrieve the data
              pass
          def set_some_property(self, value):
              #Here you get a value and save it.
              pass
          some_property = property(get_some_property, set_some_property, None, 'Doc')
       

      I just create a class "demo" and the property "some_property", everytime you use this:

      d = demo()
      d.some_property
       

      Python will call the method get_some_property allowing you to do your trick. But if you have an object with more and more properties is better to get all data at one time and then just use properties to return a piece of it. You could call a method on every property if the data container is empty but for me it is not the best.

      What you could do, is get the data the first time you need it. But, how could I know when a property/variable is requested on my object?

      Well, Python classes have several reserved methods, and one of them is __getattribute__. This method let you handle every request to any property/class variable in your object.

      With this you can digg in your object to know if the container is empty, and if it is empty fill it with data before returning the property value :-).

      Lets say that the demo object have a __data dictionary containing the data. and propeties look into it for the right value, it also have a reference to the storage layer called storage.

      class demo(object):
              def __init__(self):
                      self.__data = {}
                      self.storage = storage()
              def __getattribute__(self, name):
                      obj = object.__getattribute__(self,name)
                      #Check if the requested property is __data
                      if name in("__data", '_account__data'):
                              #Get the reference of __data
                              d = object.__getattribute__(self,'_account__data')
                              if not d: #Get in only if __data is empty.
                                      #Get your
                                      s = object.__getattribute__(self,'storage')
                                      #We can assign without using object.__getattribute__
                                      self.__data = s.get_data()
                                      #Get the value again
                                      obj = object.__getattribute__(self,name)
                      return obj
       

      Pay attention that I used object.__getattribute__ instead self.property, if I use self.property will call self.__getattribute__ and will cause a recursion exception.

      With this, we can create a great number of objects quickly and reducing the memory footprint.

      ]]>
      http://islascruz.org/html/index.php/blog/show/Python-trick%3A-How-to-make-lazy-objects%3F.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Python-trick%3A-How-to-make-lazy-objects%3F.html Sun, 22 Nov 2009 05:00:41 -0600
      <![CDATA[ Christine 0.6.0-pre1: first win32 build ]]>
      Christine on Win32

      This night I have been working on the Win32 build of christine. It seems to be working fine. This version is just a test, for those that wanted to use christine on Microsoft Windows.

      Altough that I have made some tests on a clean Windows XP installation cannot guarantee that the Win32 will work on your computer.

      Anyway, if you are brave enough, download the win32 binary and report any bug you found on it.

      If you want to compile it, you will need this:

      • Python 2.6 (I built Christine with it, but python >= 2.5 should work too)
      • Gstreamer Winbuild (http://www.gstreamer-winbuild.ylatuya.es/doku.php)
      • Microsoft Visual C++
      • py2exe (http://py2exe.org/)

      The build script is in win32resources/christine_setup.py, just copy it to the source root and run python christine_setup.py -q py2exe to build it.

      You can download the win32 binary from here: http://downloads.sourceforge.net/project/christine/christine/0.6.0-pre1/Christine-0.06.00-pre1.exe

      I forgot to mention that you have to install Microsoft Visual C++ 2008 redistributable in order to work.

      ]]>
      http://islascruz.org/html/index.php/blog/show/Christine-0.6.0-pre1%3A-first-win32-build.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine-0.6.0-pre1%3A-first-win32-build.html Sun, 22 Nov 2009 04:10:06 -0600
      <![CDATA[ Image as background in a Gtk Application. ]]> This time I'm going to talk about putting an image as the application background in Gtk. In Gtk we are used to leave the colors of the application to the theme, but sometimes we will need to use an image as background. I already wrote how to draw a pixbuf in a gtk.DrawingArea (Esp), we could use that, but we will "draw" directly on the widget window instead.

      Yes, I said the widget's window instead the widget itself. You should know that every widget that has been packed in a container has a gtk.gdk.window object and is the responsible for containing your widget. Well, we can draw on that object.

      What we need is to create a simple gtk.gdk.Pixbuf and call the gtk.gdk.window.draw_pixbuf method using your widget.window object on the expose-event.

      The code should look like this:

      #!/usr/bin/env python
      import gtk
      def draw_pixbuf(widget, event):
              path = '/home/markuz/wallpapers/WMwall1024x768.gif'
              pixbuf = gtk.gdk.pixbuf_new_from_file(path)
              widget.window.draw_pixbuf(widget.style.bg_gc[gtk.STATE_NORMAL], pixbuf, 0, 0, 0,0)
      window = gtk.Window()
      window.set_title('Drawing Test')
      window.set_size_request(640,480)
      window.connect('destroy',gtk.main_quit)
      hbbox = gtk.HButtonBox()
      window.add(hbbox)
      hbbox.connect('expose-event', draw_pixbuf)
      button = gtk.Button('Press Me!')
      hbbox.pack_start(button, True, False, 10)
      window.show_all()
      gtk.main()
       
      And the result should be like this:

      Putting an image as background in Gtk

      It is just a window with an HBoxButton as container and a Button in the middle. The button draws normal, but the HButtonBox is drawing its gtk.gdk.window with a pixbuf. ]]>
      http://islascruz.org/html/index.php/blog/show/Image-as-background-in-a-Gtk-Application..html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Image-as-background-in-a-Gtk-Application..html Wed, 18 Nov 2009 01:16:02 -0600
      <![CDATA[ Christine running on MS Win32 ]]>

      Finally!!!, Christine, my beloved media player is running on Windows, this is something that I really wanted to do for the next release. I had spend the last nights trying to compile it, first I tried to compile GStreamer, then I realized that there are binaries in the GStreamer WinBuilds project, with a little less work, I tried to compile Christine using cygwin, but it didn't worked. Then using the Python's distutils I compiled the C modules and I created a binary with Py2exe

      There it is, running. I still have a lot of work to do, because Christine is written for UNIX and several technologies like Dbus are not in win32, although it seems to be in progress.

      I'm running it on a virtual machine and I haven't tested if it really plays something, I'll give a try tomorrow.

      For tonight I'm happy :-)

      Some shots:

      Christine running on Win32 Christine running on Win32Coding Christine
      ]]>
      http://islascruz.org/html/index.php/blog/show/Christine-running-on-MS-Win32.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine-running-on-MS-Win32.html Sat, 31 Oct 2009 04:29:06 -0500
      <![CDATA[ Trying to compile christine on Windows ]]>


      Trying to

      Originally uploaded by markuz



      Last night I was trying to compile christine on windows using cygwin, I didn't made it but I think I know why, I will try to make it work this tonight.

      ]]>
      http://islascruz.org/html/index.php/blog/show/Trying-to-compile-christine-on-Windows.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Trying-to-compile-christine-on-Windows.html Wed, 28 Oct 2009 10:45:23 -0500
      <![CDATA[ Christine playing videos ]]>


      Christine playing videos

      Originally uploaded by markuz



      I was playing with gstreamer video sinks, I found that using cacasink and aasink you can play videos in ascii mode ;-) funny even when (for me) has no good use.

      ]]>
      http://islascruz.org/html/index.php/blog/show/Christine-playing-videos.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine-playing-videos.html Fri, 23 Oct 2009 17:31:00 -0500
      <![CDATA[ Christine small mode ]]>


      Christine small mode

      Originally uploaded by markuz



      This is Christine in small mode (Ctrl+d).

      ]]>
      http://islascruz.org/html/index.php/blog/show/Christine-small-mode.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine-small-mode.html Wed, 21 Oct 2009 12:22:52 -0500
      <![CDATA[ Developing Christine ]]>


      Christine

      Originally uploaded by markuz




      ]]>
      http://islascruz.org/html/index.php/blog/show/Developing-Christine.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Developing-Christine.html Wed, 21 Oct 2009 02:49:48 -0500
      <![CDATA[ Working on Christine ]]>


      Christine

      Originally uploaded by markuz



      Tonight I have been working on the display widget. That part of christine that displays the title and lenght of the song you are playing. I have set up a background to make it look less simple.
      I also put the control buttons, the volume control and the search entry (which is hided in this screenshot) in a toolbar.
      What do you think about this small changes?

      ]]>
      http://islascruz.org/html/index.php/blog/show/Working-on-Christine.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Working-on-Christine.html Wed, 21 Oct 2009 02:47:48 -0500
      <![CDATA[ October Desktop ]]>


      October Desktop

      Originally uploaded by markuz




      ]]>
      http://islascruz.org/html/index.php/blog/show/October-Desktop.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/October-Desktop.html Tue, 13 Oct 2009 02:11:00 -0500
      <![CDATA[ Christine 0.5.1 released! ]]> It supports all the media files that your gstreamer installation can support, being MP3, OGG, AVI, MPG. It saves the URIs and Meta tags in a database and let you browse them quickly.
      Christine also provides early support for Radio Stations and have its own DBus interface which let you control christine with your media keyboard buttons as they are configured on GNOME.
      The early access to Plugins will let you tweet the music you are listening to, put it on your pidgin status and use notifications while you change your current song.

      Bug fix release

      Several bugs have been fixed, you can find the bug list and release notes here

      Download

      Download Sources

      ]]>
      http://islascruz.org/html/index.php/blog/show/Christine-0.5.1-released%21.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine-0.5.1-released%21.html Tue, 13 Oct 2009 00:41:09 -0500
      <![CDATA[ Working on christine 0.5 ]]>


      Working on christine 0.5.0

      Originally uploaded by markuz



      I have been working today on Christine 0.5 fixing bugs to release 0.5.1 and then start working on new features.

      ]]>
      http://islascruz.org/html/index.php/blog/show/Working-on-christine-0.5.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Working-on-christine-0.5.html Sat, 03 Oct 2009 22:15:29 -0500
      <![CDATA[ Christine 0.5.0 released! ]]> It supports all the media files that your gstreamer installation can support, being MP3, OGG, AVI, MPG. It saves the URIs and Meta tags in a database and let you browse them quickly.
      Christine also provides early support for Radio Stations and have its own DBus interface which let you control christine with your media keyboard buttons as they are configured on GNOME.
      The early access to Plugins will let you tweet the music you are listening to, put it on your pidgin status and use notifications while you change your current song.

      What's new

      • Faster: Christine improves the startup and search methods to be faster than 0.4.0.
      • Drag and Drop import: You can import a folder by Dragging it from Nautilus and dropping into Christine.
      • Library list flick: In Christine 0.4, when the list is too big and you are at the end, it flicks while you scroll over it. Christine 0.5.0 improves that, with smooth scroll.
      • Config directory change Apply the freedesktop's standard for config directory http://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
      • Double function in Previous button When you are using Christine and click in the previous button, Christine will restart the current item, if you hit the previous button again it will get you to the previous item.
      • Import files are something non-blocking You can use Christine while you are importing files.

      Download

      Download Sources

      Binary Packages

      update: Added the Fedora package link. ]]>
      http://islascruz.org/html/index.php/blog/show/Christine-0.5.0-released%21.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine-0.5.0-released%21.html Tue, 01 Sep 2009 01:34:34 -0500
      <![CDATA[ Wrap text in a TreeView column ]]> In ICT Consulting I did a small program that help the support team to create new tickets in the tracking system and keep them updated. In the "update" screen, I put a TreeView to show the comments history.

      For Gtk TreeViews are just a "viewer" of the data stored in the "model", but it depends in the way the cell renderer will do its job. The render for text is called.. yes, you guessed: CellRendererText. This item will render the text as it is in the model.

      If you are using text with markup (with the pango markup) it will be displayed with bold, italic and many other properties you define in your markup. But this render have a small problem, if you have a long line because the input method was a text box and the user didn't use the return key then you will end with a very very long line in the treeview.

      If the line is not too big then the use of the scrollbar may help you, but, if that's not the case, and you or your user have to check more and more lines like that, using the scrollbar is tedious.

      The fix: make the column usually big to wrap the text.

      The trick is know the size of the window, and compute the space left by other columns then, set the
      wrap_width property of the cell renderer according to the space left. That's what the "resize_wrap" function do.




      treeview resize

      ]]>
      http://islascruz.org/html/index.php/blog/show/Wrap-text-in-a-TreeView-column.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Wrap-text-in-a-TreeView-column.html Sun, 30 Aug 2009 02:04:53 -0500
      <![CDATA[ Holy Shit! ]]> I used Christine in an usual way. I use to play the items in the main list as the items there are in my hard drive. Today I was switching between playlists and some of them have more or less 14000 items. I don't know why but christine grows a lot more than I expect.

      Holy Shit!!!
      ]]>
      http://islascruz.org/html/index.php/blog/show/Holy-Shit%21.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Holy-Shit%21.html Sat, 08 Aug 2009 01:03:55 -0500
      <![CDATA[ Christine Drag & Drop ]]>


      ]]>
      http://islascruz.org/html/index.php/blog/show/Christine-Drag-%26-Drop.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine-Drag-%26-Drop.html Thu, 23 Jul 2009 12:08:28 -0500
      <![CDATA[ Christine on Gentoo ]]> If you are using Gentoo, now you can use the ebuild to have christine running on your system, more on:

      http://packages.gentoo.org/


      Thanks to Samuli Suominen who is taking care :-) ]]>
      http://islascruz.org/html/index.php/blog/show/Christine-on-Gentoo.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine-on-Gentoo.html Wed, 22 Jul 2009 06:35:54 -0500
      <![CDATA[ Python C Class ]]> IronPython.
      The main reason of why you want to extend Python is because the libraries you need are not in the Python packages/modules, another reason may be that you need to crate a small piece of code that have to run faster, IMHO Python is fast enought for most tasks but it doesn't mean that you don't need to create your own C modules.
      Python offers a very good C/C++ API for this. This API is explained in the Python/C API Reference Manual and you'll have a tutorial in the document Extending and Embedding the Python Interpreter, they cover most of what you need.
      I said *most* because even when they are well done documents, you may still have some questions (as I did).
      Well, this post is about classes in python written in C. If you didn't already, there is a recipe in ActiveState's documents, Recipe 54352: Defining Python class methods in C , this recipe will tell you how to create a class in a quick way let's see what does the code do.
      In the next example, I'm creating a class whose methods are going to be inherited by a another class. Now, you know that C is not an object oriented language, and having something like object.property does not exists (you'll have to use an struct for that). Then, you have to create your "methods" as "functions" and add them later to the class you are creating.
      #include <Python.h>
      #include <import.h>
      /*
      * Constructor, yes the Class.__init__ method
      */

      static PyObject*
      init(PyObject *self){
              Py_INCREF(Py_None);
          return Py_None;
      }
      /*
      * A simple method that will be inherited
      * we are assuming that the child class will have a
      * "data" property
      */

      static PyObject *
      print_data(PyObject *self, PyObject *args)
      {
              static PyObject *result;
              static PyObject *selfobj;
              static PyObject *data;
              int index;
          if (!PyArg_ParseTuple(args, "O", &selfobj, ))
              return NULL;
          data = PyObject_GetAttrString(selfobj, "data");
          PyObject_Print(data, stderr, Py_PRINT_RAW);
          Py_INCREF(Py_None);
          return Py_None;
      }
      static PyMethodDef baseClassMethods[] = {
              {"__init__", init, METH_VARARGS,"doc string"},
          {"print_data",  print_data, METH_VARARGS,
          "Print what the data property is/contain."},
          {NULL, NULL, 0, NULL}
      };

      static PyMethodDef ModuleMethods[] = { {NULL} };
      #ifdef __cplusplus
      extern "C"
      #endif
      PyMODINIT_FUNC
      baseClass(void)
      {
              PyMethodDef *def;
              PyImport_AddModule("baseClass");
          //(void) Py_InitModule("baseClass", baseClassMethods);
          PyObject *module = Py_InitModule("baseClass", ModuleMethods);
          PyObject *moduleDict = PyModule_GetDict(module);
          PyObject *classDict = PyDict_New();
          PyObject *className = PyString_FromString("baseClass");
          PyObject *fooClass = PyClass_New(NULL, classDict, className);
          PyDict_SetItemString(moduleDict, "baseClass", fooClass);
          Py_DECREF(classDict);
          Py_DECREF(className);
          Py_DECREF(fooClass);
          /* add methods to class */
          for (def = CLibraryModelMethods; def->ml_name != NULL; def++) {
              PyObject *func = PyCFunction_New(def, NULL);
              PyObject *method = PyMethod_New(func, NULL, fooClass);
              PyDict_SetItemString(classDict, def->ml_name, method);
              Py_DECREF(func);
              Py_DECREF(method);
           }
      }
      int
      main(int argc, char *argv[])
      {
          /* Pass argv[0] to the Python interpreter */
          Py_SetProgramName(argv[0]);
          /* Initialize the Python interpreter.  Required. */
          Py_Initialize();
          /* Add a static module */
          initCLibraryModel();
          return 0;
      }
       
      The code I saw in the recipe is so simple, quite enought to start, but, I have two very very important question.. how that hell do I get the reference of the class? and then, access to the child properties?. Well, looking in the docs, the functions appear to start with a "self" PythonObject, which I assume that is the reference to the class, but no, if you look close the the PyMethod_New the sencond argument is the "self" reference to the class, which we are passing as NULL.
      Using the code in the recipe, when you inherit your class or even using it in this way:
      class a(baseClass):
          def __init__(self):
              baseClass.__init__(self)
              a.data = 'Hello World!'
      b = a()
      b.print_data()
       
      will give an error, if you consider that you are not passing arguments. The problem with the code in the recipe is that they are not using the "self" reference. I found (maybe I'm wrong) that the self reference comes in the arguments!, then you have to do something like this:
      static PyObject *
      print_data(PyObject *self, PyObject *args)
      {
          ...
          if (!PyArg_ParseTuple(args, "O", &selfobj, ))
              return NULL;
          data = PyObject_GetAttrString(selfobj, "data");
          ...
      }
       
      You take the self, reference from the args using the same PyArg_ParseTuple that you use to get the other arguments. Now you can use this class as any other class written in Python, just rememter the __setattr__ and __getattr__ part that is in the bottom of the recipe ]]>
      http://islascruz.org/html/index.php/blog/show/Python-C-Class.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Python-C-Class.html Mon, 13 Jul 2009 04:54:36 -0500
      <![CDATA[ Python mas Wiimote controlling a 15 tonnes arm ]]> Python programming language. I will not use this wiimote to use that mechanical arm just because IMO is too risky just because the wiimote is not an industrial controller, but it could be a start :-)


      ]]>
      http://islascruz.org/html/index.php/blog/show/Python-mas-Wiimote-controlling-a-15-tonnes-arm.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Python-mas-Wiimote-controlling-a-15-tonnes-arm.html Wed, 08 Jul 2009 19:40:59 -0500
      <![CDATA[ IronPython in Action ]]> The people who knows me, know that I'm a fan of the Python programming language, and many of the stuff I do in my work is done with this fabulous tool, I have made work for services, where Python behave very very well, and applications for the Desktop, most of them run on the Microsoft Windows operating system.

      Why do I choose Python instead C, C++, Java or C#?, well, I have to say that I was a PHP user before Python, that was the programming language where I start, and I thought that PHP was perfect, because I felt that PHP was so simple, easy to use because I didn't have to compile anything!. Then I meet Python and everything change.

      I choose Python because it is ridiculously simple, easy to use and it have almost everything you need by default, the data types are more than enought to work and do amazing stuff, it was by the time I meet it a fully functional programming language.

      By that time, I was also trying to learn something about Mono and the C# programming language, its obvious that I left C# in favor of Python, Why? just because Python is easier than C# (IMHO). And by the time, a lot of FUD was arround the mono framework about patents and possible Microsoft attacks which still exists, but by that time Mono was something new and everyone put their eyes on it.

      Now, that I have learned Python and know much more about it, I want to try another developing platform, as I already said, I write programs that runs on the Microsoft Windows OS, and I'm trying to learn something that help me to develop stuff there, but also let me work on it in Linux. The answer IronPython an implementation of the Python programming language under .NET (something similar to Jython but for .NET)

      Recently I receive a copy of the IronPython in Action by Michael J. Foord and Christian Muirhead. The book itself is very interesting, first, you'll see an introduction to IronPython, Python itself and the CLR then start the teaching about the .NET framework and how to write your programs using the .NET objects and IronPython, which is the reason of the book to exists. This is where the book shines, it will teach you how the core development techniques that will help you to write your applications in the IronPython way, using classes with XML, and agile testing.

      Then, and advanced look to the .Net Framwork, using the Microsoft Windows Presentation Foundation, system administration with IronPython and combine IronPython with ASP.NET concluding with the Silverlight plugin, allowing you to create appliciations like Flash does.

      Finally, something really really important, how to extend your IronPython applications using C#/VB.NET. We know that even when the programming language is very very powerfull we need tu help us with another programming language, This may be because it is simpler or easy to do in another language or just because you have to do it like that. Python let you extend your applications writing python modules with C, IronPython could not be the exception and allows you to write extensions using the C# and VB.NET languages. And in the same way you could extend Python/IronPython, you could use it to extend another application by embedding the IronPython engine into your applications.

      Yes, the book is about Windows programming, Windows programmers will benefit from the book by learning how to write their applications using IronPython. No matter if they are beginners or experienced users. I think that using IronPython will help them a lot if they use it instead the C, or C++, because it is quick, it is simple, easy to read and more, but also, programmers that use another OS will benefit from it, by using the Mono Framework.

      If you are looking a good book to learn .NET check the IronPython in Action, it's a very complete book.

      ]]>
      http://islascruz.org/html/index.php/blog/show/IronPython-in-Action.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/IronPython-in-Action.html Sat, 27 Jun 2009 00:32:33 -0500
      <![CDATA[ PyGtk: GtkDialog for configurations using pure treeviews ]]>


      I have been working on this, this is a very early version of the configuration dialog I have already created, I promisse I will put fully working version here with source code :-) ]]>
      http://islascruz.org/html/index.php/blog/show/PyGtk%3A-GtkDialog-for-configurations-using-pure-treeviews.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/PyGtk%3A-GtkDialog-for-configurations-using-pure-treeviews.html Wed, 10 Jun 2009 09:25:50 -0500
      <![CDATA[ Sockets (and some other files) and PyGTK without threads. ]]> PyGTK and Threads motivated by the work I have been doing on ICT Consulting where I have a graphical application that need to have a web service where some other applications could connect and execute some of its public function.
      My first aproach was Threads just because with them I could use an infinite loop reading the socket while in the main thread the gtk loop runs. This is nice if your application is going to ask/request something trough the socket and receive the answer at some point, then, when the answer is here, you could emit a signal and then move your gui to show the answer.
      But, what if you need to receive the request and then, move your gui asking to the user for an answer or show something in the screen, or whatever, you could make use of what I just did in the PyGTK and Threads post, where you use gobject.idle_add to launche the function that will modify your gui, which is nice you don't care about the return value of the task.
      Today, looking in trough the gobject reference I saw the gobject.io_add_watch function. This function will let you, as its name describes, watch for the I/O activity in a file descriptor. As sockets are treated like sockets, then you have the chance to use it here.
      What about that?, well, if you have the chance to check the I/O of the socket file then you will know when data arrives and call the proper handler, and do it in the very same thread that the main loop. Then, you can move the GUI and return something if you have to.
      In webservices this is useful because you can catch any error and inform the client that there is something wrong with the function it calls. The implementation is quite simple, let's do it with the code that we already use in the Threads post.
      This is the server:
      import SOAPpy
      import gtk
      import gobject
      import time
       
      def hello(name):
              dialog = gtk.Dialog("Hello dialog",
                              None,
                              gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                              (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
                                      gtk.STOCK_OK, gtk.RESPONSE_ACCEPT,)
                              )
              label = gtk.Label('Hello %s'%name)
              dialog.vbox.pack_start(label)
              label.show()
              response = dialog.run()
              dialog.destroy()
              return response
      def change_time(label):
              label.set_text(repr(time.time()))
              return True
      def handle_request(source, condition, webservice):
              try:
                      webservice.handle_request()
              except:
                      pass
              return True
             
      soapserver = SOAPpy.SOAPServer(('',8080))
      soapserver.registerFunction(hello)
      gobject.io_add_watch(soapserver.socket, gobject.IO_IN,
                           handle_request, soapserver)
      win = gtk.Window()
      win.connect('destroy', gtk.main_quit)
      win.set_size_request(300,300)
      label = gtk.Label('Main window')
      gobject.timeout_add(100, change_time, label)
      win.add(label)
      win.show_all()
      gtk.main()
       
      And the client:
      #!/usr/bin/env/python
      import SOAPpy
      import sys

      server = SOAPpy.SOAPProxy("http://localhost:8080/")

      prueba = sys.argv[1]
      args = tuple(sys.argv[2:])
      print args
      func = getattr(server, prueba, False)
      print func(*args)
       
      Using it like this:
      python soaptest.py hello markuz
      gives as result the integer value for the response asociated to the button you just clicked.

      Gtk webservices with no threads from Marco Antonio on Vimeo.


      I hope this information is useful for you. For me, it saves my day! ]]>
      http://islascruz.org/html/index.php/blog/show/Sockets-%28and-some-other-files%29-and-PyGTK-without-threads..html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Sockets-%28and-some-other-files%29-and-PyGTK-without-threads..html Wed, 27 May 2009 00:58:06 -0500
      <![CDATA[ PyGtk and Threads ]]> As a GNOME user I would like to make use of DBus, but again, I have no control over the other applications. and DBus even when it is widely accepted on the Linux/Unix environment, is not the same over Windows.
      Then, how could I communicate my program with the others?, easy, webservices, the reason: Usin a widely used protocol (HTTP) will ensure that the data is received or at least there will be error handlers, and, I don't have to implement the protocol by myself on python, even the webservices libraries exists for a while now.
      Implement a webservice is quite simple with Python, there are some libraries, but I like to use SOAPpy, so, create a webservices server is as simple as this:
      import SOAPpy
      def hello(name):
          return 'Hello %s'%name
      soapserver = SOAPpy.SOAPServer(('',8080))
      soapserver.registerFunc(hello)
      soapserver.serve_forever()
       
      This webservices server will be listening over the port 8080 for new connections and will allow the clients to use the hello function. Simple right?. Well there is something that we must watch, the serve_forever as the SOAPpy docs said, it will be serving until the doomsday, and it does it over a infinite while loop blocking our script on that point.
      For most applications this will be good, maybe because you only want to serve your functions like in the example. If you don't want to be stuck in the serve_forever method, then you have to use another thread. This is what you have to do while writing python applications that need to use a function/method that uses an infinite while loop or may take a long time to complete.
      The reason?, Gtk+ runs over a main loop, this loop is used by GTK+ to emit every signal, run the callbacks, draw everything it needs to redraw and call the functions that are in a gobject.timeout_add or gobject.idle_add methods. Gtk+ does it in one loop. Then, if a pice of your code require a bit more time the gtk loop takes more time to do the loop and it cannot redraw, emit, call, and do other stuff until your piece of code finish it's job, then, your application looks like it is freeze.
      Now, what happend if your piece of code is an infinite while loop?. Yes! Gtk will never do more than one cycle.
      This is why I use the code I know may take a long time in another thread. This may be donwloading something, or serving something. In general, you just need to initialize the threads in gobject calling
      gobject.threads_init()
       
      then, cover your thread over a gtk.gdk.threads_enter() and . This will help you making your application responsive while it is doing a long time task. But, be aware, if you don't do this your thread may not work, and you should know that you can't edit your UI within the child thread.
      It's supposed that you can do it if you use
      gtk.gdk.threads_init(), it does work on Linux, but it doesn't work if you are running your application on Win32.
      So, what can you do?, use you can use gobject.idle_add to launch a function where you are going to move the GUI. with this you will ensure that your GUI will be edited only in the main thread (where gtk.main_loop runs). Remember, your function should return something diferent than True if you don't want it to be called every time gobject have spare time.
      import SOAPpy
      import thread
      import gtk
      import gobject
      import time
      gobject.threads_init()
       
      def hello(name):
              def func(name):
                      dialog = gtk.Dialog("Hello dialog",
                                      None,
                                      gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                                      (gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
                      label = gtk.Label('Hello %s'%name)
                      dialog.vbox.pack_start(label)
                      label.show()
                      response = dialog.run()
                      dialog.destroy()
                      return False
              gobject.idle_add(func, name)
      def change_time(label):
              label.set_text(repr(time.time()))
              return True
      soapserver = SOAPpy.SOAPServer(('',8080))
      soapserver.registerFunction(hello)
      gtk.gdk.threads_enter()
      thread.start_new(soapserver.serve_forever, tuple())
      gtk.gdk.threads_leave()
      win = gtk.Window()
      win.connect('destroy', gtk.main_quit)
      win.set_size_request(300,300)
      label = gtk.Label('Main window')
      gobject.timeout_add(100, change_time, label)
      win.add(label)
      win.show_all()
      gtk.gdk.threads_enter()
      gtk.main()
      gtk.gdk.threads_leave()
       

      Gtk and threads from Marco Antonio on Vimeo.


      Finally, maybe you don't want to mess with threads and prefer to use asynchronous I/O, or if you are talking about networking the use of the event-driven networking engine Twisted ]]>
      http://islascruz.org/html/index.php/blog/show/PyGtk-and-Threads.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/PyGtk-and-Threads.html Sat, 23 May 2009 01:21:43 -0500
      <![CDATA[ Python: Create win32 services using Python and py2exe ]]> Hi, in this case I'm going to show you how to create simple services for the win32 platform using the powerfull Python programming language and the py2exe utility.
      Writing Python applications under windows is quite simple, maybe you didn't use windows to develop your application (as I do most times), the code, what you want to do with your application is up to you, and I'm not goint to touch the programming techniques for developing windows applications, Just, create a simple -and useles- win32 service that will help you to uderstand how to create your very own windows service.
      First, every single program that you create with python and compile with py2exe and does run well, may be a win32 service, it may be a program that fetches the RSS xml feed for islascruz.org, maybe is a more complex program to generate some files and then send them to another server, maybe is a simple program to remind you to sand up an walk 10 minutes.
      Said that we don't really need to create a program thinking on it as a service, we will create a simple program and test it using the python interpreter, who needs to compile?, well, we need it, but just when we are sure that our program performs well.
      Read more ]]>
      http://islascruz.org/html/index.php/blog/show/Python%3A-Create-win32-services-using-Python-and-py2exe.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Python%3A-Create-win32-services-using-Python-and-py2exe.html Fri, 01 May 2009 21:27:26 -0500
      <![CDATA[ Christine for 2009-04-26 ]]> christine, first, I move the plugins, now, instead of being a simple module, they need to be a package, doing this will let us to develop bigger plugins and make use of their directory (package) to store whatever the plugin need to. I also work a bit on the subtitles part, letting the user choose his favourite font on the preferences dialog. Also, you can change the encoding. At last, I added five functions to christineDBus package: get_tags, add_to_queue, get_playlists, get_tracks_on_playlist, get_radios

      Christine preferences dialog with subtitles

      But, I haven't just worked on this, did I mention that now christine uses Trac?, well yes, we now use Trac in http://www.christine-project.org for ticket management, Roadmap, wiki and source code browsing. ]]>
      http://islascruz.org/html/index.php/blog/show/Christine-for-2009-04-26.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine-for-2009-04-26.html Sun, 26 Apr 2009 03:40:39 -0500
      <![CDATA[ Christine: rola_christine.py ]]>
      xchat command to get christine current track

      Similar to what Gnuget do with rola-banshee.py I did the same but for christine:
      #! /usr/bin/env python
      # -*- coding: utf-8 -*-
       
      #Author: Marco Islas
      #Correo: markuz@islascruz.org
      #Based on rola-banshee.py http://gnuget.org/blog/view/203/rola-banshee-py
       
      version = "1.0"
       
      __module_name__ = "rola_christine.py"
      __module_version__ = version
      __module_description = 'Shows the track in christine (requires christine from SVN)'
       
      import dbus
      import xchat
      from dbus.mainloop.glib import DBusGMainLoop
       
      class RolaChristine:
              def __init__(self):
                      mainloop = DBusGMainLoop()
                      self.dbus_session = dbus.SessionBus(mainloop = mainloop)
                      self.christine = self.dbus_session.get_object('org.christine',
                                      '/org/christine')
                      xchat.prnt("rola-christine.py Version %s loaded!" %version)
                      xchat.prnt("/rola-christine")
             
              def rola(self,word,word_eol,userdata):
                      tags = self.christine.now_playing()
                      title = '%s'%tags.get('title','')
                      if not title:
                              xchat.command('Nada a mostrar..')
                              return xchat.EAT_XCHAT
                      artist = "%s"%tags.get('artist','')
                      if artist:
                              artist = "%s -"%artist
                      xchat.command("me esta escuchando: %s %s" %(artist,title))
                      return xchat.EAT_XCHAT
      control = RolaChristine()
      xchat.hook_command("rola-christine",control.rola)
       
      This make me check my code, and the script above works only with christine on the svn. This code was done on the afternoon and may get broken at some place, but is nice if you want to play. ]]>
      http://islascruz.org/html/index.php/blog/show/Christine%3A-rola_christine.py.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine%3A-rola_christine.py.html Sun, 12 Apr 2009 23:29:19 -0500
      <![CDATA[ Christine 0.3.0 ]]>
      Christine 0.3.0

      =========================
      Christine 0.3.0 released!
      =========================
      Christine is a small and functional media player written in Python using PyGtk as GUI toolkit and Gstreamer as backend.
      It supports all the media files that your gstreamer installation can support, being MP3, OGG, AVI, MPG. It saves the URIs and Meta tags in a database and let you browse them quickly.
      Christine also provides early support for Radio Stations and have its own DBus interface which let you control christine with your media keyboard buttons as they are configured on GNOME.
      The early access to Plugins will let you tweet the music you are listening to, put it on your pidgin status and use notifications while you change your current song.

      Changes


      • DBus support.

        • Functions:

          • Play
          • Pause
          • Prev
          • Next

        • Signals

          • NewLocation


      • Plugins

        • New Plugins

          • Gnome Media Keys support
          • Album Cover
          • Early acces to getInfo
          • GnomeDBus

        • Improved pidgin configuration dialog

      • Player

        • Support for subtitles
        • Better handle of xvimagesink

      • Misc

        • Faster import
        • 3rd party module that contains libraries developed by others
        • Improved sources UI

      • Bugfixes:

        • Visualization doesn't work with xvimagesink
        • Cannot delete a file from the main library


      As usual, you can get it from sourceforge.net: ]]>
      http://islascruz.org/html/index.php/blog/show/Christine-0.3.0.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine-0.3.0.html Sat, 11 Apr 2009 04:10:30 -0500
      <![CDATA[ Pygtk: About keyboard accelerators ]]> gtk.accelerator_parse to define your accelerator there may be cases where you do not know the tecnical name of the mod, then you can of the key value of the key you are pressing.
      Fortunately Gtk does provide the way to know this values. The next program is a small window where you can know the value of the key you are pressing.
      #!/usr/bin/env python
      import gtk
      import gtk
      def catch_button(window, event, label):
              keyval = event.keyval
              name = gtk.gdk.keyval_name(keyval)
              print event.state
              mod = gtk.accelerator_get_label(keyval,event.state)
              label.set_markup('<span size="xx-large">%s\n%d</span>'% (mod, keyval))
       
       
      window = gtk.Window()
      window.set_size_request(640,480)
      label = gtk.Label()
      label.set_use_markup(True)
      window.connect('key-press-event',catch_button, label)
      window.connect('destroy', gtk.main_quit)
      window.add(label)
      window.show_all()
      gtk.main()
       
      And looks like this:

      GtkKeyCatcher

      In my keyboard the NumLock key makes GTK to set the Mod2 value all the time as in this mail: http://mail.gnome.org/archives/gtk-list/2001-July/msg00153.html
      Anyway, this may give you a clue about what keys you are pressing, but remember, instead of using the key value directly you should use gtk.gkd.keyval_from_name() and pass the name of the key you are trying to use.
      In the next piece of code let you use the "Win" modifier and the F8 key to do something, you should notice that I'm using gtk.gdk functions to get the values.
      def key_catcherself, widget,  event):
              '''
              Maneja los eventos de las ventanas
              '
      ''
              F8 = gtk.gdk.keyval_from_name('F8')
              if os.name != 'posix':
                      superName = gtk.gdk.MOD1_MASK
              else:
                      superName = gtk.gdk.SUPER_MASK
              keyval = event.keyval
              if event.state & superName and keyval == F8:
                      mod = gtk.accelerator_get_label(F8, event.state)
                      print "you have pressed ", mod
       
      ]]>
      http://islascruz.org/html/index.php/blog/show/Pygtk%3A-About-keyboard-accelerators.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Pygtk%3A-About-keyboard-accelerators.html Fri, 10 Apr 2009 22:08:28 -0500
      <![CDATA[ Python: Merge two lists in a single in the less time possible. ]]>
      a = []
      b = []
      for i in range(0,10):
          a.append(i)
          b.append(i)
       
      Then I realize that I was being a fool by creating acouple of lists and then append in every list, the better, copy the list. Copying a list may be done in several ways:
      #Iterating over the list with a for statement
      for i in a:
          b.append(i)
       
      #Copying the data using a list mapping
      b = [k for k in a]
       
      #Using the map function
      map(lambda x: b.append(), a)
       
      But the fastest way is making a slice
      b = a[:]
       
      Then, I append the data to b
      for i in range(10,20):
          b.append(i)
       
      resulting in this:
      a = [0,1,2,3,4,5,6,7,8,9]
      b = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18.19]
       
      Doing this with a small amount data is easy and fast, but with a large amount this will take a bit more time. There is an easy way to append data to the second is this:
      b.append('')
      b[-1:] = range(10,20)
       
      I made a small test and found that iterating over 20000000 takes only 0.2 secs copying the data from the list a into the list b, while iterating using a for statement it takes aprox. 10 secs. This is the code that I use to make the test.
      import time
      added = range(100,20000000)
      a = range(100)
      b = range(100)
      ctime = time.time()
      b.append('')
      b[-1:] = added
      print time.time() - ctime
      ctime = time.time()
      for i in added:
              a.append(i)
      print time.time() - ctime
      print len(a), len(b)
      equals = 'True'
      for index,value in enumerate(a):
              if value != b[index]:
                      print value
                      equals = 'No'
                      break
       
      print "They are the same? ", equals
       
      markuz$ python append_test.py
      0.289237976074
      9.6946041584
      20000000 20000000
      They are the same? True
      markuz$
      ]]>
      http://islascruz.org/html/index.php/blog/show/Python%3A-Merge-two-lists-in-a-single-in-the-less-time-possible..html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Python%3A-Merge-two-lists-in-a-single-in-the-less-time-possible..html Tue, 31 Mar 2009 22:18:32 -0500
      <![CDATA[ Google and the Python performance ]]> Google's Python engineers efford on bringing performance boost on Python. As many of you know, I like a lot this programming language, I do all my work on it. Reading that by the second quarter of 2009 there will be a functionally equivalent replacement for the Python interpreter.
      Python, from my point of view, is a very fast programming language, not only writing on it, but in the tasks that it must do. I know it have its own speed problems inherited by using an interpreter/virtual machine instead native code, but today computers makes building non-ultra-fast programs being written on Python a delightful task. Then, using a more powerfull interpreter will make python a very close to C alternative and many more developers will look on it. ]]>
      http://islascruz.org/html/index.php/blog/show/Google-and-the-Python-performance.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Google-and-the-Python-performance.html Fri, 27 Mar 2009 23:32:03 -0500
      <![CDATA[ Python: Simple HTTP Server on python. ]]> Python have several modules that help you to achieve your goals. This week, on my spare time that is getting every day more scarce I spend time figuring out how to create a Python Web Server, I was planing to use it over an application that I'm developing on ICT Consulting. At the end I didn't use it because I didn't want a "passive" comunication, but probably I will use this code on the CRM Desktop application that we use here.
      Anyway, this code may be helpful for you too. I found that creating a small web server is really simple, It starts getting bigger as you add functions to that web server, but the basis is quite simple.
      import os
      import cgi
      import sys
      from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
      class customHTTPServer(BaseHTTPRequestHandler):
              def do_GET(self):
                      self.send_response(200)
                      self.send_header('Content-type', 'text/html')
                      self.end_headers()
                      self.wfile.write('<HTML><body>Get!</body></HTML>')
                      return
                     
              def do_POST(self):
                      global rootnode
                      ctype,pdict = cgi.parse_header(self.headers.getheader('Content-type'))
                      if ctype == 'multipart/form-data':
                              query = cgi.parse_multipart(self.rfile, pdict)
                      self.send_response(301)
                      self.end_headers()
                      self.wfile.write('Post!')
             
                     
      def main():
              try:
                      server = HTTPServer(('',8080),customHTTPServer)
                      print 'server started at port 8080'
                      server.serve_forever()
              except KeyboardInterrupt:
                      server.socket.close()
      if __name__=='__main__':
              main()
       
      There are two main methods in our small server: do_GET and do_POST, you can figure out what this methods do. Get is quite simple, Post is used to send data to the server, as an example, the file uploading. This is done via POST and many times using "multipat/form-data" as the content type. The Post method here handles that.
      Now that you have a custom server, how can you check it?, well, to check GET you can call it from the web browser. For the POST stuff, you can create a simple web form and using your web browser as "action" on it. However, this code can help you:
      import urllib2
      import urllib
      import time
      import httplib, mimetypes
      HOST = '127.0.0.1'
      PORT = '8080'
      def post_multipart(host, port, selector, fields, files):
              """
              Post fields and files to an http host as multipart/form-data.
              fields is a sequence of (name, value) elements for regular form fields.
              files is a sequence of (name, filename, value) elements for data to be uploaded as files
              Return the server's response page.
              """

              content_type, body = encode_multipart_formdata(fields, files)
              h = httplib.HTTP(host, port)
              h.putrequest('POST', '/cgi-bin/query')
              h.putheader('content-type', content_type)
              h.putheader('content-length', str(len(body)))
              h.endheaders()
              h.send(body)
              #errcode, errmsg, headers = h.getreply()
              h.getreply()
              return h.file.read()
      def encode_multipart_formdata(fields, files):
              """
              fields is a sequence of (name, value) elements for regular form fields.
              files is a sequence of (name, filename, value) elements for data to be uploaded as files
              Return (content_type, body) ready for httplib.HTTP instance
              """

              BOUNDARY = '----------ThIs_Is_tHe_bouNdaRY_$'
              CRLF = '\r\n'
              L = []
              if fields:
                      for (key, value) in fields:
                              L.append('--' + BOUNDARY)
                              L.append('Content-Disposition: form-data; name="%s"' % key)
                              L.append('')
                              L.append(value)
              if files:
                      for (key, filename, value) in files:
                              L.append('--' + BOUNDARY)
                              L.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))
                              L.append('Content-Type: %s' % get_content_type(filename))
                              L.append('')
                              L.append(value)
              L.append('--' + BOUNDARY + '--')
              L.append('')
              body = CRLF.join(L)
              content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
              return content_type, body
      def get_content_type(filename):
              return mimetypes.guess_type(filename)[0] or 'application/octet-stream'
      def test():
              print  post_multipart(HOST, PORT, 'markuz',
                                              ( ('username','markuz'),  ('another_field','another value')),
                                              (('query','query','Query'), ),
                                         )
      if __name__ == '__main__':     
           test()
       
      ]]>
      http://islascruz.org/html/index.php/blog/show/Python%3A-Simple-HTTP-Server-on-python..html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Python%3A-Simple-HTTP-Server-on-python..html Sat, 21 Mar 2009 03:40:19 -0500
      <![CDATA[ PyGTK: Playing with gtk.GenericCellRenderer ]]> I end by setting the color to the background of the cell renderer using the "background" property. This was better than shoing another column, but still was ugly, because using the background property makes the cells looks splitted.
      Recently, I discover the pygtk's GenericCellrenderer, this cell renderer allows you to implement your very own custom CellRenderer. and then, I could "draw" using Cairo to draw my cell's background. This let me use gradients, or even draw complex images in the background of the cell.

      Playing with GenericCellRenderer

      It's obvious that this is not the only use of the gtk.GenericCellRenderer, you can use it to represend anything you want, being a pixmap, maybe an object, a code bar.. I don't know, that's up to you.
      Creating your own CellRenderer is quite simple, the first you have to do is subclass gtk.GenericCellRenderer, and implement this four methods:
      def on_get_size(widget, cell_area)
      def on_render(window, widget, background_area, cell_area, expose_area, flags)
      def on_activate(event, widget, path, background_area, cell_area, flags)
      def on_start_editing(event, widget, path, background_area, cell_area, flags)
       
      The main methods are on_get_size, that tells the size of the cell, this value is going to be passed to on_render method. The method "on_render" is the one where you are about to work on, since all the "drawing" is made here.
      Just as an example, this is the code I use in the on_render method:
              def on_render(self, window, widget, background_area, cell_area, expose_area, flags):
                      cairo_context = window.cairo_create()
                      x = cell_area.x
                      y = cell_area.y
                      w = cell_area.width
                      h = cell_area.height
                      if x == 0:
                              curve_to = 'start'
                      elif (x + w ) == widget.allocation.width:
                              curve_to = 'end'
                      else:
                              curve_to = None
                      self.render_rect(cairo_context, x, y, w, h, 1, curve_to)
                      pat = cairo.LinearGradient(x, y, x, y + h)
                      color = gtk.gdk.color_parse("#87D8F5")
                      pat.add_color_stop_rgba(
                                                              0.0,
                                                              self.get_cairo_color(color.red),
                                                              self.get_cairo_color(color.green),
                                                              self.get_cairo_color(color.blue),
                                                              1
                                                              )
                      color = gtk.gdk.color_parse(self.get_property('background'))
                      pat.add_color_stop_rgb(
                                                              1.0,
                                                              self.get_cairo_color(color.red),
                                                              self.get_cairo_color(color.green),
                                                              self.get_cairo_color(color.blue)
                                                              )
                      cairo_context.set_source(pat)
                      cairo_context.fill()
                      context = widget.get_pango_context()
                      layout = pango.Layout(context)
                      layout.set_text(self.get_property('text'))
                      layout.set_width(cell_area.width)
                      widget.style.paint_layout(window, gtk.STATE_NORMAL, True,
                                              cell_area, widget, 'footext',
                                              cell_area.x, cell_area.y,
                                              layout)
       
      I already have imported gtk, pango and created some other methods like render_rect, get_cairo_color and the property methods.
      One of the disadvantages I saw is that you can't create a pangocairo context from the CellRenderer, this is because the CellRenderer is not a widget, and doesn't have the create_pango_layout, but you can use the widget.style.paint_layout to write whatever you want.}
      The full code of this is Here ]]>
      http://islascruz.org/html/index.php/blog/show/PyGTK%3A-Playing-with-gtk.GenericCellRenderer.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/PyGTK%3A-Playing-with-gtk.GenericCellRenderer.html Sat, 28 Feb 2009 03:41:48 -0600
      <![CDATA[ Know the current unix time (for the party) ]]>
      python -c "import time; print time.mktime(time.localtime())"
      Btw.. if you want to know the hour where the Unix time will be "1234567890" use this:
      python -c "import time; print time.strftime('%Y-%B-%d %H:%M:%S',time.localtime(1234567890))"
      ]]>
      http://islascruz.org/html/index.php/blog/show/Know-the-current-unix-time-%28for-the-party%29.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Know-the-current-unix-time-%28for-the-party%29.html Fri, 13 Feb 2009 08:47:06 -0600
      <![CDATA[ Christine: subtitles. ]]>
      Its alive!

      I was working tonight in subtitles, and fixing a couple of issues in christine :-) ]]>
      http://islascruz.org/html/index.php/blog/show/Christine%3A-subtitles..html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine%3A-subtitles..html Wed, 11 Feb 2009 00:10:40 -0600
      <![CDATA[ Christine, DBus and Cairo ]]> I have been working tonight trying to create a small notification window for christine, besides we have the PyNotify plugin, I feel this need to try something more. Then I use this great how to create glass like windows and create this:


      Christine, dbus and Cairo from Marco Antonio on Vimeo.

      In the video you'll see the notification window displaying the button I'm pressing in my keyboard to control christine without having christine on focus. The code is already in svn if you want to try. ]]>
      http://islascruz.org/html/index.php/blog/show/Christine%2C-DBus-and-Cairo.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine%2C-DBus-and-Cairo.html Thu, 22 Jan 2009 00:35:26 -0600
      <![CDATA[ This week on Markuz life... ]]> Well, Sunday is my free day, I try to woke up late, but I just can't, I was stand up at 8:30 in the morning. after the breakfast I clean the house and start playing with the acer and go out of the house by the 3 in the noon. Cristina was about to be in the Bus station by the 10 in the night. I can't wait until then. Its horrible that your free day, that day that you usually don't want to pass away I was counting the minutes... horrible.
      Well, after that everything is back to the normal way.
      ICTC finally release the Juvi project. Which is a software development project where almost everybody in the office was involved, not only programmers but people that have to go to the client, document writers, analyst... everyone. The hard work that everyone put is seen by now in a product very very well done. I'm glad to be in such a great team!.
      To test the desktop application for Juvi, I have to use a virtual machine, this virtual machine runs Windows XP and I have knowledge that my programs written in Python runs fine on Windows XP and WIndows 2k using py2exe but I didn't make a test under Windows Vista. We made that test yesterday and the application runs smooth!, I have to change nothing! the same installer for Windows 2K to Windows Vista that's good when you have to make the builds.
      On the other way... I have been working on christine just a bit, I have fixed some small issues and there will be dbus support for christine soon garaged convince me some time ago that using dbus is good for christine, in this way, many programs can make use of christine functionality by communicating with it using dbus. Another thing that I'd like to implement is the keyboard shortcuts what allow me to use the prev, next, stop and play/pause buttons but I don't know if it's better to use the GNOME ones os allow the user to define their owns.
      As an extra-time-consuming little project.. I was wondering how to make a Dialog windows appears as the Mac OS X do. Personally I think MacOS X user interface is one of the most polished UI in the world and the Dialog box are pretty and make me feel that this is not another window in the workspace but a window that is really a child of the window where I was working on. Currently I'm thinking on a window with no decoration and a gtk.Layout area making the animation with a button. Let's see if I can have time for this in the week. ]]>
      http://islascruz.org/html/index.php/blog/show/This-week-on-Markuz-life....html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/This-week-on-Markuz-life....html Wed, 14 Jan 2009 23:13:19 -0600
      <![CDATA[ An easy one. ]]> I have two ways to iterate over sequence with a simple filter, one is making a filtered list and store it in a variable, then iterate over that filtered list, the second is put the mapping list in the for statement. Which one is faster and why?
      TIMES = 10000
      a = xrange(10000)
      c = [k for k in a if (k % 2) == 0]
      #
      def iterate(c):
          for i in c:
              pass
           
      def mapea():
          for i in [k for k in a if (k % 2) == 0]:
              pass
      #
      for i in xrange(TIMES):
          iterate(c)
      #
      for i in xrange(TIMES):
          mapea()
       
      100 points for the first comment with the right answer.
      Update: Zodman wins (even when he is not a python newbie)... the iterate function is making just one iteration over a list with the filterered items, the second (mapea) is creating this filtered list in every iteration, so, mapea uses two for cycles and that's why it is slower. ]]>
      http://islascruz.org/html/index.php/blog/show/An-easy-one..html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/An-easy-one..html Fri, 19 Dec 2008 23:54:33 -0600
      <![CDATA[ Christine 0.2.1 ]]> As usual you may download from sourceforge.net, this are the links: ]]> http://islascruz.org/html/index.php/blog/show/Christine-0.2.1.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine-0.2.1.html Thu, 18 Dec 2008 20:32:15 -0600 <![CDATA[ Christine 0.2.0 ]]> Im proud to announce the release of Christine 0.2.0. I have been working with it for several weeks and after fixing some bugs reported I feel it quite stable to be used for everyone.
      What's the new?
      • This version makes use of the sqlite3 python module to store info in a SQLite 3 database file.
      • The item lists have been reworked and now they are faster than ever.
      • We have early support for plugins :-)
      • Re worked TreeModel wich makes christine load faster
      • gconf dependency is removed.
      • Notify bubbles and TrayIcon are now plugins easy to be enabled/disabled.
      • Plugin for Pidgin.
      • Plugin for twitter (for those that want to tweet their songs)
      Where can I have it? Thank you to everyone who contribuite with this release, bug submitters, patch submitters, packagers and users. ]]>
      http://islascruz.org/html/index.php/blog/show/Christine-0.2.0.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine-0.2.0.html Sun, 07 Dec 2008 01:37:22 -0600
      <![CDATA[ Debugging with pydev ]]>


      My first attempt to create video tutorials :-) ]]>
      http://islascruz.org/html/index.php/blog/show/Debugging-with-pydev.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Debugging-with-pydev.html Fri, 05 Dec 2008 17:52:43 -0600
      <![CDATA[ Python 3000 ]]>


      Yeap.. Python 3000 or Py3k hit the streets. I'm more than glade to hear about the new version of this powerfull programming language. It seems that was yesterday when I watch a video where Guido Van Rossum was talking about the propossal for this new version and excusing the lack of compatiblity with the 2.x python series.
      I like the idea that this language is evolving even with this move (which for me is too risky) where we are going to be forced to modify our programs if we want in the future be compatible with Python. ]]>
      http://islascruz.org/html/index.php/blog/show/Python-3000.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Python-3000.html Thu, 04 Dec 2008 23:58:03 -0600
      <![CDATA[ Python Logging: RotatingFileHandler ]]> Whenever you write a computer program that is going be a service is recommended that this program saves somewhere what is doing, most of the popular services do it (Apache, Cherokee, MySQL, Put your service here:___________________), or maybe you have a desktop application where you want to write what is doing maybe for debug purposes.
      Fortunately this is an easy task if you use Python's Logging module. This module have several handlers, some of them to write to the standardError, to a Socket, to the syslog and many others
      One of my favorite handler is the
      RotatingFileHandler This module creates a log file, when this file is full (if you set the maximum bytes per file flag) it is renamed, appending the .1 and a new file is created with the same name as main log file. You can set up the max number of files to be created.
      This module (logging) is good, easy to use, but you have to use the RotatingFileHandler with care, or you will have two, three or more files being filled and then, your logs will be in N files..
      When you create your Logger Object you can set the log level, which can be INFO, WARNING, DEBUG, ERROR, CRITICAL and EXCEPTION, you already realized which level prints what. You can set the Handler, and this is where using the RotatingFileHandler becomes a bit trickier.
      In your applications you may want to have several loggers, one for each module you have in your application. If you plan to use the RotatingFileHandler you have to use the same handler for every Logger you are creating if you plan this Logger to use the same file. If you don't do this then you will end with something saving logs in your main file, and every other data will be stored somewhere else.
      This is because when you try to save a something in your log, the handler check the log size, and if the file size is >= maxbytes makes the rollover, if you are using several handlers related to the same file, then the handler that realize first that the size of the log file reach its max size will do the rollover but this will not take effect in the other handlers, so, one handler will be logging in the newly created file while the others will be logging to the old file and now you have two files growing.
      To avoid this, just use the same fucking handler for every logger you are creating if you plan to use the same file.
      Another issue I face with logger what the fact that if you call two time s to the same logger.. I mean:
      a = logging.getLogger('chanchanchan')
      b = logging.getLogger('chanchanchan')
      When you make something like this:
      a.info('This is a test')
      You'll se this:
      This is a test
      This is a test
      Yes, you are calling a to write "This is a test" but in your log file appears two times (or N times you have created a logger with the same name). So, its better for you to have something like a manager that gives you the logger already created with that name if exists or create it for you.
      Let's do an example:
      This is a small program that logs something in a endless cycle:
      #!/usr/bin/env python
      # -*- encoding: latin-1 -*-
      import sys
      import time
      from logger1 import LoggerManager
      a = LoggerManager().getLogger('a')
      b = LoggerManager().getLogger('b')
      c = LoggerManager().getLogger('c')

      while 1:
              t = time.time()
              for index,i in enumerate((a,b,c)):
                      msg = str(index) + repr(t)
                      i.debug(msg)
                      time.sleep(0.005)
       
      And this is the logger class, singleton module can be downloaded from Here
      #!/usr/bin/env python
      import logging
      import logging.handlers
      from Singleton import Singleton
      import os
      if os.name == 'nt':
              LOGPATH = 'C:\\'
      else:
              LOGPATH = './'
      class LoggerManager(Singleton):
              def __init__(self):
                      self.loggers = {}
                      formatter = logging.Formatter('%(asctime)s:%(levelname)-8s:%(name)-10s:%(lineno)4s: %(message)-80s')
                      level = 'DEBUG'
                      nlevel = getattr(logging, level, None)
                      if nlevel != None:
                              self.LOGGING_MODE = nlevel
                      else:
                              self.LOGGING_MODE = logging.DEBUG
                      self.LOGGING_HANDLER = logging.handlers.RotatingFileHandler(
                                              os.path.join(LOGPATH, 'log_event.log'),'a',524288, 10)
                      self.ERROR_HANDLER = logging.handlers.RotatingFileHandler(
                                              os.path.join(LOGPATH,'log_error.log'),'a',524288, 10)
                      self.LOGGING_HANDLER.setFormatter(formatter)
                      self.LOGGING_HANDLER.setLevel(self.LOGGING_MODE)
             
              def getLogger(self, loggername):
                      if not self.loggers.has_key(loggername):
                              logger = Logger(loggername,
                                              logging_handler= self.LOGGING_HANDLER,
                                              error_handler = self.ERROR_HANDLER,
                                              logging_mode = self.LOGGING_MODE)
                              self.loggers[loggername] = logger
                      return self.loggers[loggername]
      class Logger:
              '''
              Implements the christine logging facility.
              '
      ''
              def __init__(self, loggername, type = 'event', logging_handler= '', error_handler = '', logging_mode = ''):
                      '''
                      Constructor, construye una clase de logger.
                     
                      @param loggername: Nombre que el logger tendra.
                      @param type: Tipo de logger. Los valores disponibles son : event y error
                                              por defecto apunta a event. En caso de utilizarse otro
                                              que no sea event o error se apuntara a event.
                      '
      ''
                      # Creating two logger, one for the info, debug and warnings and
                      #other for errors, criticals and exceptions
                      self.__Logger = logging.getLogger(loggername)
                      self.__ErrorLogger = logging.getLogger('Error'+ loggername)
                      # Setting Logger properties
                      self.__Logger.addHandler(logging_handler)
                      self.__Logger.setLevel(logging_mode)
                      self.__ErrorLogger.addHandler(error_handler)
                      self.__ErrorLogger.setLevel(logging_mode)
                      self.info = self.__Logger.info
                      self.debug = self.__Logger.debug
                      self.warning = self.__Logger.warning
                     
                      self.critical = self.__ErrorLogger.critical
                      self.error = self.__ErrorLogger.error
                      self.exception = self.__ErrorLogger.exception
       
      I hope this help you. ]]>
      http://islascruz.org/html/index.php/blog/show/Python-Logging.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Python-Logging.html Tue, 02 Dec 2008 22:30:22 -0600
      <![CDATA[ Call for testers and translators ]]> christine release, the christine development team have been working on improving christine, and think it is time to make a new release, but before, we want you to test it and report every single fail you detect. We also make use of launchpad's translation page.
      You can find the code Here, the page for tracking bugs is Here, and the translations are Here. ]]>
      http://islascruz.org/html/index.php/blog/show/Call-for-testers-and-translators.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Call-for-testers-and-translators.html Fri, 21 Nov 2008 01:30:11 -0600
      <![CDATA[ Netbeans 6.5 ]]> Netbeans 6.5 release shows an Early Access Netbeans IDE for Python ]]> http://islascruz.org/html/index.php/blog/show/Netbeans-6.5.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Netbeans-6.5.html Thu, 20 Nov 2008 13:24:48 -0600 <![CDATA[ What's your favorite programmer cartoon? ]]>

      What's your favorite programmer cartoon? ]]> http://islascruz.org/html/index.php/blog/show/What%27s-your-favorite-programmer-cartoon%3F.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/What%27s-your-favorite-programmer-cartoon%3F.html Wed, 19 Nov 2008 23:57:15 -0600 <![CDATA[ 2008-11-16 ]]> In this week I have been pretty busy, bugfixing the Juvi desktop application. We don't want Banana products (those that mature with the user) and the test team is doing their best to hit every bug and report it to have a very stable application.
      I have been also busy "porting" the Supramax Evo4 driver to run on windows, the port is quite easy to do since the program was written in Python and I have to fix some paths. In my tests I was doing to the driver I found a Not so funny issue with M2Crypto for MS Windows.
      We have a parameter in the driver, as most Unix programs do the "-v" do a verbose run, spitting to the stdout the logs, if you don't use the verbose parameter then it saves it somewhere. Well, running on verbose mode was easy, it just run perfectly, storing the logs wasn't I had an error with OpenSSL... but wait.. we where talking about logs and not about OpenSSL.. what does OpenSSL has to be with logs?.
      Well, there is an issue with M2Crypto and Python where it doesn't ship a special file and this causes OpenSSL crash if you use I/O. M2Crypto let you load a RSA key in pem format that you can use to crypt/decrypt something this method is called load_key and is part of the M2Crypto's RSA package, you only have to pass the path to the key as first argument and in the second argument a function (anything callable) that returns the password for the key (if it is private). Well, this I/O was crashing M2Crypto.
      There are two workarrounds for this. The first, is to compile at least M2Crypto (I didn't do it, some blogs says that you have to compile python) against OpenSSL and include this specific file... at least Google points to blogs that says that... The other and easier way is just use RSA's function load_key_string where you pass as first argument the string that holds the key instead the path, doing this you will eliminate the I/O done by OpenSSL and then, there is no crash.
      Last Thursday Cristina and I went to Maquiavelo's house to an informal meeting with xbitcarry, unfortunately Maquiavelo was too busy and the meeting wasn't really done but was nice to see xbitcarry again.
      I think that's all for today my readers. Fortunately I don't have to work tomorrow and now I have to work a bit on christine ]]>
      http://islascruz.org/html/index.php/blog/show/2008-11-16.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/2008-11-16.html Sun, 16 Nov 2008 23:08:00 -0600
      <![CDATA[ Playing with gtk.Calendar ]]>

      I'm writing a desktop application for ICTC where the user must select a day in in a calendar. I start using gtk.Calendar because is an easy to use Calendar widget, but I this program also have to set the days available for the user to pick.
      I didn't find this on the gtk.Calendar widget, but tought it may be easy to do by subclassing gtk.Calendar. And here is my first approximation:
      #!/usr/bin/env python
      import gtk
      import calendar

      class Calendar(gtk.Calendar):
              def __init__(self):
                      gtk.Calendar.__init__(self)
                      self.available_days = ()
                      self.last_selected_day =  None
                      self.connect('day-selected', self.__check_day_available)
                      self.connect('map', lambda *args: self.__set_available_days())
                     
             
              def set_available_days(self, *args):
                      '
                      Let you set the days availables on the month
                      @args: days to be used.
                      '

                      nargs = [k for k in args if isinstance(k, int)]
                      self.available_days = tuple(nargs)
              def __check_day_available(self, calendar):
                      '
                      Check if the selected day is available, if not,then
                      try to select the last available day selected, and if can'
      t
                      then select the first available day in the available_days list
                      '
                      day = self.get_property('
      day')
                      if not day in self.available_days:
                              nday = False
                              if self.last_selected_day:
                                      nday = self.last_selected_day
                              elif self.available_days:
                                      nday = self.available_days[0]
                              if nday:
                                      self.select_day(nday)
                      print self.get_date()
             
              def __set_available_days(self):
                      '

                      Set a range of days that are not going to be marked and thus,
                      free days for the user.
                      '
                      if not self.available_days:
                               self.set_sensitive(False)
                      month = self.get_property('
      month')
                      days = calendar.mdays[month]
                      for i in range(1,days+1):
                              if not i in self.available_days:
                                      self.mark_day(i)
                      #Force the calendar to select the first day available
                      day = self.get_property('
      day')
                      self.select_day(day)
      if __name__ == '
      __main__':
              window = gtk.Window()
              window.connect('
      destroy', gtk.main_quit)
              a = Calendar()
              a.set_available_days(1,2,3,5,8,13,21)
              window.add(a)
              window.show_all()
              gtk.main()
      Update: Syntax Highlight sucks and change the code to a simple "pre" tag
      Update: returned to Syntax highlight. in Jaws 0.8.6 is working fine again :-) ]]>
      http://islascruz.org/html/index.php/blog/show/Playing-with-gtk.Calendar.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Playing-with-gtk.Calendar.html Fri, 17 Oct 2008 01:37:36 -0500
      <![CDATA[ 2008 10 08 ]]> So, it is time to post again.. this time is to post about christine. Christine as many of you know is a small project of mine, it must be an easy to use and small (and cute) media player, It start as some gstreamer play and then it becomes the music player I use for my every day, no longer rhythmbox nor banshee, wich are fine, but, not for me.
      The project is slow, mostly because I code on it when I need something else or just want to fix something that don't like me. Why? because I get almost no feedback. So, if you use christine or, you want to see this project to grow up, please, test it and fill bugs or request features so we can work on it or maybe you want to cooperate with this project in another way, like writing documents, doing artwork or something like that.
      The last two weeks GaRaGeD have been working on christine too, on the Pidgin "plugin" which is a nice plugin and I have been doing my work too. This makes me fell good, when you are not the only one in the project it feels better, when you can discuss some point to other project mates and know what would be the better for the average user.

      pidgin and christine

      Well, I'm working on the plugin interface and in the last.fm plugin for christine, I already have the authorization part, and then create the configuration dialog for the plugin, this requires me to get familiar with last.fm but, if you already use last.fm and want some feature that you already have in another player, please comment here or on the feature request tracker for the christine project.
      On the paid work side, I have been working a lot with Gtk, and reading about the Human Interface Guidelines, have you noted that the GNOME Human Interface Guidelines are quite similar to the Apple Human Interface Guidelines. Well, I hope this helps me to create more intuitive and very usable gtk interfaces.
      On the personal side. Cristina and I are really happy, last friday we went to the gynecologist and we see our baby, he is three months right and everything looks right. I have nothing more to say, Im happy!
      Just to close this post, if you use mac or compiz, how does looks likeyour desktop right now using the Exposé or the Scale plugin on compiz

      Desktop
      ]]>
      http://islascruz.org/html/index.php/blog/show/2008-10-08.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/2008-10-08.html Wed, 08 Oct 2008 02:03:00 -0500
      <![CDATA[ About my life ]]> Well, I think you just don't care abot my life, is quite boring for everyone that is not me. Why? just because this is not the blog of some kind of nerdy hacker that do lot of shiny new and amazing stuff, nor the guy that post every single fart that Apple, ubuntu nor Microsoft does.
      So, what is about this blog? I think is a way to flush my mind. I wish I have all the time to write more posts, Several times I had Ideas to be written in the blog, but they didn't come to the blog because (again) there is no time.
      Anyway, three paragraphs are enough for my complaints. So, what have I done since my last Post? (the christine love, the picture is not..a post) Well, let me see... let me see... Lot of work. I have been working on this project on ICTC, a desktop application using Python and PyGtk.
      User interface design is a quite interesting challenge, and more if you need to design input forms, make them look good, being user friendly (mmm, user friendly... If user friendly means scratching the testicles {or your favorite scratch part of the body} of the users. This application in some forms, need to be fully functional without mouse and use only the key pad, which makes the challenge more interesting. Writing a form that makes input validation, key-press-event handling for every widget, looks good, be ultra-easy to use is... is sometimes castrating... (the more if the client want the application in this color: #FF00FF.)
      Obviously I don't have to see the application in that color, but I also have to write a color chooser for this application, if I don't, then the client is going to ask me to change the colors after 15 days using the program or when it get almost blind.
      Well. This is most of the work I have done, I'm trying to learn how to use django. I love python, and I want to use django (or another python based framework) to write web applications in the future. I have write some applications but nothing really functional by now. One of the first and small projects I want to do is a web page for christine.
      And talking about christine, I'm still working on the new version. I'm refactoring modules. And by now is quite usefull. Just commit this night fixes for the bug #2122313 but I need people to test it to check it is working fine. I have also fixed the open remote dialog that wasn't working since I reallocate this methods.
      Well, I thinks is enough for today. See you latter.
      Update I forgot, If you like the season 1 of The Big Bang Theory you can the download links from Here, those rar files don't have the subtitles, I will post them there too. I have been watching this tv serie and I love it. ]]>
      http://islascruz.org/html/index.php/blog/show/Aboutmylife.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Aboutmylife.html Fri, 26 Sep 2008 02:30:19 -0500
      <![CDATA[ Giving love to christine ]]>



      Giving love to christine, originally uploaded by markuz.

      This is my desktop testing some changes I have done to christine in this night. Most of them code cleaning and some harmless optimizations.

      Update: I have made a screencast, you can download it


      here


      Update: Maybe you want to see the full resolution video ]]>
      http://islascruz.org/html/index.php/blog/show/Givinglovetochristine.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Givinglovetochristine.html Fri, 12 Sep 2008 00:52:54 -0500
      <![CDATA[ HotKeys on Windows using Python ]]> One of challenges for me in this application is that as it must run in the background there must be a way to raise it, the most easy way to do it is by force the user to click on the small icon in the notification area, but in this case, that was impossible because the computer don't have any mouse, everything is done with the keyboard.
      So, I start googling for some way to use hot keys with GTK (PyGtk) in this case, I found that Gtk does have a way to represent the Display wich a way to get to your computer display resources. I just want to grab the keyboard presses and if the right key with the right modifier where pressed then the application arises.
      Unfortunely for me, Gtk+ does have a way to do this, but the implementation in PyGTK has a bug where all the display events are ignored, I mean, every time you check of a pending event for the display pygtk will return None, so, no event, no catch, no working code.
      Well, in linux you can do this by using the xlib bindings for python, but I have to do this on Windows, so a workmate point me to
      This url. Wich shows how to register a hot key on windows.
      That was easier than I thought!. But, there is a trick... As you can see in this piece of code:
      try:
        msg = wintypes.MSG ()
        while user32.GetMessageA (byref (msg), None, 0, 0) != 0:
          if msg.message == win32con.WM_HOTKEY:
            action_to_take = HOTKEY_ACTIONS.get (msg.wParam)
            if action_to_take:
              action_to_take ()
          user32.TranslateMessage (byref (msg))
          user32.DispatchMessageA (byref (msg))
       
      The method GetMessageA is the one that is listening to the messages in the system, and returns when there is a message. If you use a single threaded program, like... some text bassed application or just a "show something" application, then it will be nice, but, if you use Gtk, where the application's events are handled in the gtk main loop this is useless, why? because this method locks until it receives something, and then let your application work, but, if you have it in a while loop you will never leave that loop and then, your signals will never been emited and your handler will never do their job. Is something similar to the use of sockets. Ha... I forgot, you can't use the while gtk.events_pending(): gtk.main_iteration_do() stuff.. it doesn't work, keep reading if you wanna know why.
      So, what can I do for this to work?, well, I thought: A thread, but, there is a problem. Windows documentation says that the hotkey registerd with the method RegisterHotKey will only be catched with GetMessageA if the "register" method and the "get message" are in the same thread.
      So, what can I do? Put this on the same thread, and then use a flag to let the rest of your application know that the keys have been pressed, then, raise your application. But, why I can't make a gobject based class that emits a signal when this keys are pressed? Well, you should know that Gtk+ is thread aware, but not thread safe, this means, you cannot use Gtk accross the threads, and this is something inherited from gobject (AFAIK).
      Here's the code that will let you register hot keys on windows and make your applications raise when you need them.
      #!/usr/bin/env python
      import ctypes
      import thread
      import win32con
      import gobject
      from ctypes import wintypes
      class keyhandler:
              def __init__(self):
                      self.__emit = False
                      thread.start_new_thread(self.__catchMsgs, tuple())
                      gobject.timeout_add(5,self.checkEmit)
             
              def checkEmit(self):
                      if self.__emit:
                              self.emit('keyhandler-keypress',self,self.__emit)
                              print 'Emitiendo senial..'
                              self.__emit = False
                      return True
              def __catchMsgs(self, *args):
                      byref = ctypes.byref
                      user32 = ctypes.windll.user32
                      self.HOTKEYS[1] = {'hotkey' : win32con.VK_F3,'modifiers': win32con.MOD_WIN}
                      if not user32.RegisterHotKey (None, 1, win32con.MOD_WIN, win32con.VK_F3):
                              print "Unable to register id", 1
                      while 1:
                              try:
                                      msg = wintypes.MSG()
                                      if user32.GetMessageA (byref (msg), None, 0, 0):
                                              if msg.message == win32con.WM_HOTKEY:
                                                      if self.HOTKEYS.has_key(msg.wParam):
                                                              self.__emit = self.HOTKEYS[msg.wParam]
                                              user32.TranslateMessage (byref (msg))
                                              user32.DispatchMessageA (byref (msg))
                              except:
                                      pass
       
      ]]> http://islascruz.org/html/index.php/blog/show/HotKeysonWindows.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/HotKeysonWindows.html Wed, 10 Sep 2008 01:03:05 -0500 <![CDATA[ Christine folder import ]]> .flickr-photo { border: solid 2px #000000; } .flickr-yourcomment { } .flickr-frame { text-align: left; padding: 3px; } .flickr-caption { font-size: 0.8em; margin-top: 0px; }



      christine, originally uploaded by markuz.

      This is christine (trunk) importing a whole folder, about 1321 songs in just 1:07 mins.

      ]]>
      http://islascruz.org/html/index.php/blog/show/christine-1.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/christine-1.html Tue, 09 Sep 2008 16:27:34 -0500
      <![CDATA[ Christine using 6Mb ]]>



      screenshot3.png, originally uploaded by markuz.

      This is a screenshot quite surprising for me, this is the gnome-system-monitor saying that christine uses just 6Mb of my RAM. I was looking for memory leaks in one of the applications that I'm currently developing in ICT Consulting, and I found that the memory used by one program, that memory that just belongs to the program is the Writeable memory and that is the memory you should be aware.
      I have to say, christine was doing nothing, Just launch it and listen some music, then for one reason that I don't remember, just set it to pause and I get over another task, now, looking at the process table, christine is using more thatn 6 Mb.
      btw.. Im using Christine 0.1.6.

      ]]>
      http://islascruz.org/html/index.php/blog/show/Christineusing6Mb.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christineusing6Mb.html Sun, 17 Aug 2008 23:00:26 -0500
      <![CDATA[ Christine in launchpad ]]> sourceforge.net si no longer maintained, the reason: I cannot commit my changes to the svn repo, then, I cannot share the newest code.
      Christine is now a registered project in Launchpad, well, christine has been a in launchpad for a while but never really use it. So, I will use the launchpad christine account. The bug tracker, the code (and all the good things that launchpad offers) will be hosted here.
      As part of the change, christine no longer use Subversion, instead, will use Bazaar, you can get the code using this:
      bzr branch lp:christine ]]>
      http://islascruz.org/html/index.php/blog/show/Christineinlaunchpad.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christineinlaunchpad.html Sun, 03 Aug 2008 10:56:51 -0500
      <![CDATA[ Christine love in the night ]]>



      Christine love in the night, originally uploaded by markuz.

      1:47 in the morning. Im still giving some love to christine, that personal proyect that I used to code frequently. Now, it takes some days before I can toch it.
      I'm working on the sqlite3 storage layer, This should help me with a more unified data between multiple "sources" that should be renamed as playlists. This will be usefull for many other features, I'm thinkin in some kind of browser.
      Anyway, I'm still in the process. I'd like to share the code I have, but SourceForge.net's SVN service is bothering me with a 403 (Forbidden) error that don't let me commit my changes. Now I'm seriously change the project host. What do you recommend?

      ]]>
      http://islascruz.org/html/index.php/blog/show/Christineloveinthenight.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christineloveinthenight.html Thu, 24 Jul 2008 01:57:45 -0500
      <![CDATA[ Creating a gtk custom model ]]> ICT Consulting. We found a problem with many many rows in gtk.ListStore. This is a common problem with Gtk's ListStore and TreeStore. Both are easy to implement and convenient if you are not going to work with too many values. I'm thinking in a couple of thousands. As far as this, the TreeModel is quite usable, but if you use a TreeFilterModel and/or TreeModelSort then you will experience some performance issues.



      If what you want to do is just map the main application and then fill the model you can use the idle_add gobject function to iterate over your data and then store it in your model without freezing your application, but it is at the same way, the slowest. You can put chunks of 20 or so, then every time you application runs the callback function will run a small but faster insertion. Anyway, this is still a bit slow.



      I have been doing tests with 100,000 rows, in the easy way there are just numbers using a for cycle via a range() result.I think in Gtk, the smaller is the data stored in the model, the faster it goes, because I can insert 100,000 rows in a gtk.ListStore in 7 seconds aprox. while in christine, inserting 2600 row in christine (with more data per cell) takes a lot more.



      Anyway, the application that I'm developing shows a list of customers, this is a growing list as new customers are added, in our tests we need to show up to 17,000 customers. Using gtk.ListStore takes at least 17 seconds on my machine just to show it, but we also have a filter model becuse search in a list of 17000 items is not easy if you go looking every row by hand. So, usig the FilterModel takes almost the same time in searching something. Obviusly, waiting 17 seconds for the result is not an option, even worse, you made a mistake and wrote LOPEX instead LOPEZ.



      So, I was searching over internet what can I do. I have already use the common 'tweaks' to improve the gtk.ListStore performance and I have reached the 8 - 9 seconds over those 17,000 items, but even with this, its too much time. The search points me to the gtk.GenericTreeModel. This generic model allows you to create a custom model where you can make your own tweaks to improve the performance of your model. In the link above gives you the way to use it. I have alreade created my own custom model and it really relly made the things better.



      Now, one of the problems that gtk.GenericTreeModel have are the memory leaks. Using this model you may use lots of memory. This is because the GTM use to create a reference to the value that you are returning as Iter, e.g. you are using a list of lists, where you store the values, every item in the list is a row, then, the index if the iter wich references to the list you are storing in that row. The problem is that the GTM increase the reference count of you node (the list inside of the list) to aviod row destruction and then use the iter. This, in the best will make your values been refered until you destroy your model (and any reference to the data), in the worse the reference count of your data will never been unrefered and then the memory will never be freed.



      You can use the invalidate_iters every time you modify the rows (add or delete) to make the rows invalid and then decrease the reference count of the row, and when your data have no more references then be deleted. But, I have the problem that the reference count was never decreased when I destroy the window or the model. Where is the trick here, use the Python's garbage collector, and your memory will be freed.



      So, the new model based on PyGtk's GenericTreeModel actually works for us. Inserting 17,000 takes just 1 second, and the search (filter) is the same thing, 1 second is an option. I would like to see everything just appear when you request it, but one second is good for now. And testing with my current christine music list it takes just 0.06 seconds to show the list. Inserting 100,000 items (the easy way, just numbers) takes just 1.164 seconds to get filled with four columns and 2.36 seconds to show itself (creating a filter model and setting it to a treeview), so, for now this kind of optimizations will work for us, there are other optimizations on the Filter model and the treeview, My goal is to create something similar to wat Aaron bockover do with banshee.

      Gtk Custom Model

      Note: Test times are approximate, cache, cpu usage, load average and other may cause the times change, but at the end give us an idea of what is going on.
      ]]>
      http://islascruz.org/html/index.php/blog/show/Creating-a-custom-model.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Creating-a-custom-model.html Sat, 17 May 2008 10:24:50 -0500
      <![CDATA[ Testing the new christineConf module ]]>


      Testing the new christineConf module, originally uploaded by markuz.

      I have been working in the configuration module for christine, something similar to gconf, but just for christine. Why? well, many people complains because christine needs the gnome-extras package, where gconf is, and to be honest, christine didn't use all the gconf power, so, there isn't a big reaons to keep gconf on christine.
      This isn't the only thing I have been working on. I'm trying to improve many things for the next release. Most of the work wil be in the list, zodman gives me some nice ideas, and I will try to implement them.
      Anyway, you are also invited to work with me in the christine development. You can join the maling list for the next release.

      ]]>
      http://islascruz.org/html/index.php/blog/show/TestingthenewchristineConfmodule.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/TestingthenewchristineConfmodule.html Sat, 03 May 2008 23:38:30 -0500
      <![CDATA[ Christine 0.1.6 ]]>
      christine 0.1.6
      CLick to enlarge


      This is the new release of Christine Media Player. This release include:
      HelpMenu.png
      1. Some bugfixes
      2. Reworked code in Sources list
      3. Reworked display.
      4. Improved import code (no more freeze while looking for the media files)
      5. Multiple Sources list.
      6. Translate Christine and Report a bug menuitems
      You can download it from sourceforge:




      ]]>
      http://islascruz.org/html/index.php/blog/show/Christine-016.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine-016.html Tue, 29 Apr 2008 13:45:20 -0500
      <![CDATA[ PyGTK y Threads ]]>
      gtk.gdk.threads_init()
       
      Esto lo tendras que hacer antes de iniciar algun thread. Y luego, al usar algun thread debes englobarlo dentro de
      gtk.threads_enter()
      thread.start_new(funcion, (arg1,arg2,argN))
      gtk.threads_leave()
       
      Solo recuerda que no debes manipular gtk fuera del thread en el que esta corriendo el ciclo principal (gtk.main_loop).
      Si lo que necesitas es estar cachando informacion en un thread aparte y modificar la interfaz (ej. Leyendo un socket y mostrando informacion de cuanto llevas leido) entonces usa alguna bandera y modifica tu apariencia en el thread principal, de lo contrario tendras problemas con gobject y glib. ]]>
      http://islascruz.org/html/index.php/blog/show/PyGTK-y-Threads.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/PyGTK-y-Threads.html Thu, 10 Apr 2008 18:51:44 -0500
      <![CDATA[ Translation status ]]>

      Translation status in christine

      Wanna help? Translate christine HERE! ]]>
      http://islascruz.org/html/index.php/blog/show/Translation-status.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Translation-status.html Tue, 12 Feb 2008 16:57:22 -0600
      <![CDATA[ Profiling Python ]]> Profiling and Optimizing Python ]]> http://islascruz.org/html/index.php/blog/show/Profiling-Python.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Profiling-Python.html Thu, 22 Nov 2007 08:40:15 -0600 <![CDATA[ Widgets 'recortados' en Gtk ]]> Gtk tienen una ventana asociada, y no precisamente la ventana con decoracion que todo mundo ve. Gtk adiere una propiedad llama "window" a los widgets al ser empacados, o emparentados a otro widget contenedor.
      Generalmente estos widgets son de apariencia rectangular, pero es posible tunearlos para que tengan la forma que nosotros queremos. La forma mas facil de hacerlo es tomar una imagen un usarla como "Molde" para crar nuestro contenedor recortado. aunque tambien es posible dibujar lo que nosotros querramos usando las funciones de cairo sobre un contexto (Que en si, es lo que hacemos con la imagen molde, pero mucho mas sencillo).
      Lo que hacemos es obtener un molde a partir de una imagen, es decir, abrimos la imagen y creamos un gtk.gdk.Pixbuf, que es el mostraremos, pero podemos obtener el gtk.gdk.Pixmap y la mascara de este Pixbuf de forma que podamos usar dicha mascara para crear el contorno de nuestro widget.
      Los widgets, una vez empacados,como ya habia dicho obtienen una propiedad llamada window, que pertenece a la clase gtk.gdk.Window. Aquellos que ya se han puesto a dibuar algo con cairo se habran dado cuenta que se obtiene un contexto de un widget a partir de su gtk.gdk.Window.
      Bien. tambien es posible obtener este contexto de cairo a partir de un pixmap, hacer el dibujo molde y luego pegarselo a la ventana para que gtk.gdk sepa que partes ha de dibujar y cuales no.
      Veamos un pequenio ejemplo.
      class shapedWindow(gtk.DrawingArea):
              def __init__(self):
                      gtk.DrawingArea.__init__(self)
                      self.__pixbuf =  gtk.gdk.pixbuf_new_from_file('./logo.png')
                      self.connect('size-allocate',self.size_allocated)
                      self.connect('expose-event',self.do_expose_event)
                      self.set_size_request(self.__pixbuf.get_width(),
                                      self.__pixbuf.get_height())
             
              def size_allocated(self,win,allocation):
                      w,h = (allocation.width, allocation.height)
                      self.bitmap = gtk.gdk.Pixmap(None,w,h,1)
                      context = self.bitmap.cairo_create()
                     
                      self.do_expose_event(self,'',context)
                      parent = self.get_parent()
                      win.shape_combine_mask(self.bitmap,0,0)
                      parent.shape_combine_mask(self.bitmap,0,0)
                     
              def do_expose_event(self, widget, event,allocate = False):
                      if allocate:
                              context = allocate
                      else:
                              context = self.window.cairo_create()
                      if allocate:
                              context.set_operator(cairo.OPERATOR_DEST_OUT)
                              w,h = (self.allocation.width, self.allocation.height)
                              context.rectangle(0,0,w,h)
                              context.set_source_rgb(1,1,1)
                              context.paint()
                      context.move_to(0,0)
                      context.set_operator(cairo.OPERATOR_OVER)
                      if allocate:
                              pixmap,mask = self.__pixbuf.render_pixmap_and_mask()
                              context.set_source_pixmap(mask,0,0)
                      else:
                              context.set_source_pixbuf(self.__pixbuf,0,0)
                      context.paint()
             
      if __name__ == '__main__':
              window = gtk.Window()
              window.set_decorated(False)
              a = shapedWindow()
              window.add(a)
              window.show_all()
              gtk.main()
             
       
      Que es lo que hacemos aqui? bien, primero creamos un widget personalizado usando gtk.DrawingArea y conectamos la sennial size-allocate para poder establecer el tamanio de nuestro widget. Una vez llamada esta funcion creamos un pixmap vacio del tamanio de nuestro widget, que es el tamanio que nos ha dado el contenedor padre, este es un rectangulo como de costubre, con un ancho y alto. A este pixmap le sacaramos el cairo context, sobre el cual hemos de 'dibujar' nuestro molde.
      Como en este ejemplo el widget y su molde de la misma forma estoy aprovechado el metodo do_expose_event para hacer el dibujo inicial y despues hacer las funciones de redibujado en caso de un evento de expose.
      Quienes hacen la chamba aqui? bien, para el dibujo inicial de nuestro widget es context.set_source_from_pixmap(), aunque podriamos usar el mismo set_source_from_pixbuf he detectado problemas con colores en Windows, entonces no lo recomiendo.
      Otro que entra en juego y es el que le dice al widget 'orale cabron, apegate a esta forma' es win.shape_combine_mask(self.bitmap,0,0).
      De ahi, el ponerle contenido a nuestro widget no es mas que un amanipulacion de colores y demas dentro de nuestro contexto cairo. Que, es otro tema del que hablar, como 'dibujar' lo que queremos en nuestro widget usando su contexto cairo.

      Shaped Window widget
      Tamanio Completo

      Ciertamente, el logtipo de Christine es el widget 'recortado' :-) ]]>
      http://islascruz.org/html/index.php/blog/show/Widgets-recordatos-en-Gtk.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Widgets-recordatos-en-Gtk.html Fri, 09 Nov 2007 17:19:06 -0600
      <![CDATA[ Sockets ]]> GTK+ que es el que corresponde a la termina de la esquina inferior izquierda. Otro cliente es puro texto, que es el que esta en la parte superior, y el servidor es la terminal alargada que esta en el centro.

      screenshot5.png

      Lo que muestran las terminales no es mas que pura informacion loggeada usando el modulo logging de python
      En los proximos dias, ya que tenga el codigo mas limpio vere la forma de ponerlo al publico. ]]>
      http://islascruz.org/html/index.php/blog/show/Sockets.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Sockets.html Wed, 31 Oct 2007 18:22:09 -0500
      <![CDATA[ Imprimir a un archivo PDF usando GTK. ]]> Perfecto. En esta semana me ha tocado estar trabajando sobre un programita que ando haciendo, el cual debe correr sobre Linux y MS Windows >= 2000. El desarrollo se esta haciendo en Python usando GTK para la interfaz grafica, pero me he encontrado uno que otro problemita con GTK, sobre todo con el manejo de ventanas, aunque el que mas tiempo me ha llevado ha sido el de impresion.
      Gtk+ a partir de la version 2.10 incluye soporte para impreision en Linux y otros Unix'es gracias a CUPS, mientras que en Windows lo hace de manera nativa con el sistema de impresion de Windows.
      Debo decir que en linux esta cosa es la maravilla, En windows no tanto, pero funciona decentemente si tus requerimientos no son tan especiales.
      Los requerimientos para imprimir son estos:
      • Debe imprimir en la impresora por defecto
        • NO debe mostrar el dialogo de seleccion de impresora
      • Debe imprimir en el tamanio determinado por el programa
      En linux, repito, esto es una maravilla, solo le digo imprime usando la constante gtk.PRINT_OPERATION_PRINT y con esto no me muestra el cuadro de dialogo, previamente he creado la operacion de impresion y le he dicho que seleccione la impresora por defecto, en linux, si en settings.set_printer() le pasas el parametro '' usa la impresora por defecto, es mas, si no usas el metodo set_printer usa la impresora por defecto.
      Pero en Windows la cosa no es tan bonita. para empezar Siempre muestra el cuadro de seleccion de impresora (punto menos). Y para acabarla de amolar, aunque tengas una impresora predeterminada y esta impresora este seleccionada mandas imprimir (Alt +m o ENTER) habra un error porque GTK no ha configurado las cabeceras de impresion para mandarle el 'win32-driver', 'win32-driver-extra' y otros parametros fumados de los que Windows sabe. Obviamente, si seleccionas otra impresora y regresas a la que esta por defecto estos parametros son llenados y entonces la impresion funciona "bien". Obviamente, como no queremos que el usuario vea el cuadro de impresion esto no es opcion.
      Lo siguiente es, obtener la impresora por defecto y mandar establecer los encabezados, para esto se pueden valer del modulo win32print
      import win32print
      printerName = win32print.GetDefaultPrinter()
      printer = win32print.OpenPrinter(printerName)
      printerValues = win32print.GetPrinter(printer,2)
      dir(printerValues['pDevMode'])
       
      Y pueden valerse del gtk.PrintSettings.set() para poner los encabezados.
      Esto les sera util cuando ustedes quieran mostrar el cuadro de impresion, a fin de que lo muestre y espere una configuracion por parte del usuari, o en caso de que no se configure nada por parte del usuario, usar las configuraciones por defecto.
      Hasta aqui todo bien, pero, Yo no quiero el cuadro de impresion!, solo quiero que imprima.
      Bien, yo no queria hacerlo asi, pero pues bueno, no hay de otra.
      if os.name == 'nt':
              filename = './ultimafactura.pdf'
              op.set_export_filename(filename)
              action = gtk.PRINT_OPERATION_ACTION_EXPORT
      elif '-d' in sys.argv:
              action = gtk.PRINT_OPERATION_ACTION_PRINT_DIALOG
      else:
              action = gtk.PRINT_OPERATION_ACTION_PRINT
      try:
              response = op.run(action)
      except:
              response = gtk.PRINT_OPERATION_RESULT_ERROR
      if response == gtk.PRINT_OPERATION_RESULT_ERROR:
              settings = op.get_print_settings()
              settings.foreach(funcPrintKeys)
              print "Hubo un error a imprimir"
      elif response == gtk.PRINT_OPERATION_RESULT_APPLY:
              if os.name == 'nt':
                      filename = './ultimafactura.pdf'
                      import win32api
                      win32api.ShellExecute(0,
                                      'print',
                                      filename,
                                      None,
                                      '.',
                                      0)
       
      La solucion ha sido crear un archivo PDF, usando el PrintOperation.set_export_filename() para despues usar win32api.ShellExecute() para imprimir.
      Que es lo que hace ShellExecute?. Bien, ejecutara el comando que tu le des, en este caso 'print' sobre el archivo dado por el siguiente parametro "filaname", el siguiente parametro son los parametros al programa que va a realizar la operacion, el siguiente, el directorio de trabajo y por ultimo un valor entre 0 y 1 que dice si se ha de mostrar o no la ventana del programa que ha de realizar la operacion.
      Para esto, es necesario tener en Windows un programa que pueda abrir e imprimir PDF. Obviamente el mas conocido es Adobe Acrobat Reader, pero Adobe Acrobat Reader es un Monstruo si lo unico que queremos es impresion. Asi que, lo que he hecho es utilizar Foxit PDF Reader, el cual es mucho mas ligero y rapido.
      Y eso es todo, ese ha sido el cucharazo porque GTK por defecto no te utiliza la impresora por defecto, ni te esconde el cuadro de impresion en Windows.
      En fin. el chiste es lograr que las cosas jalen.
      Un ejemplo sencillo de impresion lo pueden encontrar Aqui ]]>
      http://islascruz.org/html/index.php/blog/show/Imprimir-a-un-archivo-PDF-usando-GTK.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Imprimir-a-un-archivo-PDF-usando-GTK.html Fri, 19 Oct 2007 10:18:44 -0500
      <![CDATA[ Christine 0.1.1 ]]> El equipo de desarrollo de Christine se complace en presentarles la nueva version de Christine, 0.1.1, Esta version es una version corregida de Christine 0.1, es decir, no implementa cosas nuevas, solo mejora lo que ya estaba.
      Pueden descargar las fuentes de Christine 0.1.1 Aqui, y revisar las notas de liberacion Aqui.
      Gracias a todos los que han cooperado con el desarrollo de Christine. ]]>
      http://islascruz.org/html/index.php/blog/show/Christine-011.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine-011.html Fri, 21 Sep 2007 14:10:38 -0500
      <![CDATA[ Usando el widget creado anteriormente ]]>

      widgetTest.ogg
      ]]>
      http://islascruz.org/html/index.php/blog/show/Usando-el-widget-creado-anteriormente.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Usando-el-widget-creado-anteriormente.html Fri, 14 Sep 2007 16:44:13 -0500
      <![CDATA[ Un contenedor GTK Redimensionable al gusto. ]]> gtk.Fixed, Este contenedor nos permite poner widgets de manera estatica en nuestra aplicacion. Es decir, si la ventana cambia de tamanio los widgets no se redimencionaran y tampoco cambiaran de posicion. Pocos lo utilizan por esto, pero a veces es necesario.
      Pues resulta que en una de las aplicaciones lo tengo asi, simplemente porque los widgets NO se tienen que mover ni cambiar de tamanio si la ventana se redimenciona, aqui yo lo veo como algo bueno. En fin, El problema del GtkFixed es que nomas no me cacha los eventos, y meterlo en un gtk.EventBox me parece no tan optimo, puesto que yo quiero que los eventos los cache el Widget, no un EventBox.
      Mi primer intento de solucion: Crear una clase que herede de gtk.Fixed y cachar los eventos para que cuando el cursor este dentro de un punto determinado se pueda redimencionar al muy puro estilo de click-arrastra-suelta. Problema, gtk.Fixed no me cacha los eventos, incluso si se los agrego a manita con gtk.Fixed.add_events.
      Segundo intento: Hereda primero de un gtk.EventBox y luego de un Fixed: Si cacha los eventos, No te muestra ni madres. Inviertelo, Si te dibuja, pero no te cacha los eventos... (ya me estoy desesperando)
      La solucion?, Bueno, nunca le habia echado el ojo al gtk.Layout,
      entonces heredo de un gtk.Layout primero, este no me cacha los eventos, pero, me permite dibujar como si fuera un gtk.DrawingArea aunque tienes que dibujar sobre el bin_window de tu layout (gtk.Layout.bin_window) en lugar del window como tipicamente se hace en gtk.DrawingArea. Bien, tu segunda herencia es de un EventBox para poder cachar las seniales, y listo :-).
      Es importante que Primero se herede de gtk.Layout y luego de algun otro widget (gtk.DrawingArea tambien funciona) para que Gtk no reniegue al tratar de agregar widgets a tu gtk.Layout.
      El codigo seria mas o menos asi (Estoy seguro que de alguna manera se puede mejorar):
      class groupWidget(gtk.Layout,gtk.EventBox):
              '''
              Una version modificada del gtk.Fixed
              '
      ''
              def __init__(self):
                      gtk.Layout.__init__(self)
                      gtk.EventBox.__init__(self)
                      self.__buttonPressed = False
                      self.set_name('groupWidget')
                      self.set_size_request(50,50)
                      self.set_property('events',
                                      gtk.gdk.EXPOSURE_MASK |
                                      gtk.gdk.ENTER_NOTIFY_MASK|
                                      gtk.gdk.POINTER_MOTION_MASK |
                                      gtk.gdk.BUTTON_RELEASE_MASK |
                                      gtk.gdk.BUTTON_PRESS_MASK )
                      self.add_events(
                                      gtk.gdk.EXPOSURE_MASK |
                                      gtk.gdk.ENTER_NOTIFY_MASK|
                                      gtk.gdk.POINTER_MOTION_MASK |
                                      gtk.gdk.BUTTON_RELEASE_MASK |
                                      gtk.gdk.BUTTON_PRESS_MASK )
                      self.connect('expose-event',self.__exposeEvent)
                      self.connect('motion-notify-event',
                                      self.__motionNotify)
                      self.connect('button-press-event',
                                      self.__buttonPressEvent)
                      self.connect('button-release-event',
                                      self.__buttonReleaseEvent)
             
              def __motionNotify(self,widget,event):
                      if self.__buttonPressed:
                              x,y = self.get_pointer()
                              if (x,y ) > (0,0):
                                      self.set_size_request(x,y)
                                      self.__lastWH= [x,y]
              def __buttonPressEvent(self,widget,event):
                      w,h = self.__lastWH
                      px,py = self.get_pointer()
                      if event.button == 1:
                              if w > px > w-5 and  h > py > h-6:
                                      self.__buttonPressed = True
             
              def __buttonReleaseEvent(self,widget,event):
                      if event.button == 1:
                              self.__buttonPressed = False
              def __exposeEvent(self,widget,event):
                      '''
                      Encargada de dibujar el widget
                      '
      ''
                      context = self.bin_window.cairo_create()
                      x,y,w,h = self.allocation
                      self.__lastWH = [w,h]
                      context.set_line_width(1)
                      context.set_antialias(cairo.ANTIALIAS_NONE)
                      #Dibujamos el relleno y el borde
                      context.move_to(0,0)
                      context.rectangle(1,0,w-1,h-1)
                      context.rectangle(1,0,w-1,h-1)
                      context.set_source_rgba(1,1,1,0.5)
                      context.fill_preserve()
                      context.set_source_rgb(0,0,0)
                      context.stroke()

                      #Dibujamos un pequenio rectangulito
                      # en la parte inferior derecha.
                      context.rectangle(w-5,h-6,5,5)
                      context.set_source_rgb(0.5,0.5,0.5)
                      context.stroke()

       
      Y se deberia ver asi:



      En el video se puede apreciar que el boton esta dentro del contenedor, por eso de corta cuando el tamanio del contenedor es menor (se pueden usar Scrollbars gracias a la capacidad de gtk.Layout. ]]>
      http://islascruz.org/html/index.php/blog/show/Un-contenedor-GTK-Redimensionable-al-gusto.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Un-contenedor-GTK-Redimensionable-al-gusto.html Thu, 13 Sep 2007 16:23:52 -0500
      <![CDATA[ Respuesta ]]> Armando: En las escuela esta muy dificil que te ensenien a usar PHP, y esta aun mas dificil que te ensenien a usar Python, mas cabron aun, que te ensenien a usar GTK. Desafortunadamente en mexico las escuelas estan dedicadas a enseniar cosas como Java o .NET porque:
      1.- Es un circulo vicioso, los profesores lo saben, lo ensenian a los alumnos, los alumnos aprenden, la mayoria de los alumnos no aprenden otra cosa, y cuando les toca enseniar solo pueden enseniar lo que saben, asi terminan dando Java.
      2.- Muchas escuelas estan casadas con Microsoft, asi que por fuerza lo han de dar :).
      De PHP hay infinidad de libros, y tutoriales libres muy buenos por la red, el libro con el que yo empece con PHP es con el de 'Proyectos Profesionales con PHP' de editorial ANAYA,
      De Python, te recomiendo el tutorial de python que esta en la documentacion de python, 'Dive Into Python' y 'How to think like a computer scientist learning with python' .
      De Gtk, Hay un tutorial muy bueno en la documentacion de PyGTK.
      Un comentario, si piensas aprender PHP para usar GTK, te recomiendo mejor aprender Python para usarlo con GTK. ]]>
      http://islascruz.org/html/index.php/blog/show/Respuesta.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Respuesta.html Thu, 09 Aug 2007 15:35:56 -0500
      <![CDATA[ Amo a PyGTK ]]> Aun no termino el programa, me faltan varios detalles, pero para 2,3 dias que llevo en el vamos bien. Lo que me encanta es que programo desde linux con Vim y pruebo en windows. Obviamente, no se permite que cada maquina tenga una conexion directa con base de datos, asi que mejor abrimos un socket en una maquina 'servidor' y los clientes solo piden datos ahi.

      I love GTK
      En GNU/Linux

      I love GTK
      En Windows

      ]]>
      http://islascruz.org/html/index.php/blog/show/Amo-a-PyGTK.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Amo-a-PyGTK.html Wed, 08 Aug 2007 08:34:08 -0500
      <![CDATA[ Christine -deb ]]> pcero.net Pcero se han iniciado en el mundo de la empaquetada para debian, y ha creado un paquete de Christine para ubuntu Feisty Fawn. Este paquete tiene los cambios hecho al dia 26 de Julio. ]]> http://islascruz.org/html/index.php/blog/show/Christine--deb.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine--deb.html Fri, 27 Jul 2007 10:11:54 -0500 <![CDATA[ Christine for birthday! ]]> Piratearle Metodos a un objeto para hacer empapelados y crear un ambiente de desarrollo mas sencillo. Todo esto es en lo que se esta trabajando y formar??????? parte de christine.
      Otras cosas en las que he trabajado es en bugfixes para la version 0.1 y peque??????±as mejoras (que he de agregar lo otro). Lo mejor es que ahora christine tiene un mejor soporte para archivos m3u y pls y que tiene un "display" que ahora se dibuja con los colores del theme.

      Christine
      ]]>
      http://islascruz.org/html/index.php/blog/show/Christine-for-birthday.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine-for-birthday.html Thu, 26 Jul 2007 12:56:34 -0500
      <![CDATA[ "Piratearle" las propiedades a un objeto en Python ]]> Uno y quieres que obtenga las propiedades de la clase Dos o Tres, Por que harias esto?, simplemente porque en tu programa no quieres lidiar con
      import uno,dos,tres
      if "uno":
          refrerencia = uno()
      elif "dos":
          referencia = dos()
      else:
         referencia  = tres()
       
      Y despues averiguar sobre quien haces la instancia en cada parte de tu codigo que requiera una instancia, de hecho, no es escalable, agregar una referencia mas seria doloroso si tu codigo es grande. mejor es hacer un empapelado de las referencias y hacer instancia a una sola, y que esta se haga pelotas de a quien referenciar.
      Una forma de acercarse seria usar esto:
      class wrapper:
          def __init__(self,modulo):
              moduloobj = __import__("paquete",globals(),locals(),[modulo])
              referencia = vars(moduloobj)[modulo]
              self.__empapelado = referencia()
       
      Para obtener refrencias de las propiedades de un objeto usamos getattr, getattr recibe como primer parametro el objeto en el que se buscar??????? la propiedad y como segundo, el nombre de la propiedad en cadena.
          def Query(self,metodo,*args):
              '''
              @param string metodo: Nombre del metodo en cadena
              @param *args: argumentos a pasar al metodo.
              '
      ''
              met = getattr(self.__empapelado,metodo)
              if callable(met):
                  return met(*args) #ejecutamos el metodo y regresamos lo que nos regrese
       
      Y tener:

      a = wrapper("uno") #o "dos", o "tres"

      a.Query("imprimeEsto","Texto a imprimir")
      Esto, desde mi punto de vista es ideal, pues tu codigo es limpio, pero tal vez quieres hacer el empapelado sobre un proyecto que ya tiene rato jalando, y que todo se hace referencia a una clase, pero, quieres que esta clase ahora sea el "empapelado". Puedes Piratearle las propiedades a otro objeto, asi:
      #!/usr/bin/env python
      import paquete
      class Pirata:
              '''
              Se piratea las propiedades de un objeto.
              '
      ''
              def __init__(self,modulo,objeto):
                      '''
                      Constructor
                      '
      ''
                      moduloobj = __import__(paquete,globals(),locals(),[modulo])
                      referencia = vars(moduloobj)[modulo]
                      pirateable = getattr(referencia,objeto)()
                      for i in dir(pirateable):
                              newkey = i.replace("_%s_"%objeto,"_Pirata_")
                              self.__dict__[newkey] = getattr(pirateable,i)
       
      Para tener algo asi:

      a = test.Pirata("modulo","clase")

      a.imprimeEsto("Texto a Imprimir")
      De esta forma, no cambias nada en tu codigo que ya tienes, simplemente, en alguna parte de tu codigo, indicas que el "empapelado" ha de piratearle las propiedades a otro objeto que haga las operaciones necesarias. ]]>
      http://islascruz.org/html/index.php/blog/show/Piratearle-las-propiedades-a-un-objeto-en-Python.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Piratearle-las-propiedades-a-un-objeto-en-Python.html Tue, 24 Jul 2007 11:35:27 -0500
      <![CDATA[ Como dibujar un imagen (jpg, png, gif, etc..) en Cairo ]]>
      def setPixbuf(self,pixbuf):
              if type(pixbuf) != gtk.gdk.Pixbuf:
                      raise TypeError("Pixbuf debe ser %s recibido %s"%(gtk.gdk.Pixbuf, type(pixbuf)))
              self.__Pixbuf = pixbuf
              self.emit("expose-event",gtk.gdk.Event(gtk.gdk.EXPOSE))

      def exposeEvent(self, widget,event):
              x,y,w,h = self.allocation
              try:
                      context =  self.window.cairo_create()
              except AttributeError:
                      return True
              if self.__Pixbuf != None:
                      scaledPixbuf = self.__Pixbuf.scale_simple(ancho,
                                      alto,
                                      gtk.gdk.INTERP_BILINEAR)
                      ct = gtk.gdk.CairoContext(context)
                      ct.set_source_pixbuf(scaledPixbuf,BORDER_WIDTH,BORDER_WIDTH)
                      context.paint()
                      context.stroke()
       
      Y listo :-) ]]>
      http://islascruz.org/html/index.php/blog/show/Como-dibujar-un-imagen-jpg-png-gif-etc-en-Cairo.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Como-dibujar-un-imagen-jpg-png-gif-etc-en-Cairo.html Sat, 21 Jul 2007 10:52:16 -0500
      <![CDATA[ Alo dotpy! ]]> planetario de dotpy. Espero ver mas gente en este planetario. :-) ]]> http://islascruz.org/html/index.php/blog/show/Alo-dotpy.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Alo-dotpy.html Mon, 16 Jul 2007 08:19:48 -0500 <![CDATA[ Creando tus propios objetos con gobject y error con las seÃ?Æ?Ã?±ales. ]]>

      <nombredeObjecto object (paquete+modulo+nombredeObjeto) at 0xb7b6f34c&rt;
      Pues es facil, en nuestra clase tendremos esto:
      #notese que estoy haciendo una subclase de gtk.Widget.
      class nombredeObjeto(gtk.Widget):
         def __init__(self):
             gobject.GObject.__init__(self)
             self.set_name("nombredeObjeto")
      gobject.type_register(nombredeObjeto)
       
      Asi de facil :-), el nombre que mostrara despues del "<" sera lo que definas en set_name ]]>
      http://islascruz.org/html/index.php/blog/show/Creando-tus-propios-objetos-con-gobject-y-error-con-las-seales.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Creando-tus-propios-objetos-con-gobject-y-error-con-las-seales.html Thu, 05 Jul 2007 12:08:01 -0500
      <![CDATA[ Creando clases de Python en C ]]> pero aqui va mas o menos como se hace. No encontre mucha documentacion sobre la implementacion de clases de Python en C, pero le seguir??????© buscando.
      Algo que tambien me puse a buscarle hoy, fue como usar variables globales. es algo muy sencillo de lograr, algo que los programadores en C me diran, "Pues si, pendejo, asi se hace", pero yo no sabia, y alguien por ahi no sabr??????? tampoco, asi que ahi va:
      suponiendo que tenemos un modulo demo, en python seria algo asi:
      nombre = ""
      apellido = ""
      def asignaDatos(nom,ape);
          nombre = nom
          apellido = ape
      def doSomething():
          print nombre
          print apellido
       
      para poder usar algo asi:
      Python 2.4.3 (#1, Jul 26 2006, 20:13:39)

      [GCC 3.4.6] on linux2

      Type "help", "copyright", "credits" or "license" for more information.

      >>> import demo

      >>> demo.asignaDatos("marco","islas")

      >>> demo.doSomething()

      marco

      islas

      >>>
      en C seria asi:
      #include <Python.h>
      #include <stdio.h>
      #include <stdlib.h>

      struct pers {
          char *nombre;
          char *apellido;
      };
      struct pers persona;
      static PyObject *doSomething(PyObject *self, PyObject *args){
          extern struct pers persona;
          printf("%s\n",persona.nombre);
          printf("%s\n",persona.apellido);
          free(persona.nombre);
          free(persona.apellido);
          Py_INCREF(Py_None);
          return Py_None;
      }

      static PyObject *asignaDatos(PyObject *self, PyObject *args){
          extern struct pers persona;
          char *nombre,*apellido;
          persona.nombre = malloc (1024);
          persona.apellido = malloc(1024);
          PyArg_ParseTuple(args,"ss",&nombre,&apellido);
          strcpy(persona.nombre,nombre);
          strcpy(persona.apellido,apellido);
          Py_INCREF(Py_None);
          return Py_None;
      }
      static PyMethodDef demoMethods[] = {
          {"doSomething",doSomething,METH_VARARGS,"imprime los valores de la persona"},
          {"asignaDatos",asignaDatos,METH_VARARGS,"Asigna los datos de la persona en la estructura"},
      };
      PyMODINIT_FUNC initdemo(void){
          (void) Py_InitModule("demo",demoMethods);
      }

       
      ]]>
      http://islascruz.org/html/index.php/blog/show/Creando-clases-de-Python-en-C.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Creando-clases-de-Python-en-C.html Wed, 04 Jul 2007 18:08:30 -0500
      <![CDATA[ Christine 0.1rc2.deb ]]> nibblesmx ha creado un paquetin para Ubuntu Feisty de Christine 0.1.rc2. Puedes obtenerlo aqui ]]> http://islascruz.org/html/index.php/blog/show/Christine-01rc2deb.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine-01rc2deb.html Wed, 04 Jul 2007 13:01:43 -0500 <![CDATA[ Work and Fun! ]]> Grupo de usuarios de software libre de Poza Rica (GNUPR) por no haber podido asistir a las tres ultimas reuniones, me fue imposible, la primera, andaba en salamanca en ICTC, y las otras dos por motivos personales, espero en estas semanas compensar.
      Como ya lo mencion??????© en el post anterior, he estado usando Eclipse por un ratito, no saben lo facil que me ha hecho desarrollar en Python con el plugin PyDev, ojo, aun no uso las PyDev extensions, pero puede que en un rato pague la licencia, dependiendo de que tan bien me sienta en un futuro.
      Que es lo bueno?, bien, pues el debugger me ayuda algo, pero el autocompletado, el docstring, el hecho de que analiza mi codigo en el vuelo y me dice si tengo algun error de sintaxis, el crear un modulo o un paquete me queda a un click, el navegador me muestra mis modulos, sus clases y propiedades sean publicas o "privadas". Es un buen chunche muy bonito, muy practico. Ademas, en ICTC usamos svn para manejar las revisiones del software, asi que use el subclipse (el plugin de tigris.org para manejar subversion en eclipse) y todo va sweet, incluso el hecho de que no se hace autenticacion por contrase??????±a sino por llave dsa, muy bonito.
      Tambien he estado utilizando Tomboy para mis notas, ya me estoy acostumbrando a usarlo :-).
      En la semana me fui a Huauchinango a renovar mi licencia de manejo, no tengo fotos porque se me olvido la camara (junto con mi celular) en la casa, pero me di cuenta de algo genial, las oficinas de MySpace.com en mexico han cerrado o se han reubicado puesto que el local esta en renta. En cuanto vaya de nuevo, tomare foto a lo que eran las "oficinas".
      Creo que es todo por ahora. ]]>
      http://islascruz.org/html/index.php/blog/show/Work-and-Fun.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Work-and-Fun.html Sat, 23 Jun 2007 23:44:40 -0500
      <![CDATA[ Cambiando el color de nuestros widgets en GTK. ]]> Lo ideal para cambiar el color de un widget seria dejarlo al libre gusto del usuario, pero a veces necesitamos que un widget tenga X o Y color (gimmie?). Bien para cambiar el color de un widget basta con un simple:
      map = widget.get_colormap()
      color = map.alloc_color("white") #Se puede usar codigo RGB #FFFFFF
      widget.modify_bg(gtk.STATE_NORMAL,color)
       
      Ciertamente, no es lo mejor, pero puede que lo necesitemos, y mejor es tenerlo y saber como hacerlo. ]]>
      http://islascruz.org/html/index.php/blog/show/Cambiando-el-color-de-nuestros-widgets-en-GTK.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Cambiando-el-color-de-nuestros-widgets-en-GTK.html Fri, 08 Jun 2007 13:15:21 -0500
      <![CDATA[ Christine 0.1rc2 ]]> christine-0.1rc2.tar.bz2 ]]> http://islascruz.org/html/index.php/blog/show/Christine-01rc2.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine-01rc2.html Mon, 04 Jun 2007 19:56:30 -0500 <![CDATA[ Christine 0.1rc1 ]]> Anyway, I need you to test it before I upload it to sourceforge.net servers.
      get it at: http://islascruz.org/html/data/files/christine-0.1rc.tar.bz2
      And what's the new in christine 0.1 againts 0.0.3??
      • Faster, I mean, really faster import.
      • Very simple radio station support.
      • Drag'n'Drop queue add.
      • lots of bugs fixed.
      Go, test it and report your bugs :-) ]]>
      http://islascruz.org/html/index.php/blog/show/Christine-01rc1.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine-01rc1.html Fri, 01 Jun 2007 16:26:59 -0500
      <![CDATA[ Happy Sunday for Christine ]]> Christine Bug Squash I'm Happy because we (nibblesmx and I) fixed some bugs, 5 bug reports where fixed and closed while some others are still open waiting for some user testing (even that they where fixed and in my machine it works fine).
      Tanks to Pcero and Jose Oviedo, for their bug reports.
      Things that I like more about Christine is:
      • Support for radio stations. (via Open Remote) Now you can just copy the Url of the .pls or m3u file and christine will play it.
      • Improved the Visualization mode. Now it works on the radio stations too. And if you aren't playin Christine and activate it, when you hit the play button it will work (no wait until next song or deactivate and reactivate).
      • Improved the time for importing I have been working with signals, and at least in my machine it runs smooth, Importing my 1865 songs in just 2 or 3 minutes (hey, fetching all that data isn't easy in GStreamer, and I know there are some other libraries, but we have to be able to fecth this data (tags) with all Media Files supported by GStreamer not only mp3 and vorbis ogg)
      Some things still need some work:
      • Some keyboard bindings are broken.
      • The player display (where videos and visualization shows up) steals events if it is in focus.
      • There are a bunch of features that I'd like to include in next release.
      ]]>
      http://islascruz.org/html/index.php/blog/show/Happy-Sunday-for-Christine.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Happy-Sunday-for-Christine.html Sun, 22 Apr 2007 22:04:13 -0500
      <![CDATA[ Christine bug squash ]]>
      Se llevar??????? a cabo un bug squash de christine este fin de semana, buscando la liberaci???????n de la primera estable. Si usas christine y quieres cooperar, reporta tu bug en el Bug Tracker. Los bugs permanecer???????n abiertos hasta el fin de semana, en donde les daremos mate. ]]>
      http://islascruz.org/html/index.php/blog/show/Christine-bug-squash.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine-bug-squash.html Tue, 17 Apr 2007 10:36:49 -0500
      <![CDATA[ I listen my music with Christine ]]>
      Since almost a year ago, I'm listening my music with the player that I have been building. Yeap, sure, ain't need a flashing-all-in-one player (those that even serve coffe), so, my needs are almost fill.
      Talking about christine, I have fixed some minor bugs yesterday, and Also "automatize" the Radio experiment. Here comes the user feedback. Pcero, is a hard user of somafm and other radio stations, while people use to have Gigabytes of music, he just play it from the radio on internet (and uses all that Gb for movies or something like that). Pcero have been asking for the internet radio support, and after my "experiment" he start using christine for that. Pcero is a bit annoying, because he criticizes everything!, but in some way, that's good, user feedback is good. ]]>
      http://islascruz.org/html/index.php/blog/show/I-listen-my-music-with-Christine.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/I-listen-my-music-with-Christine.html Thu, 05 Apr 2007 10:05:13 -0500
      <![CDATA[ Christine code clean bugfix ]]>

      bigfixing Christine

      I also integrate a "--devel" option in christine, that let you work with christine from the source code directory. I mean, checkout the christine code, then run autogen.sh, run configure, make, and then just run christine like this: "./christine --devel" from the top of the source directory. Useful for people (coff coff developers coff coff) that want to try, not to install.
      As always, my invitation to Check it out, test it, and fill our Bug tracker ]]>
      http://islascruz.org/html/index.php/blog/show/Christine-code-clean-bugfix.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine-code-clean-bugfix.html Fri, 23 Mar 2007 07:57:31 -0500
      <![CDATA[ Christine for today!! ]]>
    • Package lib_christine have been changed to libchristine.
    • Most of the bugs generated by the code clean are solved.
    • and....

    http://www.christine-project.org/

    ]]> http://islascruz.org/html/index.php/blog/show/Christine_for_today.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine_for_today.html Wed, 14 Mar 2007 19:11:43 -0500 <![CDATA[ Christine moves.. ]]>
  • demrit have been working in the code clean and he is doing a very great job.
  • He also create some clases like Singleton and Validator, and improve some others.
  • Christine has been moved from cvs to svn.
  • There are some ideas about the Plugins stuff, we are still researching.
  • We are three developers now (demrit, nibblesmx and me, although only demrit have been working in this week).
  • SVN code is broken by now but it will be fixed when the code clean gets done.
  • ]]>
    http://islascruz.org/html/index.php/blog/show/Christine_moves.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine_moves.html Fri, 09 Mar 2007 09:49:36 -0600
    <![CDATA[ Improved C launcher ]]> When I create the Christine launcher embedding Python into a C binary, I thought that the PyInitialize function creates the global environment and pases the arguments to the python script executed by PyRun_SimpleString(). Bud it doesn't. So, I have to use PyRun_String and create a Python list with the arguments and then, assign them to the sys.argv property in order to be used by the Python christine code.
    Thanks to Zodman and nibblesmx who help me with this C hell. ]]>
    http://islascruz.org/html/index.php/blog/show/Improved_C_launcher.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Improved_C_launcher.html Wed, 21 Feb 2007 07:56:22 -0600
    <![CDATA[ Video de Christine en atsion ]]>



    Estoy subiendo otro, donde se ve bien a christine en accion :-) pero esta conexion de infinitum no ayuda en mucho..
    Por cierto... para quien preguntaba cuantas lineas componen a Christine: son 3439 segun "wc" sin contar los descriptores de interface creados con glade :-), ni los Makefile.am regados en los directorios.
    Update: Un descripcion un poco mejor (y en atsion) de christine, hasta hoy termine de subirlo... les digo, Infinitum no ayuda de mucho..
    ]]>
    http://islascruz.org/html/index.php/blog/show/Video_de_Christine_en_atsion.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Video_de_Christine_en_atsion.html Sun, 18 Feb 2007 18:49:03 -0600
    <![CDATA[ Py2exe ]]> Py2exe, meramente por cuestiones de trabajo, mas que por gusto (entiendase: "Estoy usando Windows por cuestiones de trabajo mas que por gusto"), como diria el buen v1s0r: "Primero comer que ser cristiano".
    En fin, este modulo extiende las opciones de otro modulo llamdo distutils, y aprovechandonos del archivo setup.py podemos pedirle a python (por medio de py2exe) que nos genere un binario en windows que aparte de la ventaja de ser binario (para quienes no quieren compartir el codigo) evita la dependencia con Python. Obviamente, tu progamita de 30K se te va a 4 megas o mas dependiendo de los modulos que necesita.
    Actualmente lo he ocupado para la chamba y aprovechando lo que ya sabia, pues hice lo mismo con mi programita de inventario en mi negocio, esto si, nomas por gusto.
    De ahi te creas tu instalador con el Nullsoft Scriptable Install System y vual???????, te codeas en Python felizmente, no expones tu codigo (si es un programa propietario) y tu cliente sigue feliz porque no necesitar??????? instalarse Python en su sistema (al menos no por ti).
    Habia mencionado que puedes incluso hacer servicios con esto?, Pues se puede, pero presta atencion a crear una clase con una propiedad de nombre "_svc_name_" para poder iniciar el servicio, si no, ]]>
    http://islascruz.org/html/index.php/blog/show/Py2exe.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Py2exe.html Fri, 02 Feb 2007 18:30:00 -0600
    <![CDATA[ Imprimiendo usando GTK ]]> GTK+ dentro de Linux tiene ya mucho tiempo con los usuarios, se ha dado gracias a Gnome, mas no por GTK. Hasta hace poco GTK+ carec??????­a de un API para impresi???????n, y muchos tenian que integrar Gnome para poder hacer uso de este servicio.
    Bien, a partir de la version 2.10 de GTK+ se cuenta con un API para imprimir que si bien por ahora se utiliza en sistemas UNIX se pretende que sea un sistema portable para imprimir, es decir que con el mismo codigo se pueda imprimir tanto en Unix como en Windows.
    Bien, hoy por la ma??????±ana, yo digo que fue por que madrugu??????© me avente un clavado en busqueda de documentacion para usar la API de impresiond e GTK (pygtk precisamente) y no encontre ni madres, mas que un ejemplo que vi en este documento (P???????ginas 12 y 13). Y usando ese ejemplo hice lo mismo en Python:
    #!/usr/bin/env python
    import gtk,cairo
    def draw_page(PrintOperation,PrintContext,Page):
        context = PrintContext.get_cairo_context()
        context.set_source_rgb(1,0,0)
        context.rectangle(0,0,PrintContext.get_width(),50)
        context.fill()
        context.set_source_rgb(0,0,0)
        context.move_to(90,75)
        context.line_to(60,80)
        context.curve_to(40,70,65,65,70,60)
        context.set_line_join(cairo.LINE_JOIN_ROUND)
        context.set_line_width(5)
        context.stroke()
    window = gtk.Window()
    window.connect("destroy",gtk.main_quit)
    op = gtk.PrintOperation()
    settings = gtk.PrintSettings()
    op.set_print_settings(settings)
    op.set_n_pages(1)
    op.set_unit(gtk.UNIT_MM)
    op.connect("draw_page",draw_page)
    op.connect("done",gtk.main_quit)
    response = op.run(gtk.PRINT_OPERATION_ACTION_PRINT_DIALOG)
    if response == gtk.PRINT_OPERATION_RESULT_APPLY:
        settings = op.get_print_settings()
    gtk.main()
     
    y el resultado a la hora de imprimir es este:

    Print dialog in GTK dsc05756.jpg

    Como ven, no es tan dificil, lo dificil es "dibujar" el documento con Cairo :-). En fin..
    Nota: No, no es degradado el rectangulo ese, mi tonner rojo ya esta valiendo madres. ]]>
    http://islascruz.org/html/index.php/blog/show/Imprimiendo_usando_GTK.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Imprimiendo_usando_GTK.html Mon, 22 Jan 2007 11:43:34 -0600
    <![CDATA[ christine with the C launcher ]]> Christine have at the time I'm writing this a C written launcher. But Why?. Ok, this is Why: Its cooler to see christine in the process table than python christine.py. And when you want to kill christine you don't have to look into the python processes the PID of the python process running christine, just "killall christine" or something, those Deskbar Applet users will thank this :-)
    It works to me, and I will apreciate if you check it, mainly for the compiling issues in the makefiles. Code is available in the CVS.

    Screenshot-2.png
    ]]>
    http://islascruz.org/html/index.php/blog/show/christine_with_the_C_launcher.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/christine_with_the_C_launcher.html Wed, 17 Jan 2007 21:10:01 -0600
    <![CDATA[ Incorporando python en nuestros proyectos en C ]]> para evitar que el pid sea python.
    Cuando corremos un programa en python a estilo python miscript.py y vemos la tabla de procesos veremos que el pid pertenece al programa "python" y dentro de sus argumentos tenemos el "miscript.py", incluso cuando ejecutemos nuestro script asi: "./myscript.py". Mayor problema, no vamos a estar mirando la tabla de procesos siempre, o si? ;-)
    El problema, al menos conmigo es que soy muy huevon para andar buscando el pid y cositas asi, yo prefiero un "killall python", lo malo es que me termina mantando otros procesos de python como mi shell interactiva con la que practico peque??????±as piezas de codigo, o el mendigo (chupa-recursos) deskbar :-P.
    La soluci???????n, empotrar Python en un "lanzador" en C. el ejemplo que les pondre es la forma mas raza, escuata y todo lo que se puedan imaginar, pero funciona >:-), es algo que ya hice con Christine
    Primero moveremos nustro lanzador original escrito en python a algun paquetin
    cp christine lib_christine/christine.py
    Luego creamos el lanzador en c:
    #include
    int
    main(int argc, char *argv[])
    {
      Py_Initialize();
      PyRun_SimpleString("from lib_christine.christine import *\n"
                         "a = christine()\n"
                         "a.main()\n");
      Py_Finalize();
      return 0;
    }
     
    compilamos y enlazamos:
    $ gcc -Wall -O2 -march=k8 -mtune=k8 -I/usr/include/python2.4/ -c christine.c -o christine.o

    $ gcc -Xlinker -export-dynamic christine.o /usr/lib/python2.4/config//libpython2.4.a -lnsl -ldl -lreadline -ltermcap -lieee -lpthread -lutil -lm -o christine
    y vual???????, listo :-).
    Screenshot-2.png
    ]]>
    http://islascruz.org/html/index.php/blog/show/Incorporando_python_en_nuestros_proyectos_en_C.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Incorporando_python_en_nuestros_proyectos_en_C.html Wed, 17 Jan 2007 18:22:47 -0600
    <![CDATA[ Trabajando con gstreamer:: Usando los Bins ]]> Ok, el Playbin solo permite empotrar un elemento de audio para el sink de audio, lo que nos impide meter dos elementos, digamos "autoaudiosink" y nuestro "ecualizador", Tambien seria un pedote escribir nuestro "audiosink" por completo, lo unico que queremos es empotrar un ecualizador sin tener que programar todo. Bien, aqui es donde entran los Bins.
    Un GstBin permite "empacar" elementos dentro de ??????©l. Como un GstBin es en si un elemento, este puede ser empotrado en el PlayBin. Para crear el Bin utilizaremos gst.element_factory_make("bin"). Luego agregaremos los sinks con el metodo "add".
    audio = gst.element_factory_make("autoaudiosink")
    bin = gst.element_factory_make("bin")
    bin.add(audio)
     
    Hasta aqui el bin ya tiene empacado el elemento "audio" que ahora es propiedad de bin, si se destruye bin se destruye al elemento "audio". Hasta aqui todo bien, la cuestion es que el mismo bin no cuenta con ningun pad. Un pad es un "conector" entre los elementos, si no hay pads no hay donde conectar.
    Es aqui donde entra el GhostPad, El GhostPad nos permite crear un pad sintener que crear el elemento que lo contendr???????, y podemos enlazarlo (conectarlo) a un pad que si se encuentre dentro de un elemento. Luego, agregamos este pad a algun elemento y vual???????!!.
    import gst
    audio = gst.element_factory_make("autoaudiosink")
    ecualizador = gst.element_factory_make("ecualizador") #elemento ficticio
    bin = gst.element_factory_make("bin")
    bin.add(audio)
    bin.add(ecualizador)
    audio.link(ecualizador)
    # enlazamos con el pad "sink" de audio
    # Note que el nombre del pad es "sink" esto es importante porque
    # playbin busca por el pad con nombre "sink"
    ghost_pad = gst.GhostPad("sink",audio.get_pad("sink"))
    bin.add_pad(ghost_pad)
    # En este punto el bin ya tiene un elemento adentro (audio) y tiene un pad para poder
    # ser conectado
    playbin = gst.element_factory_make("playbin")
    playbin.set_property("audio-sink",bin)
     
    El pad con nombre "src" no es necesario ser creado, el playbin lo har??????? para poder enlazar los elementos (audio,video,visualizaci???????n). ]]>
    http://islascruz.org/html/index.php/blog/show/Trabajando_con_gstreamer_Usando_los_Bins.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Trabajando_con_gstreamer_Usando_los_Bins.html Mon, 15 Jan 2007 15:10:54 -0600
    <![CDATA[ Trabajando con gstreamer::Creando un Playbin ]]> Gstreamer es muy flexible, y se trabaja con pipelines, que vendria siendo como un conducto por el cual nuestro archivo de audio/video ha de pasar para ser procesado y poder llegar a nuestra pantalla/bocinas, tecnicamente se construlle un pipeline, luego se crean y se enlazan elementos (fuentes, demuxers, sinks etc..), se enlazan los elementos.... y al final del tunel se ve la luz. Pero esto es mucho trabajo para aquellos que son noveles con gstreamer y puede ser algo tedioso otros.
    Afortundamente gstreamer incluye un elemento llamado "Playbin", un playbin es un pipeline ya hecho, con otras funciones que permiten especificar el sink de audio, el de video y el de visualizacion. automaticamente determina el de fuente y en caso de no definirse los elementos de audio y video utiliza unos por defecto.
    Con esto podriamos de manera sencillicima empotrar un "mini-reproductor" a nuestras aplicaciones, por ejemplo, cuando querramos tener una "vista previa" de un archivo de audio, podriamos empotrar un miniplayer que tenga un boton play y que toque (de ser posible) el archivo seleccionado, para saber si es o no el indicado.
    Para crear un playbin utilizaremos la funcion "element_factory_make" esta funcion nos crear??????? un objeto de tipo GstElement, digamos que vendria a ser algo asi como un Widget en Gtk.
    import gst
    playbin = gst.element_factory_make("playbin")
     
    Con esto tenemos un elemento GstPlaybin, que ya incluye el pipeline, demuxers etc.. lo que nos resta es tunerarlo. Podremos modificar el audio-sink y video-sink por medio de sus propiedades:
    audio_sink = gst.element_factory_make("gconfaudiosink")
    playbin.set_property("audio-sink",audio_sink)
    video_sink = gst.element_factory_make("gconfvideosink")
    playbin.set_property("video-sink",video_sink)
     
    No hay necesidad de enlazar los elementos, el playbin lo har??????? por si mismo :-). En este ejemeplo estamos usando los sinks de gconf, para los usuarios de Gnome, estos retornan el sink establecido con gstreamer-properties. otros sinks validos los pueden buscar con gstreamer-inspect |grep sink.
    Ahora.. como hago que el playbin toque algo?. Sencillo, el playbin tiene una propiedad llamada "uri", un uri describe la ubicacion de un archivo, puede ser un archivo local, o en algun servidor remoto, o tal vez sea un track dentro de un dvd, o un CD de audio. Un uri, define su "protocolo" al inicio, tal y como lo hacen las direcciones de las paginas web "http","https" u otros protocolos como "ftp","rsync", etc..
    ejemplos:
    uri = "file:///home/markuz/algunmp3.mp3"
    uri = "http://www.islascruz.org/algunvideo.ogg"
    uri = "cdda:///1"
    uri = "dvd:///4"
     
    Obviamente, la capacidad del playbin para poder parsear el uri y reproducir el objeto depende de los plugins instalados.
    Una vez hecho esto, podremos decirle al playbin cual archivo tocar.
    import gst
    playbin = gst.element_factory_make("playbin")
    uri = "file:///home/markuz/algunmp3.mp3"
    audio_sink = gst.element_factory_make("gconfaudiosink")
    playbin.set_property("audio-sink",audio_sink)
    video_sink = gst.element_factory_make("gconfvideosink")
    playbin.set_property("video-sink",video_sink)
    playbin.set_state(gst.STATE_READY) #El playbin debe estar listo
    playbin.set_property("uri",uri)
    playbin.set_state(gst.STATE_PLAYING)
     
    Listo, con esto empezar??????? a tocar :-).
    Otras propiedades del playbin se pueden conocer con gst-inspect playbin ]]>
    http://islascruz.org/html/index.php/blog/show/Trabajando_con_gstreamerCreando_un_Playbin.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Trabajando_con_gstreamerCreando_un_Playbin.html Sun, 14 Jan 2007 21:28:39 -0600
    <![CDATA[ Lazy days and Plugins ]]> Lazy days:
    I have been so lazy this days, this is something that I believe is temporal, just like one of those days that I may spend coding all the fucking day. And I know what to do, I know what needs to be done, and I would like to do it, but im so lazy.
    And that's why christine is taking to long in get mature. I spit some lines in the day but not a real work. I just didn't really feel so inspired.
    But.. There is something...
    Plugins:
    I have, in this few inspirations, work over the plugins stuff, Its still very very early but, I'm trying to make a god environment to become christine into a plugable application. At this time I'm just creating the public interface, but also converting the "show properties" action (menu: edit/show properties) that show the tags of the selected item in the library, to a plugin. So, isn't by now a lib_christine package module. Ok, here is the shot:

    Show properties

    Somebody with plugins implementation knownledge and good will to work over this stuff, give me an email :-). ]]>
    http://islascruz.org/html/index.php/blog/show/Lazy_days_and_Plugins.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Lazy_days_and_Plugins.html Sat, 13 Jan 2007 19:44:05 -0600
    <![CDATA[ Utilizando las seÃ?Æ?Ã?±ales ]]> Gtk+ es genial para esto porque ya implementa un sistema de se??????±ales que podemos ajustar a nuestro programa.
    Por ejemplo, en christine a la hora de importar archivos los someto a un "descubridor", este chunche abre el archivo, busca por las etiquetas y avisa cuando hay etiquetas, luego, la biblioteca actualiza los campos con las etiquetas. En realidad no es mas que un playbin con fakesinks del cual tomo el bus y lo conecto a un watcher, cuando existe un mensaje de etiquetas agrego las respectivas etiquetas a la lista.
    Hasta aqui bien, pero al momento christine lo que hace al importar los archivos es utilizar un repetidor con "gobject.timeout_add", la ventaja es que funciona bien y es decentemente rapido, lo malo es que en CPUs con buenca capacidad no es enteramente aprovechada esta capacidad. Posible solucion, que se emita una se??????±al a quien llama cuando se descubran las etiquetas.
    Para hacer que nuestro objeto emita la se??????±al heredaremos de gtk.Widget y haremos esto:
    class library(gtk.Widget):
    ...
        def __init__(self):
            gobject.signal_new("tags-found",self,
                gobject.SIGNAL_RUN_LAST,
                gobject.TYPE_NONE,
                (gobject.TYPE_PYOBJECT,))
        def add_file(file):
            #algun codigo para agrear el archivo...
        def watcher(self,bus,message):
            # Algun codigo para manejar los mensajes
            self.emit("tags-found",self)
    def do_something(widget,userdata):
        #Codigo para manejar la se??????±al.
    li = library()
    li.connect("tags-found",do_something)
     
    Heredamos gtk.Widget para tener acceso a algunos elementos de gobject, si no se lo ponemos nos va a rebusnar sobre gobject.TYPE_PYOBJECT y utilizamos gobject.signal_new para definir nuestra se??????±al. Despu??????©s utilizamos self.emit para emitir la se??????±al. Obviamente, quien tenga una instancia a nuestro objeto debe conectar la se??????±al a un manejador.
    De esta forma nuestra clase library que resulta en un objeto heredado de gtk.Widget y no se empaqueta ni se muestra ni nada o aunque contenga otros widgets (por ejemplo, un gtk.TreeView y un gtk.TreeModel), puede emitir se??????±ales y puede alertar (en este ejemplo) que se han encontrado las etiquetas y que es hora de cargar un nuevo archivo. ]]>
    http://islascruz.org/html/index.php/blog/show/Utilizando_las_seales.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Utilizando_las_seales.html Sun, 07 Jan 2007 20:45:06 -0600
    <![CDATA[ Working in the plugins stuff. ]]> The plugins interface is still a mockup, and have to define public methods and properties available in the plugins to change the christine look and feel. At the moment, just let me show you how it looks like.

    Christine with a plugin

    I have also embed the lists queue and sources (and many others that may be) in the notebook. ]]>
    http://islascruz.org/html/index.php/blog/show/Working_in_the_plugins_stuff.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Working_in_the_plugins_stuff.html Wed, 03 Jan 2007 20:35:43 -0600
    <![CDATA[ Christine for Christmas ]]> Estoy orgulloso de anunciar que Christine ha liberado su primera version inestable. La version 0.0.1, esta version aun en faces de desarrollo es completamente usable para los fines y objetivos que Christine define, ser un reproductor de audio y video bonito y chiquito para Gnome.
    Christine depende de Gstreamer, Python, GTK 2.10 y sus bindings para Python. Si se desea se puede utilizar libnotify para ver esos popups apuntando a un icono en el area de notificaci???????n. configurable desde el area de notificaci???????n.
    Christine aun esta en fases de desarrollo y aun le faltan cosas, aunque lo he estado utilizando desde hace ya un buen rato y parece que todo va bien.
    Hago la invitacion a los pythoneros que vean esto y que se interesen en cooperar con un proyecto sencillo, aun chico y en crecimiento.
    El paquete con el codigo fuente se puede conseguir en la p???????gina de descargas.
    Feliz Navidad :-)
    Update1:: Un peque??????±o error en la linea de comandos de gcc ha sido corregido y un nuevo paquetin te espera en la zona de descargas, gracias damog por apuntarlo. Cualquier error/bug favor de reportarlo al Bug Tracker. Gracias de nuevo y feliz navidad. ]]>
    http://islascruz.org/html/index.php/blog/show/Christmas_Christine.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christmas_Christine.html Sun, 24 Dec 2006 18:04:37 -0600
    <![CDATA[ Christine and the i18n job ]]> christine, he subido algunos archivos .po al CVS y un peque??????±o script para sacar las cadenas traducibles de los descriptores de interface hechos con Glade-3 y los que se escriben directamente en el codigo, por ejemplo los titulos de las columnas.
    Hablando de Glade, usando glade 2 puedes pedirle a glade que todas las cadenas traducibles te las guarde en un archivo de texto plano, estas cadenas puedes ser facilmente obtenidas con xgettext usando la codificacion de C. Pues vaya relajo, que con Glade-3 estos archivos ya no se obtienen asi nomas, para poder obtenerlos es necesario usar directamente xgettext y utilizar el parametro "--from-code=Glade". En fin, asi si se pudo.
    Ahora tengo un peque??????±o problema, la ventana principal de chirstine, o sea, el mero mero reproductor no se traduce. Las cadenas traducidas estan instaladas, y para cargar los descriptores de interface utilizo un wrapper (clase glade_xml) que asigna el directorio de los "locales", y usa bindtextdomain, y textdomain. En todos los mendigos descriptores de interface funciona, menos en el de interface, los menus todos en ingles (menos los que usan elementos de stock), tooltips, etiquetas, etc.. todo en el idioma en el que lo puse en glade :-/ . Que ser??????? que esta fallando?
    En fin, sigo trabajando sobre esta cosa... ]]>
    http://islascruz.org/html/index.php/blog/show/Christine_and_the_i18n_job.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine_and_the_i18n_job.html Fri, 22 Dec 2006 16:51:16 -0600
    <![CDATA[ Christine clibrary ]]> modulo de mismo nombre en Christine.
    Debo decir que en Python, me sorprende que la velocidad pocas veces sea un problema :-), y que la diferencia de velocidad entre C y Python no es mucha, aun asi hice esta implementacion mas como prueba que como algo que es realmente necesario, es como un "pega y corre".
    Christine normalmente toma poco menos de 2 segundos en crear todo, desde cargarse las interfaces, crear el modelo y lo mas pesado, llenar el modelo con las 1751 canciones que tengo, que bueno, no son muchas. La diferencia no es mucha, pero repito, no son tantas canciones y si alguien por ahi mete unos 5000 elementos no quiero que espere 10 segundos a que se cargue christine.
    He aqui la prueba :-):
    pgen_model

    0

    set: /apps/christine/control/CONTROL_STAT 1

    Not to miniviewer

    set: /apps/christine/ui/small_view False

    set: /apps/christine/control/volume 0.5
    real 0m1.327s <==Hecho con Python

    user 0m1.057s

    sys 0m0.084s

    cgen_model

    0

    set: /apps/christine/control/CONTROL_STAT 1

    Not to miniviewer

    set: /apps/christine/ui/small_view False

    set: /apps/christine/control/volume 0.5
    real 0m0.990s <== Hecho con C

    user 0m0.785s

    sys 0m0.048s
    No elimine el metodo en python, simplemente hice un empapelado y al utilizar "--clibrary" como argumento en la linea de comandos ejecuta el metodo en C (cgen_model) mientras que ejecutando christine directamente carga con el metodo hecho en Python (pgen_model). El parametro "-q" hace que Christine se muera (sys.exit()) al terminar de cargar todo, obviamente nomas ves que aparece la ventana un segundo y zas, ya se fue.
    En fin, solo queria comentar esto :-). Igual y hace implementaciones en C de otros puntos criticos de Christine >:-) ]]>
    http://islascruz.org/html/index.php/blog/show/Christine_clibrary.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine_clibrary.html Thu, 14 Dec 2006 15:04:45 -0600
    <![CDATA[ Christine for 2006-12-12 ]]> Yer.. Otra vez posteo sobre el estado de Christine, es que me pega la webonera y luego no hago ni madres.. :-D pero que le vamos a hacer, esta cosa no se va a crear solita.
    He estado trabajando en el display, que hasta hace unos dias solo servia para mostrar el porciento de la cancion en la barrita, ademas del tiempo y del nombre de la cancion, album y artista. Hoy ya funciona esa cosa para cambiar el tiempo dentro de la cancion. Sigo con que me falta pulirla, pero ahi va poquito a poquito, al menos ya funciona.
    Estoy tratando de darle mas poder a la entrada de busqueda, estoy pensando usar palabras reservadas como ARTIST, ALBUM, NAME, GENRE, TYPE entre otros y usar los operadores OR y AND, esto para que la seleccion de canciones sera mucho mas flexible y poderosa, Ahorita se hace una busqueda por digamos "kid rock", y mostrara todas las canciones en las que el artista, album, cancion o genero sea igual a "kid rock".
    El plus viene con lo que le estoy tratando de implementar a christine, las fuentes, es decir, las listas de reproduccion, las cuales podr???????n ser estaticas, o sea que el usuario le mete los archivos a manopla y estos no cambian. El otro tipo son dinamicas, es decir, estas se crearan en base al contenido de la biblioteca principal y de los parametros que el usuario pase como el genero, o que sean las mas recientes, o tal vez las mas tocadas, etc.
    Damog mencion??????? en un post sobre hacer que christine maneje plugins, esto tambien lo tengo que hacer pronto, aunque estoy dise??????±ando la interface para los plugins :-).
    Para los aventurados, aquellos que quiera cooperar, o bucear un poco, pueden darse una idea de como esta christine en el CVS ]]>
    http://islascruz.org/html/index.php/blog/show/Christine_for_20061212.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine_for_20061212.html Tue, 12 Dec 2006 18:20:03 -0600
    <![CDATA[ Christine con el display hecho en Cairo ]]> jugando con cairo y que pensaba incluir un display en Christine hecho con cairo, para quitarme de las etiquetas que se muestran y eliminar de paso el gtk.Scale que hasta hoy se usaba para ver el avance de la cancion.
    Bien, pues ya hoy en la tarde me puse a jugar con este desmadre hoy otra vez, y por fin puli un poquito mas el widget ese y lo incruste en christine ;-). Aun me falta pulirlo mas, pero tenia que presumir un poco :-P.

    christine

    Por cierto, es Apocalyptica, no Apocolytica, alguien me paso esa rola y le pusieron mal las etiquetas. ]]>
    http://islascruz.org/html/index.php/blog/show/Christine_con_el_display_hecho_en_Cairo.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine_con_el_display_hecho_en_Cairo.html Fri, 01 Dec 2006 22:08:06 -0600
    <![CDATA[ Inventario...(avance?) ]]> Se acuerda usted de esto, pues es una aplicacioncita que me hice hace unos cuantos meses para llevar el control de mis chucherias que tengo y que vendo en mi negocio, originalmente (y hasta el momento) esta pensado primordialmente para que cumpla su objetivo mera y razamente, o sea que no tiene todas esas mamadas y complicadeces que tiene esas aplicaciones comerciales porque simplemente No las necesito.
    Bien, continuando, la chucheria esta esta escrita en Python (ya lo sabias, pero como quiera va) y se conecta con una base de datos manejada por MySQL. Lo shido es que Python es multiplataforma, MySQL tambien, GTK Igual, PyGTK... yer, o sea, lo que necesita esta cosa para trabajar existe al menos en las dos plataformas que uso: Windows y Linux.
    Pues, bien, este mismo proyecto lo estoy agarrando de ejemplo para mi tesis, mi tesis habla sobre como desarrollar aplicaciones de manera rapida con Python, GTK y Glade, asi que es el ejemplo perfecto, porque aparte de ser un ejemplo sencillo, que escribi en unos cuantos dias, muestra el uso de la mayoria de los widgets de GTK (Windows, dialogs, Scrollbars, SpinButton, ToolBar, botones [checkbuton, normales, toolbutton], Modelos, Treeview, TextView, Frames, etc..). Peeeero, asi como estaba no me sirve, esta demasiadamente sencilla, ranfla y con un chingo de cosas que faltan por pulir y a las que no le dedique tiempo, por que?, porque soy webon.
    Bien, antier, ayer y hoy me puse a darle esta madre, tres dias, bueno, tres medios dias, me bastaron para pulir las cositas que me hacian falta (sin agrear mas desmadre), para que sea una aplicacion de uso mediano, completamente funcional y que ademas, me sirva para poner de ejemplo sencillo, porque tiene que ser lo suficientemente sencillo como para que alguien que se interese en aprender pueda comprenderlo.
    Bueno, el chiste es que la cosa ahi va, y les dejos las capturas de que la cosa esta funciona tanto con los buenos como con los no tan buenos.

    inventario The Systems
    inventario The Systems
    ]]>
    http://islascruz.org/html/index.php/blog/show/Inventarioavance.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Inventarioavance.html Fri, 24 Nov 2006 18:50:38 -0600
    <![CDATA[ Python y sus extensiones en C ]]> A pesar de que python es un lenguaje interpretado, es mucho mas rapido que otros lenguajes, y si esto no es suficiente, es posible escribir extensiones en C para las partes mas "rudas" del programa.
    Como todos saben (y si no ya lo va sa saber), estoy escribiendo un programita en Python que se llama Christine, que es un reproductor de audio y video basado en gstreamer y que utiliza GTK+ para la interfaz grafica, ok, una de mis preocupaciones con christine es hacer que la lista de elementos (musica y videos) se genere lo mas rapido posible, lo mismo con las busquedas.
    Los elementos se almacenan en un diccionario, que vendria siento un array por referencia (no indexado, donde no hay un orden en especifico y los elementos se llaman por un nombre de llave) , para agilizar las cosas actualmente utilizo el modulo cPicle. Este modulo crea un archivo de texto con algunos simbolos para poder almacenar un diccionario, lista, tupla, cadena, etc. cPicle es mas o menos la misma cosa que picle, la diferencia es que cPicle esta hecho completamente en C y por ende es mucho mas rapido que picle. Ok, pero una vez con el diccionario lo que sigue es llenar la lista de elementos (en un gtk.ListStore), para esto obtengo las llaves del diccionario, y despues hago una iteracion sobre las llaves para asi obtener los elementos del diccionario e ir insertando uno a uno en el modelo.
    Al momento he estado trabajando con una lista de cacines de poco mas de 1600 elementos y tarda uno o dos segundos en llenarme la lista, eso no es lo alarmante, lo que me preocupa es trabjar con christine con unos 10000 elementos?, claro, yo no creo tener tantos en una lista de reproduccion, pero hay que hacer las cosas para que aguanten. Asi que me puse a ver si podia hacer una extension en C para hacer este ciclo. Obviamente la creacion del modelo, los gtk.TreeIter, la inserci???????n y lo demas, esta practicamente hecho en C (aunque se usen los bindings de Python), lo que tal vez podria mejorar es a la hora de hacer el ciclo.
    No lo he implementado en christine, pero he hecho algo base, sobre todo para pruebas, y he visto que, tal vez porque la insersion de elementos en el modelo y creacion de iteradores esta hecho en C, o porque juego con funcions de Python desde C, el resultado no cambia mucho, incluso, en ocaciones (debido a otros procesos en mi equipo) Python hace las cosas mas rapidas. Ojo, esto con una diccionario de 1600 elementos e insertando en un modelo de una sola columna. En vista de que el resultado es casi casi el mismo, pues intente hacer lo mismo pero tomando como referencia un archivo de texto e iterar sobre cada uno de los caracteres que lo componen (eliminando los retornos de carro y los espacios en blanco).
    El elemento a tratar: el manual de bash (markuz$ man bash > texto;), una vez abierto el texto desde Python, se pasa este texto a una funcion en el modulo escrito en C, esta funcion devuelve un diccionario que se pasa la funcion que llenara el modelo. el resultado: C le gano a Python como por 1 segundo en todo el proceso (crear el diccionario y llenar el modelo). pero con unos 314227 elementos en lista. :-o, en fin. los resultados son estos:
    markuz$ time python libtest.py -c

    longitud del modelo: 314227
    real 0m7.478s

    user 0m7.182s

    sys 0m0.138s
    markuz$ time python libtest.py

    longitud del modelo: 314227
    real 0m8.582s

    user 0m8.268s

    sys 0m0.134s
    El parametro -c al llamar el script hace que este ejecute la funcion en C, si no se encuentra se hace todo con Python. Note que son 314227 elementos en la lista!!!!, quien tiene tantos elementos en la lista de reproduccion?, ni napster >:-).
    En fin... de que hacer las extensiones en C es mucho mas eficiente (con respecto a velocidad en proceso) si lo es, pero es mucho mas facil escribir en Python :-), asi que si no merece la pena hacer dicho esfuerzo no lo hagan XD. ahora que supongo que si toda la inserscion de elementos (gtk.ListStore.apend() y gtk.ListStore.set()) fuese escrita en Python el resultado estaria mucho mas marcado.
    Bien, en esto perdi el dia ayer, mas que nada en entender como hacer la extension, no soy muy bueno en C, y si me costo algo de trabajo :-/
    Codigo de Python
    Codigo de C ]]>
    http://islascruz.org/html/index.php/blog/show/Python_y_sus_extensiones_en_C.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Python_y_sus_extensiones_en_C.html Fri, 17 Nov 2006 15:38:30 -0600
    <![CDATA[ Python Cookbook ]]> e-compugraf.com y no tardo nada en llegar. Ahora mismo lo estoy leyendo (me di un tiempo para presumir).

    Python Cookbook
    ]]>
    http://islascruz.org/html/index.php/blog/show/Python_Cookbook.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Python_Cookbook.html Sat, 11 Nov 2006 16:52:03 -0600
    <![CDATA[ Keep going ]]> test.py.png Sigo dandole a Cairo, hoy, aunque en menor medida, le di a esta madre para hacer una barra de progreso y poco a poco ir agarrandola para hacer el display que tanto quiero :-).
    En el programita anterior (continuacion del programa del post sobre cairo anterior) esta onda escribia en el "display" lo que uno escribia en la caja de texto, ahora la barra de progreso se llena/vacia de acuerdo a al valor entre 0 y 1 que se le indique en el SpinButton.
    Lo que queda es hacer que el texto de la cancion (lo que dice "Empty" en la imagen) se mueva (nomas por mamon) mientras que el slide se mueva de un lado pa otro conforme avanza la cancion, y aun mas me va a faltar hacer esas funciones de escala para que el cliente al hacer click sobre alguna posicion de la barra cambie la posicion de la cancion (y de la barra :-P).
    En fin... a ver en que avanzo ma??????±ana :-P. Deberia estar corrigiendo bugs en christine en lugar de estar viendo la forma de agregar mas >:-) ]]>
    http://islascruz.org/html/index.php/blog/show/Keep_going.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Keep_going.html Thu, 09 Nov 2006 21:36:51 -0600
    <![CDATA[ Aprendiendo a usar Cairo ]]> Cairo es una biblioteca que soporta multiples dispositivos de salida (X Window System, Win32, PostScript, PDF, SVG) y soporta de manera experimental algunos otros como OpenGL. Cairo esta dise??????±ado para producir una salida consistente en todos los dispositivos de salida y aprovechar las aceleracion por hardware cuando esta est??????© disponible.
    En fin, yo estoy desde hace un tiempecito tratando de empezar a crear mis widgets personalizados, si bien no para crear todo a base de widgets personalizados si para saber como diantres se hacen. Uno de los propositos es crear un "display" para las canciones que reproduce christine en lugar de un gtk.Label y un par de botones, proyectandome muy feo, tal vez algo como el display que tiene iTunes.
    Hoy me puse a jugar con esto, y la verdad, aunque al principio esta mas perdido que cualquier cosa, ya medio le estoy agarrando la onda, comenece con los tutos que estan en la pagina de pygtk.org y en el codigo de ejemplo en el cvs de PyGTK. widget.py
    Al final del dia (si, por que ya me dolio la cabeza, desde las 10 de la ma??????±ana que estoy aqui frente a la computadora - no miento, aqui com??????­-) me comprendi bien que es lo que hacia el mendigo ejemplo y le agregue la caracterisitica de que el texto se mueva de izquierda a derecha hasta desaparecer.
    #!/usr/bin/env python
    # test for writting a custom gtk-cairo widget

    import gtk, cairo, pango, gobject
    BORDER_WIDTH = 5
    POS_INCREMENT = 5
    class test(gtk.DrawingArea):
            def __init__(self,text="Empty"):
                    gtk.DrawingArea.__init__(self)
                    self.connect("expose-event",self.expose)
                    self.set_text(text)
                    fontw,fonth = self._layout.get_pixel_size()
                    self.wpos = 0
                    self.set_size_request(100,100)
                    gobject.timeout_add(200,self.move_text)
           
            def set_text(self,text):
                    self._layout = self.create_pango_layout(text)
                    self._layout.set_font_description(pango.FontDescription("Sans Serif 34"))
           
            def expose(self,widget,event):
                    try:
                            self.area = event.area
                    except:
                            pass
                    self.create_context()
                    self.draw(self.context)
                    return False
           
            def create_context(self):
                    self.context = self.window.cairo_create()
                    (self.x,
                    self.y,
                    self.w,
                    self.h) = self.area
                    self.context.rectangle(BORDER_WIDTH,
                                                            BORDER_WIDTH,
                                                            self.area.width -2*BORDER_WIDTH,
                                                            self.area.height -2*BORDER_WIDTH)
                    self.context.clip()
           
            def draw(self,context):
                    rect = self.get_allocation()
                    x = rect.x
                    y = rect.y
                    w = rect.width
                    h = rect.height
                    context.rectangle(BORDER_WIDTH,BORDER_WIDTH,
                                    w -2*BORDER_WIDTH,h - 2*BORDER_WIDTH)
                    context.set_source_rgb(1,1,1)
                    context.fill_preserve()
                    context.set_source_rgb(0,0,0)
                    context.stroke()
                    self.write_text()
                   
            def write_text(self):
                    x,y,w,h = self.allocation
                    fontw,fonth = self._layout.get_pixel_size()
                    self.context.move_to(self.wpos,(h-fonth)/2)
                    self.context.update_layout(self._layout)
                    self.context.show_layout(self._layout)
            def move_text(self):
                    if self.wpos > self.allocation.width:
                            self.wpos = 0
                    self.wpos += POS_INCREMENT
                    self.create_context()
                    self.draw(self.context)
                    return True
    class window:
            def __init__(self):
                    self.window = gtk.Window()
                    self.window.set_border_width(10)
                    self.window.connect("destroy",gtk.main_quit)
                    vbox = gtk.VBox(False,2)
                    a = test()
                    vbox.pack_start(a,True,True,2)
                    self.window.add(vbox)
                    entry = gtk.Entry()
                    entry.connect("changed",lambda widget: a.set_text(widget.get_text()))
                    vbox.pack_start(entry,True,False,2)
                    self.window.show_all()
            def main(self):
                    gtk.main()
    if __name__ == "__main__":
            a = window()
            a.main()

     

    Cairo based widget

    En fin... al menos salio pa poner el post del dia :-P. ]]>
    http://islascruz.org/html/index.php/blog/show/Aprendiendo_a_usar_Cairo.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Aprendiendo_a_usar_Cairo.html Wed, 08 Nov 2006 19:06:33 -0600
    <![CDATA[ Tareas en christine ]]> Christine poco a poco, a paso lento (a veces muy lento) esta alcanzando su madurez. Aunque a veces no tengo tiempo suficiente como para dedicarle, me gusta el proyecto y en realidad quiero que crezca. Y una de las cosas que mas me intereza es que sea usado por los demas, tiene sentido que lo use, porque a fin de cuentas el proyecto comenz??????? por que queria que el reproductor hiciera lo que yo quiero que haga, en fin, y como no tengo todo el tiempo del mundo y aparentemente no hay mucha gente interezada en el proyecto, pues he decidido hacer unas peque??????±as tareas, para quien tenga ganas de programar un poco, para quien quiera probar sus habilidades con Python o para quien simplemente quiera jugar.
    Las tareas son sencillas, y son las siguientes: Salvo de la primera tarea, ser??????? necesario obtener el codigo fuente, que facilmente lo podr???????n cachar del CVS, informaci???????n sobre como obtener el codigo se encuentra en esta pagina: http://sourceforge.net/cvs/?group_id=167966
    Hay un bugcito reportado en el bug tracker, quien quiera echarse un clavado y ayudarme a corregirlos aqui se los pongo. Si no sabes programar, pero quieres probarlo, adelante :-), por favor hazlo y reporta todos los bugs que encuentres en el tracker: http://sourceforge.net/tracker/?group_id=167966&atid=845044. ]]>
    http://islascruz.org/html/index.php/blog/show/Tareas_en_christine.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Tareas_en_christine.html Mon, 06 Nov 2006 20:52:56 -0600
    <![CDATA[ Mas capturas de Christine ]]>
    Christine with visulaizationsChristine with visulaizationsChristine with visulaizations
    ]]>
    http://islascruz.org/html/index.php/blog/show/Mas_capturas_de_Christine.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Mas_capturas_de_Christine.html Wed, 01 Nov 2006 21:36:40 -0600
    <![CDATA[ Volviendo a Christine ]]> villahermosa y obviamente en ese tiempo ni toque la computadora con aires de programar algo, solo la use para descargar las fotos y escuchar un poco de musica (tampoco queria romper christine entonces).
    Pero en esta semanita me he sentido con ganas de programar, y tomando en cuenta que estoy esperando la revision de la tesis para poder continuar, pues en este tiempecito me he dado a programar otra vez con christine.
    christine improvementsNo he hecho mucho, pero he logrado que importar archivos a la lista sea dos veces mas rapido, lo que en algunos equipos lentos podria tal vez (por limitantes de gstreamer) crear una falla de segmento y terminar la aplicaci???????n, pero para eso estoy pensando en habilitar un modo de "importado rapido", es decir, meter en la biblioteca todas las canciones/videos a importar de a putazo, con sus nombres feos de archivo (ej. cold_play_-_the_scientist) y despues en un proceso en segundo plano actualizar los datos con tiempo suficiente, digamos una cancion por segundo. Tomando en cuenta que el usuario pone la musica y se dedica a hacer otras cosas, pues eventualmente ver??????? que su biblioteca tiene todos los datos.
    Tuve un problemita con el paquete de gstreamer que se incluye en DroplineGnome porque no me reproducia los videos en formato mpeg, y resulto ser porque no tenia libmpeg2 instalado, y por lo tanto al compilar gst-plugins-ugly (que incluyen el plugin mpeg2dec) no compilaba mpeg2dec. Pues hasta que se pudo.
    Tambien he habilitado de nuevo el visualizador, que trabaja en mi maquina bastante bien, consume un poco de recursos (eleva el uso de mi cpu al ~33% por christine) pero funciona bien :-).
    christine improvements
    ]]>
    http://islascruz.org/html/index.php/blog/show/Volviendo_a_Christine.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Volviendo_a_Christine.html Wed, 01 Nov 2006 12:52:29 -0600
    <![CDATA[ Como loco.. ]]> christine y gpkg, por el momento tengo que dedicarle un poco mas de tiempo a lo que me ha de dar de tragar, como bien me dijo el buen visor: Primero comer que ser cristiano en fin, prefiero dedicar un poco mas de tiempo las cosas que me van a redituar un poco de dinero y si tengo tiempo le dedico a christine y gpkg.
    La tesis me tiene un poco atareado, con eso de que hay que cambiarle todo para que sea mas "entendible", menos t??????©cnica y que aun asi describa todo lo que yo necesito que describa, aunque encuentro esto bastante dificil, pues mi tesis trata sobre desarrollo de aplicaciones en Python utilizando Pygtk y Glade y hablar de un lenguaje de programacion y sus herramientas resulta ser por naturaleza bastante t??????©cnico. En fin... tengo que hacerla.
    Por otro lado he estado trabajando en un peque??????±o proyecto, que si todo sale como yo espero en un par de semanas a mas tardar estar??????? montado y podr??????? por fin ver la luz. Esto me recuerda, que vaya como son las cosas. Hace un par semanas recordaba mi primer lenguaje de programacion: PHP, curiosamente este nuevo proyecto esta siendo desarrollado en PHP, y vaya que si despues de poco mas de 1 a??????±o no moverle a PHP se me estaban olvidando varias cosas, sobre todo por el modo de trabajo de Python. Por ejemplo, estoy acostumbrandome a que una cadena por si misma tenga sus metodos y no a llamar funciones para modificar la cadena.
    $string  = "Hola#mundo";
    $string1 = str_replace("#"," ",$string);
    // retorna "Hola mundo"
    $string2 = explode("#",string)
    //retorna array("Hola","mundo");
     
    string = "Hola#mundo"
    string1 = string.replace("#"," ")
    # retorna "Hola mundo"
    string2 = string.split("#")
    #retorna ["Hola","mundo"]
     
    En fin, el chiste es que he estado haciendo consultas seguidas a php.net en busca de documentaci???????n, y aunque me parece definitivamente un poco mas dificil la programacion en PHP sobre todo por las vueltas que hay que dar, me recuerda buenos tiempos y me divierte.
    ]]>
    http://islascruz.org/html/index.php/blog/show/Como_loco.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Como_loco.html Wed, 11 Oct 2006 12:57:55 -0500
    <![CDATA[ Si... estoy enamorado de Christine... ]]> Pero aun asi me gusta, y desde que se volvi??????? usable ya no uso pr???????cticamente ningun otro player, a menos que christine (por su backend con gstreamer) no pueda reproducir el archivo (tipicamente archivos de video), pero para todo mi audio uso christine.
    Que bonito no?, hacer tus propias cosas y que te funcionen como tu gustas :-).
    ]]>
    http://islascruz.org/html/index.php/blog/show/Si_estoy_enamorado_de_Christine.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Si_estoy_enamorado_de_Christine.html Sun, 01 Oct 2006 10:35:19 -0500
    <![CDATA[ Christine full Screen mode ]]> Christine para ajustar lo del FullScreen Mode, y al momento lo tengo basico para video, aun echare ojo al Full Screen Mode para audio, pero aun no me decido si se mostrara la aplicacion con un simple window.fullscreen() o si mostrare algun tipo de visuallizador, que al momento de escribir esto suckea el visualizador en christine, asi que tengo algo mas en que trabajar. De momento ya esta el full Screen para video, ahi dejo el screenshot:
    Tambien he cambiado algunos keybindings para hacer la aplicacion mucho mas simple. Si alguien quiere probarlo puede descargarse el codigo del CVS, necesitara Python, PyGTK y gst-python. ]]>
    http://islascruz.org/html/index.php/blog/show/Christine_full_Screen_mode.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine_full_Screen_mode.html Tue, 26 Sep 2006 16:52:39 -0500
    <![CDATA[ Recordando PHP ]]> PHP, hace algo asi de unos 4 a??????±os ya de que le empece a dar a esto. Pero de un a??????±o para aca que le doy en su mayoria a Python.
    De un tiempo para ac??????? se me ocurrio hacer mi propio planeta. Con el intento de continuar trabajando con Python quise hacerlo con el software de planetplanet.org mas sin embargo, por un peque??????±o problema con el servidor no pude. Busque y en el planeta de php tienen un software para hacer esto, pero... es necesario PHP5 (que no tengo), una base de datos y ganas de configurarlo (que tampoco tengo), asi que se me prendi??????? el foco.
    Si a mi me gusta programar, y si yo se programar en PHP, caramba por que putas madres no hago mi propio planeta?, ps si, aprovechando de que algun bondadoso ser humano ya hizo la biblioteca para parsear los feeds (MagpieRSS) pues nomas es cosa de ordenar y ponerle una bonita cara. Y ya esta, poco a poco ire agregando a mis cuates a mi planeta, disponible en http://www.islascruz.org/planet.
    Y aunque aun no esta bien terminado (medio dia de chamba), pues ya hace lo minimo necesario, hay poco a poco le dare mas forma, pulir??????© el c???????digo y le agregare caracteristicas. Ya cuando sea un poco mas usable pondr??????© el codigo para quien guste.
    ]]>
    http://islascruz.org/html/index.php/blog/show/Recordando_PHP.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Recordando_PHP.html Sat, 23 Sep 2006 16:53:30 -0500
    <![CDATA[ This is shameful ... :'-( ]]> I sold Cunegunda I had to use the computer in "my work" that runs Windows. Its nice, I can live with it, but I can't work and do all that stuff that I was used to do in Linux. The good thing is that I can poke some code for the Inventory program for my small bussines.
    This reminds me that I didn't know how to hide the terminal window on Python Gui programs running on Windows. Asking in #python on irc.freenode.net some nice guy told me that using pythonw.exe. jeje, and there it is, if you didn't know this like me.
    So.. Until I had my new computer, I will code a bit for this in this machine.. :-(
    ]]>
    http://islascruz.org/html/index.php/blog/show/This_is_shameful__.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/This_is_shameful__.html Sun, 03 Sep 2006 18:09:33 -0500
    <![CDATA[ Back to work.... ]]> Ffrom the last thursday to the sunday I was in "vacations" again, I can't say who came to see me, but that person makes me feel fine again, and "this person" makes me forget all about computers and internet and all that related stuff, then I have now this need to code, and implement some new ideas in my head.
    I start writting for Christine instead Gpkg because christine is a very early stage and I like to make it reach a stable state to let it rest for some monts while I will code for gpkg.
    So... I will be busy again, but happy, very very happy. :-).
    ]]>
    http://islascruz.org/html/index.php/blog/show/Back_to_work.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Back_to_work.html Tue, 29 Aug 2006 11:48:23 -0500
    <![CDATA[ Christine on August 2006 ]]> FLOSS category.

    Click in the picture to see some nice comments.
    ]]>
    http://islascruz.org/html/index.php/blog/show/Christine_on_August_2006.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine_on_August_2006.html Mon, 07 Aug 2006 16:28:50 -0500
    <![CDATA[ Como matar dragones usando lenguajes de programacion. ]]> maikool blog, I'm not gonna copy/paste all here, read it from where I read (it's fair), but I love this chunk:
    PYTHON - Como solo hay UNA forma obvia de matar al dragon:
    >>> from muertesObvias import hacerBrocheta

    >>> dragon

    dragon malo que dice agggh y tira fuego at 0???????????3007c370>

    >>> hacerBrocheta(dragon)

    >>> dragon

    >>> brocheta de dragon traigan vino asi empedamos a la princesa at 0???????????3007c370>
    hacer brocheta tambien manda un mail de invitacion a que hagan reportaje de los canales de cable locales, publica una entrada diciendo que el caballero mato al dragon en su blog, da de baja todos los dominios que tenia registrados el dragon a su nombre y se conecta con un servidor jabber para avisar a los familiares del dragon que lo mataron.
    Python.. Es una verga.... :-D ]]>
    http://islascruz.org/html/index.php/blog/show/Como_matar_dragones_usando_lenguajes_de_programacion.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Como_matar_dragones_usando_lenguajes_de_programacion.html Wed, 26 Jul 2006 21:49:44 -0500
    <![CDATA[ To CONSOL 2006 ]]> This post had some links, but then Jaws screw everything and Now I don't want to make the links again, so there it is, another ugly post. ]]> http://islascruz.org/html/index.php/blog/show/To_CONSOL_2006.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/To_CONSOL_2006.html Sun, 23 Jul 2006 16:25:53 -0500 <![CDATA[ No PyXine in Christine ]]> Christine, why?, because it will take me more time to create a common interface betwen cristine and Gstreamer and Pyxine and the more important one, PyXine is to old, is not stable and is most probably dead.
    And I was thinking about including pyxine in christine because some videos and some audio files didn't play, but that was a problem with my own gstreamer copy. Now even using eSound (esd) cristine (and any other gst based application) takes less cpu time for me, so compile!.
    I had nothing to write, ok, and Iam writting to make time before My Name is Earl begins :-P. ]]>
    http://islascruz.org/html/index.php/blog/show/No_PyXine_in_Christine.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/No_PyXine_in_Christine.html Mon, 03 Jul 2006 21:42:42 -0500
    <![CDATA[ Todays christine journey ]]> christine again. Today I fix some problems with gconf, I had not finished the preferences dialog, but it should work with hiding/showing columns. I also work with christine in the library and queue lists.
    I had some problems playing some videos, more of them downloaded from google, I was very very anger because I didn't find out the problem, until today that build gstreamer and the whole plugins (base,good,ugly,bad) and gst-python, and Yupiii!!!, all my videos are now played with christine :-).
    And looking to christine when is playing a video (and hiding the library and queue list) it looks very very clean.

    Again, in the black spot is a video, GL stuff.
    Hoo christine... ]]>
    http://islascruz.org/html/index.php/blog/show/Todays_christine_journey.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Todays_christine_journey.html Sat, 01 Jul 2006 19:25:04 -0500
    <![CDATA[ Christine playing video ]]> First, the Import to Queue works, this is to import a file to the queue (next audio or video to be played) without importing it to the main playlist.
    And second, Play video works again, I haven't work with this since christine was upgraded from gstreamer 0.8 to 0.10, and now it plays video again, but some issues will happen since I had just work on it today and some videos downloaded from video.google.com seems to doesn't work, I wonder that it is because gstreamer or the discoverer class wrote by me.
    So this is a screenshot, and there is a video on video.google, but it still is unavailable for some google reasons.

    Just imagine a video playing in the black square :-p.
    And click on the image to see it bigger
    ]]>
    http://islascruz.org/html/index.php/blog/show/Christine_playing_video.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine_playing_video.html Thu, 22 Jun 2006 15:01:30 -0500
    <![CDATA[ christine ]]> ]]> http://islascruz.org/html/index.php/blog/show/christine.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/christine.html Sat, 17 Jun 2006 15:30:05 -0500 <![CDATA[ Emputado.. ]]> Bien, tenia un post asi bien chingon, explicativo y demostrativo, pero el puto firefox cometi??????? un puto error que ya habia hecho antes y se cerr???????, lo que mand??????? mi post al Limbo de donde nunca podr??????? ser rescatado. Y me da una hueva tremenda volver a escribirlo porque soy un webon y porque me da miedo de que me vuelva a pasar, asi que en resumidas (muy resumidas cuentas) esto decia:
    • No he trabajado en Christine porque toy haciendo mi tesis. Y no he escrito por lo mismo.
    • Aunque no he escrito, tengo que entrar en el blog para quitar los molestos comentarios spam que se acomodan y eso que tengo el Captcha activado.
    • Intente instalar GNU/Solaris(Nexenta) y Solaris Express pero toy muy pendejo, y no quiero darle en la madre (ni por accidente) a los datos que tengo en el disco duro de la voladora.
    • Y ya no me acuerdo que mas...
    ]]>
    http://islascruz.org/html/index.php/blog/show/Emputado.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Emputado.html Mon, 12 Jun 2006 14:57:08 -0500
    <![CDATA[ Frankenstein desktop ]]> alo en su post GNOME desktop wiki.. or Pushing way too hard for Mono da al clavo con uno de los puntos debiles de Gnome y de sus componentes:
    By the way, what scares me most is that, each day we are moving closer towards a "Frankenstein" desktop: a single desktop depending on its own libraries, the Mono ones, the STL, the Python interpreter, the Java virtual machine, and eventually something more exotic like the Ada95 runtime. If we are thinking of conquering the desktop with something like that, I'd better boot Windows and play StarCraft. :-(
    Y no es mas que una realidad, Gnome esta escrito en C, y la mayor parte de sus componentes igual, pero se estan desarrollando aplicaciones para el que estan escritas en muchos lenguajes, y soy culpable de usar Python en lugar de C :-(. Pero lo que mas pega para los desarrolladores de Mono es esto:
    Another reason to use Mono inside GNOME is the ability to bring Windows developers to the free desktop development field. It sounds nice. I mean, the more we are the better, but actually to me it doesn't sound like a credible reason. What would be the motivation of a .NET programmer to use GTK#? At the end of the day, the WinForms is the standard for him.. and Mono is meant to support it.
    Quien canijo windowsero que ha escrito en Windows.Forms va a dejar de usar Windows.Forms para usar GTK#??, Lo que sea de cada quien, GTK (en cualquier lenguaje [supongo]) es bonito, pero para cualquiera es tedioso aprender algo nuevo, y si actualmente Mono soporta Windows.Forms lo unico que generar??????? sera un Gnome con cara de windows.. Wakala, que asco. Y e que lo malo no es que usen Windows.Forms, sino que Windows.Forms no se integran con GTK, por el contrario GTK si se integra con el ambiente de Windows ;-).
    Apoyo a alo en su "lucha" contra Mono en Gnome. ]]>
    http://islascruz.org/html/index.php/blog/show/Frankenstein_desktop.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Frankenstein_desktop.html Wed, 31 May 2006 21:58:00 -0500
    <![CDATA[ christine ]]> Screenshot-Fucking Hostile - Christine.png
    Click para ver en grande ]]>
    http://islascruz.org/html/index.php/blog/show/christine.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/christine.html Tue, 30 May 2006 15:54:36 -0500
    <![CDATA[ Christine improvements ]]> anterior mencionaba sobre las canas verdes que me estaba sacando Christine porque se me colgaba cuando utilizaba el discoverer para obtener los tags de los archivos a reproducir.... mmmm, ni modos, lo tuve que quitar y hacer mi propio discoverer:
    class discoverer:
            def __init__(self):
                    print "discoverer: new instance"
                    self.discoverer = gst.element_factory_make("playbin")
                    self.discoverer.set_property("audio-sink",gst.element_factory_make("esdsink"))
                    self.discoverer.set_property("video-sink",gst.element_factory_make("xvimagesink"))
                    self.discoverer.set_property("volume",0.0)
                    self.bus = self.discoverer.get_bus()
           
            def set_location(self,file):
                    self.tags = {}
                    self.discoverer.set_property("uri","file://%s"%file)
                    self.discoverer.set_state(gst.STATE_READY)
                    self.discoverer.set_state(gst.STATE_PAUSED)
                    self.discoverer.set_state(gst.STATE_PLAYING)
                    self.discoverer.set_state(gst.STATE_PAUSED)
            def found_tags_cb(self,tags):
                    if len(tags.keys()) > 0:
                            for i in tags.keys():
                                    self.tags[i] = tags[i]
                    #print self.tags
                   
            def get_location(self):
                    path = self.discoverer.get_property("uri")
                    if path != None:
                            path = path[7:]
                    return path
           
            def get_tag(self,key):
                    try:
                            return self.tags[key]
                    except:
                            return ""
     
    Apenas lo hice hoy y aun me faltan algunas cosas como el determinar si el archivo es de audio o video, pero me funciona bien, y ya hoy pude importar mi colecci???????n de musica colocando los tags correctos en la lista:
    Cabe mencionar que en esta clase, es necesario conectar el bus (self.discoverer.bus) con un manejador para que cuando se envie el mensaje gst.MESSAGE_TAG utilice el metodo parse_tag propio del mensaje y que estos tags sean enviados a discoverer.found_tags_cb.
    def message_handler(self,a,b):
                    d = self.discoverer
                    t = b.type
                    if t == gst.MESSAGE_TAG:
                        self.discoverer.found_tags_cb(b.parse_tag())
     
    ]]>
    http://islascruz.org/html/index.php/blog/show/Christine_improvements.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine_improvements.html Fri, 26 May 2006 14:24:17 -0500
    <![CDATA[ Christine y las canas verdes ]]> Christine, me toy dando el respectivo break para no caer en esto :-P. Christine ahi va poco a poco, el problema es que no se por que mendiga razon se cuelga :-S.
    Mientras jala con mp3 todo va perfecto, pero al aventarse a reproducir ogg, la cosa se puede colgar, por un error raro de no se que cosa.

    Fatal Python error: GC object already tracked

    Supongo que es al usar la clase gst.extend.discoverer.Discoverer, lo que hace esta clase es tomar como parametro de inicializaci???????n el archivo a leer, y le saca las entra??????±as (etiquetas, bitrate, etc.. ) aparte de definir si es un archivo de audio o de video. En fin... Si no fuera porque gstreamer tarda (en mi opinion) demasiado para obtener las etiquetas de un archivo (y se cuelga de vez en cuando), todo iria perfecto. :-/ ]]>
    http://islascruz.org/html/index.php/blog/show/Christine_y_las_canas_verdes.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine_y_las_canas_verdes.html Wed, 24 May 2006 11:14:32 -0500
    <![CDATA[ Christine in Sourceforge.net && Infinitum ]]> Christine ya esta en Sourceforge.net :-). Hace como semana y media o dos que habia pedido ese nombre, lo tenia un proyecto de base de datos registrado hace un a??????±o pero que nunca mostr??????? ningun resultado.
    En cuanto pueda subir??????© el codigo de Christine al CVS para quienes est??????©n interezados en el proyecto. :-)
    Update:Ya he subido las fuentes al CVS, tambien se pueden ver por via web
    Por otro lado, a mi rancho ya lleg??????? el servicio de infinitum, asi que el modem satelital tendr??????? unas buenas vacaciones mientras pienso que hago con el. La ventaja es que ya no me tendr??????© que limitar por las descargas y el ancho de banda de subida es mayor :-). ]]>
    http://islascruz.org/html/index.php/blog/show/Cristine_in_Sourceforgenet__Infinitum.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Cristine_in_Sourceforgenet__Infinitum.html Sat, 20 May 2006 12:24:44 -0500
    <![CDATA[ Prueba ]]>
    Bien, pues ya lo prob??????© en windows y jal??????? perfecto, sin necesidad de mover una linea al c???????digo:
    Python, PyGTK (GTK+) y Glade son una ?erga.. ]]>
    http://islascruz.org/html/index.php/blog/show/Prueba.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Prueba.html Tue, 16 May 2006 16:18:38 -0500
    <![CDATA[ Work for the last week ]]> break o mejor dicho, bajandole el ritmo al vicio.
    En fin, entre lo poco que he hecho en esta semana esta el migrar Christine de gst-python 0.8 a gst-python 0.10, comenc??????© con ese porque era la version que tenia instalada cuando comenc??????© a desarrollarlo, y pues mejor me instal??????© gstreamer 0.10 y sus bindings porque se supone que est???????n mejor.
    Un poco de trabajo me ha costado, pero ah??????­ va, y de christine, pues aun me falta acomodar las cosas con Gconf, resanar detallitos y pulir c???????digo. Que espero poder hacer al menos lo ultimo antes de que los del equipo de SF.net me den el espacio del proyecto christine, ya lo ped??????­ y ya esta concedido, aun falta terminar el proceso :-). ]]>
    http://islascruz.org/html/index.php/blog/show/Work_for_the_last_week.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Work_for_the_last_week.html Thu, 11 May 2006 15:23:03 -0500
    <![CDATA[ Christine again ]]> GStreamer, y christine ya es "usable" (para mi), ya me sirve pa tocar mi musica, y meter elementos en cola, importar archivos y carpetas completas (incluyendo subdirectorios si se especifica). En el ultimo post mostre unas imagenes, pero aun no era tan usable, porque despues de un rato la interface se conjelaba y solo los elementos de control servian, por lo que un no lo podia agarrar pa poner mi musica eternamente :-P.
    Ahora ya resolv??????­ ese problema y le acomod??????© el visualizador, el chunche para que mientras toca aparezca algo en pantalla. el problema del visualizador es que consume muchos recursos (un 40% de mi cpu!!!), asi que por defecto lo tengo desactivado.
    Como todo buen contribuidor al software libre, este chunche estar??????? disponible para descarga y desmenuzada bajo la GNU/GPL, pero eso ser??????? cuando ya tenga un poco mas de forma, limpie un poco y acondicione el c???????digo.
    De momento dejo una foto:
    ]]>
    http://islascruz.org/html/index.php/blog/show/Christine_again.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine_again.html Mon, 01 May 2006 15:51:48 -0500
    <![CDATA[ Christine ]]> GStreamer, Python y PyGTK. He estado desarrollando una peque??????±a aplicaci???????n que reproduzca sonido y video. Pero, por que reinventar la rueda?, bueno, he sido usuario de xmms por mucho tiempo, sobre todo por su sencillez, y porque lo que hace lo hace bien :-). Y de un tiempo para ac??????? he estado usando rhythmbox. Los dos son geniales, xmms es muy sencillito, y ligero, mientras que Rb me permite crear listas (estaticas y dinamicas) ademas de que usa gstreamer.
    Las dos aplicaciones son buenas, pero RB no reproduce video (si si, ya s??????© que ah??????­ esta xine y tambien Mplayer, Totem y otros) y los que lo hacen es en una aplicacion aparte, yo quiero tener una lista de reproduccion donde esten mis videos y mi musica, para no tener que abrir dos aplicaciones si quiero ver video primero y luego escuchar una canci???????n. Adem???????s ando de ocioso.
    El chunce este ya me permite guardar una lista principal, meter elementos a una cola de reproduccion, hacer busqueda de canciones, toca en orden aleatorio y obviamente toca musica y reproduce video :-). Aun ta muy verde, pero pues en mis grandes tiempos de ocio le seguir??????© dando para que haga jutamente lo que yo quiero que haga :-).
    Ah??????­ quedan dos capturas de como lo veo ahorita:

    Vista en miniatura

    Vista normal

    Reproduciendo video
    ]]>
    http://islascruz.org/html/index.php/blog/show/Christine.html markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php/blog/show/Christine.html Sat, 29 Apr 2006 16:37:01 -0500
    <![CDATA[ GStreamer ]]> Desde mas o menos una semana he estado trabajando en un proyectito que involucra el uso de GStreamer, principalmente por la necesidad de aprender algo nuevo mas que por cubrir alguna necesidad no cubierta (vamos siendo sinceros) salvo por hacer un programita que haga lo que yo quiero que haga.
    En general este programita hace lo basico que gstreamer debe hacer, reproducir audio y video, pero, pero me ha costado un poco, y no porque gstreamer sea dificil, no, gstreamer en realidad es algo sencillo, mucho menos complejo que GTK+ pero desgraciadamente mucho mas carente de Documentaci???????n. Lo que me ha hecho perder tiempo.
    En la pagina de documentaci???????n de GStreamer se puede encontrar el Application Development Manual y el Plugin Writer's Guide, el manual de referencia del coraz???????n y de las librerias ya las habia visto antes gracias a Devhelp, y para ser honestos, no me ayudaron mucho, si acaso un poco el manual de desarrollo de aplicaciones, que trata GStreamer desde un bajo nivel.
    Afortunadamente Python en su consola interactiva me permite el uso de la funcion dir para ver que tiene en sus adentros alguna clase u objeto.
    En GStreamer casi todo son elementos, y en el Manual de desarrollo de aplicaciones habla sobre crear un Pipeline y otras cosas, que en los bindings de python se resumen a crear un objeto con la funcion
    gst.play.Play()
    , agregar los sinks (elementos que manejaran al archivo) y listo, que a ultimas tarde o temprano se aprende, pero... no hay alguna lista de sinks disponibles?? me he tenido que guiar usando gstreamer-properties para saber los sinks de audio y video disponibles, pero se que no son los unicos (goom, fakesink, ... )
    Por que no se habla de este elemento en la documentaci???????n de GStreamer??, No s??????©, pero si veo una falta de documentaci???????n. Y hablando de los bindings de python, bueno, de estos si casi casi no hay nada de documentaci???????n.
    Ahora, dejando de lado esto de la falta de documentaci???????n, el uso de GStreamer es muy sencillo como ya lo habia dicho, generas un objeto con gst.play.Play() y solo conectas se??????±ales, agregas los sinks, etc..
    import gst,gst.play
    player = gst.play.Play()
    player.connect("eos",gst.main_quit)
    player.set_data_src(gst.element_factory_make("filesrc"))
    player.set_audio_sink(gst.element_factory_make("esdsink"))
    palyer.set_video_sink(gst.element_factory_make("xvimagesink"))
    player.set_location("/mnt/hda8/muzak/algun_formato_