Marco Islas Blog Python http://islascruz.org/html/ markuz@islascruz.org (Marco Antonio Islas Cruz) 2005-2008, Marco Antonio Islas Cruz Sat, 27 Jun 2009 00:39:55 -0500 JAWS 0.8.6 <![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/SingleView/id/IronPython-in-Action markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/IronPython-in-Action 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/SingleView/id/PyGtk%3A-GtkDialog-for-configurations-using-pure-treeviews markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/PyGtk%3A-GtkDialog-for-configurations-using-pure-treeviews 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/SingleView/id/Sockets-%28and-some-other-files%29-and-PyGTK-without-threads. markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Sockets-%28and-some-other-files%29-and-PyGTK-without-threads. 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/SingleView/id/PyGtk-and-Threads markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/PyGtk-and-Threads 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/SingleView/id/Python%3A-Create-win32-services-using-Python-and-py2exe markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Python%3A-Create-win32-services-using-Python-and-py2exe 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/SingleView/id/Christine-for-2009-04-26 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine-for-2009-04-26 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_at_islascruz_dot_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/SingleView/id/Christine%3A-rola_christine.py markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine%3A-rola_christine.py 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/SingleView/id/Christine-0.3.0 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine-0.3.0 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/SingleView/id/Pygtk%3A-About-keyboard-accelerators markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Pygtk%3A-About-keyboard-accelerators 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/SingleView/id/Python%3A-Merge-two-lists-in-a-single-in-the-less-time-possible. markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Python%3A-Merge-two-lists-in-a-single-in-the-less-time-possible. 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/SingleView/id/Google-and-the-Python-performance markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Google-and-the-Python-performance 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/SingleView/id/Python%3A-Simple-HTTP-Server-on-python. markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Python%3A-Simple-HTTP-Server-on-python. 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/SingleView/id/PyGTK%3A-Playing-with-gtk.GenericCellRenderer markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/PyGTK%3A-Playing-with-gtk.GenericCellRenderer 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/SingleView/id/Know-the-current-unix-time-%28for-the-party%29 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Know-the-current-unix-time-%28for-the-party%29 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/SingleView/id/Christine%3A-subtitles. markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine%3A-subtitles. 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/SingleView/id/Christine%2C-DBus-and-Cairo markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine%2C-DBus-and-Cairo 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/SingleView/id/This-week-on-Markuz-life... markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/This-week-on-Markuz-life... 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/SingleView/id/An-easy-one. markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/An-easy-one. 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/SingleView/id/Christine-0.2.1 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine-0.2.1 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/SingleView/id/Christine-0.2.0 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine-0.2.0 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/SingleView/id/Debugging-with-pydev markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Debugging-with-pydev 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/SingleView/id/Python-3000 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Python-3000 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/SingleView/id/Python-Logging markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Python-Logging 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/SingleView/id/Call-for-testers-and-translators markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Call-for-testers-and-translators 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/SingleView/id/Netbeans-6.5 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Netbeans-6.5 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/SingleView/id/What%27s-your-favorite-programmer-cartoon%3F markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/What%27s-your-favorite-programmer-cartoon%3F 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/SingleView/id/2008-11-16 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/2008-11-16 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/SingleView/id/Playing-with-gtk.Calendar markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Playing-with-gtk.Calendar 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/SingleView/id/2008-10-08 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/2008-10-08 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/SingleView/id/Aboutmylife markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Aboutmylife 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/SingleView/id/Givinglovetochristine markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Givinglovetochristine 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/SingleView/id/HotKeysonWindows markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/HotKeysonWindows 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/SingleView/id/christine-1 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/christine-1 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/SingleView/id/Christineusing6Mb markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christineusing6Mb 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/SingleView/id/Christineinlaunchpad markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christineinlaunchpad 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/SingleView/id/Christineloveinthenight markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christineloveinthenight 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/SingleView/id/Creating-a-custom-model markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Creating-a-custom-model 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/SingleView/id/TestingthenewchristineConfmodule markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/TestingthenewchristineConfmodule 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/SingleView/id/Christine-016 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine-016 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/SingleView/id/PyGTK-y-Threads markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/PyGTK-y-Threads 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/SingleView/id/Translation-status markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Translation-status Tue, 12 Feb 2008 16:57:22 -0600
<![CDATA[ Profiling Python ]]> Profiling and Optimizing Python ]]> http://islascruz.org/html/index.php?Blog/SingleView/id/Profiling-Python markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Profiling-Python 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/SingleView/id/Widgets-recordatos-en-Gtk markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Widgets-recordatos-en-Gtk 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/SingleView/id/Sockets markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Sockets 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/SingleView/id/Imprimir-a-un-archivo-PDF-usando-GTK markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Imprimir-a-un-archivo-PDF-usando-GTK 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/SingleView/id/Christine-011 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine-011 Fri, 21 Sep 2007 14:10:38 -0500
<![CDATA[ Usando el widget creado anteriormente ]]>
widgetTest.ogg
]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Usando-el-widget-creado-anteriormente markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Usando-el-widget-creado-anteriormente 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/SingleView/id/Un-contenedor-GTK-Redimensionable-al-gusto markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Un-contenedor-GTK-Redimensionable-al-gusto 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/SingleView/id/Respuesta markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Respuesta 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/SingleView/id/Amo-a-PyGTK markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Amo-a-PyGTK 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/SingleView/id/Christine--deb markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine--deb 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/SingleView/id/Christine-for-birthday markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine-for-birthday 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/SingleView/id/Piratearle-las-propiedades-a-un-objeto-en-Python markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Piratearle-las-propiedades-a-un-objeto-en-Python 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/SingleView/id/Como-dibujar-un-imagen-jpg-png-gif-etc-en-Cairo markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Como-dibujar-un-imagen-jpg-png-gif-etc-en-Cairo 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/SingleView/id/Alo-dotpy markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Alo-dotpy 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/SingleView/id/Creando-tus-propios-objetos-con-gobject-y-error-con-las-seales markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Creando-tus-propios-objetos-con-gobject-y-error-con-las-seales 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/SingleView/id/Creando-clases-de-Python-en-C markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Creando-clases-de-Python-en-C 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/SingleView/id/Christine-01rc2deb markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine-01rc2deb 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/SingleView/id/Work-and-Fun markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Work-and-Fun 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/SingleView/id/Cambiando-el-color-de-nuestros-widgets-en-GTK markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Cambiando-el-color-de-nuestros-widgets-en-GTK Fri, 08 Jun 2007 13:15:21 -0500
<![CDATA[ Christine 0.1rc2 ]]>
christine-0.1rc2.tar.bz2 ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Christine-01rc2 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine-01rc2 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/SingleView/id/Christine-01rc1 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine-01rc1 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/SingleView/id/Happy-Sunday-for-Christine markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Happy-Sunday-for-Christine 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/SingleView/id/Christine-bug-squash markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine-bug-squash 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/SingleView/id/I-listen-my-music-with-Christine markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/I-listen-my-music-with-Christine 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/SingleView/id/Christine-code-clean-bugfix markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine-code-clean-bugfix 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/SingleView/id/Christine_for_today markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine_for_today 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/SingleView/id/Christine_moves markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine_moves 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/SingleView/id/Improved_C_launcher markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Improved_C_launcher 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/SingleView/id/Video_de_Christine_en_atsion markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Video_de_Christine_en_atsion 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/SingleView/id/Py2exe markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Py2exe 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/SingleView/id/Imprimiendo_usando_GTK markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Imprimiendo_usando_GTK 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/SingleView/id/christine_with_the_C_launcher markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/christine_with_the_C_launcher 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/SingleView/id/Incorporando_python_en_nuestros_proyectos_en_C markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Incorporando_python_en_nuestros_proyectos_en_C 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/SingleView/id/Trabajando_con_gstreamer_Usando_los_Bins markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Trabajando_con_gstreamer_Usando_los_Bins 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/SingleView/id/Trabajando_con_gstreamerCreando_un_Playbin markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Trabajando_con_gstreamerCreando_un_Playbin 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/SingleView/id/Lazy_days_and_Plugins markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Lazy_days_and_Plugins 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/SingleView/id/Utilizando_las_seales markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Utilizando_las_seales 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/SingleView/id/Working_in_the_plugins_stuff markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Working_in_the_plugins_stuff 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/SingleView/id/Christmas_Christine markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christmas_Christine 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/SingleView/id/Christine_and_the_i18n_job markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine_and_the_i18n_job 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/SingleView/id/Christine_clibrary markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine_clibrary 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/SingleView/id/Christine_for_20061212 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine_for_20061212 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/SingleView/id/Christine_con_el_display_hecho_en_Cairo markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine_con_el_display_hecho_en_Cairo 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/SingleView/id/Inventarioavance markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Inventarioavance 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/SingleView/id/Python_y_sus_extensiones_en_C markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Python_y_sus_extensiones_en_C 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/SingleView/id/Python_Cookbook markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Python_Cookbook 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/SingleView/id/Keep_going markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Keep_going 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/SingleView/id/Aprendiendo_a_usar_Cairo markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Aprendiendo_a_usar_Cairo 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/SingleView/id/Tareas_en_christine markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Tareas_en_christine 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/SingleView/id/Mas_capturas_de_Christine markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Mas_capturas_de_Christine 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/SingleView/id/Volviendo_a_Christine markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Volviendo_a_Christine 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/SingleView/id/Como_loco markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Como_loco 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/SingleView/id/Si_estoy_enamorado_de_Christine markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Si_estoy_enamorado_de_Christine 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/SingleView/id/Christine_full_Screen_mode markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine_full_Screen_mode 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/SingleView/id/Recordando_PHP markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Recordando_PHP 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/SingleView/id/This_is_shameful__ markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/This_is_shameful__ 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/SingleView/id/Back_to_work markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Back_to_work 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/SingleView/id/Christine_on_August_2006 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine_on_August_2006 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/SingleView/id/Como_matar_dragones_usando_lenguajes_de_programacion markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Como_matar_dragones_usando_lenguajes_de_programacion 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/SingleView/id/To_CONSOL_2006 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/To_CONSOL_2006 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/SingleView/id/No_PyXine_in_Christine markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/No_PyXine_in_Christine 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/SingleView/id/Todays_christine_journey markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Todays_christine_journey 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/SingleView/id/Christine_playing_video markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine_playing_video Thu, 22 Jun 2006 15:01:30 -0500
<![CDATA[ christine ]]> ]]> http://islascruz.org/html/index.php?Blog/SingleView/id/christine markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/christine 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/SingleView/id/Emputado markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Emputado 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/SingleView/id/Frankenstein_desktop markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Frankenstein_desktop 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/SingleView/id/christine markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/christine 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/SingleView/id/Christine_improvements markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine_improvements 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/SingleView/id/Christine_y_las_canas_verdes markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine_y_las_canas_verdes 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/SingleView/id/Cristine_in_Sourceforgenet__Infinitum markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Cristine_in_Sourceforgenet__Infinitum 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/SingleView/id/Prueba markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Prueba 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/SingleView/id/Work_for_the_last_week markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Work_for_the_last_week 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/SingleView/id/Christine_again markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine_again 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/SingleView/id/Christine markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Christine 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_soportado.ogg")
player.set_state(gst.STATE_PLAYING)
gst.main()
 
Un simple player que reproducir??????? el archivo algun_formato_soportado.ogg, si es alguno de tipo video lo abrir??????? en alguna ventanita aparte, el cual es facil de empotrarlo en nuestra aplicaci???????n solicitando al video_sink que cambide de xwindow_id:

...

video_sink = gst.element_factory_make("xvimagesink")
video_sink.set_xwindow_id(window.xid)
...

 
Donde window es un widget de tipo contenedor, un HBox por ejemplo.

Ejemplos de esto se pueden encontrar en el directorio examples del codigo fuente de gst-python. ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/GStreamer markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/GStreamer Tue, 25 Apr 2006 15:05:03 -0500
<![CDATA[ Dropline Downloader ]]> Slackware Linux de hueso colorado, bueno, tambien sabr???????n que soy un fan???????tico de GNOME. Bueno, pues normalmente utilizo en la voladora a Slackware con Gnome como mi escritorio por defecto, que por lo general es Dropline Gnome.

El sistema de Instalaci???????n de Dropline Gnome es bastante bueno, pero tiene un Bug Garrafal, que si bien no es mortal, si es algo molesto. El caso es que cuando estas descargando tus paquetines, el instalador muestra algo como si fuera wget, pero si por algo cancelas (o por alguna razon pierdes conexion) mientras va algun paquete por el medio; cuando reinicias la descarga vuelves a descargar todo el paquete.. lo que es.. molesto, por que volver a descargar los 11.5 megas de los 11.7 megas si ya nomas fallta un piquito??.

Bueno, esto me esta pasando ahorita, que vine a un ciber pa descargar pero no se si es por onda del encargado o que pedo que a cada rato me esta cortando la puta conexi???????n y nomas no puedo descargar paquetes grandes.. pero aqui viene al rescate Wget y Python :-D.

Con este peque??????±o script podemos descargar los paquete de Dropline Gnome utilizando wget y ya que tengamos todos pues los instalamos utilizando el dropline-installer.

#!/usr/bin/env python
import os
f = open("/var/cache/dropline-installer/DroplineFiles2.14","r")
lines  = f.readlines()
f.close() for i in lines:
    split = i.split(":")
    a = os.popen("md5sum /var/cache/dropline-installer/%s"%split[0])
    md = a.readlines()[0].split()[0]
    a.close()
    if split[4] != md:
        os.popen("wget -c http://osdn.dl.sourceforge.net/sourceforge/dropline-gnome/%s -O /var/cache/dropline-installer/%s"%(split[0],split[0]))
    else:
        print "%s descargado"%split[0]
 
Que esta pitero, si, esta pitero, pero porque lo hice en 5 minutos, tal vez de aqui me prenda y haga algun tipo de Dropline Updater con Gtk. ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Dropline_Downloader markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Dropline_Downloader Wed, 19 Apr 2006 12:29:05 -0500
<![CDATA[ python + gtk + gtk.glade + MySQL ]]>
Es un peque??????±o programa de gesti???????n de base de datos. Originalmente lo pensaba hacer con PHP pero... me dio bastante flojera, sobre todo por tener que crear la interface, que si bien php me gusta, pues la flojera me gan??????? :-P, ademas, mi hermano como que est??????? renuente a tener instalado un servidor web, una base de datos y php en la maquina que va a usar de vez en cuando para jugar (no me digan nada, preguntenle a ??????©l). Esto ya hace un buen tiempo, si no es que un a??????±o XD.

Reciente me dio otra vez el gusanito de hacer el programita de inventario este para llevar un mejor control, porque esas hojas de calculo que lleva mi hermano como que no muy me convencen, entonces pues, comenc??????© a sacar algunas ideas, primero se me ocurrio hacerlo con Python+PyGTK, pues est???????n disponibles en GNU/Linux y en windows (entre otras) ademas de ser una prueba un tanto mas real (fuera del "Hola Mundo"), y me di cuenta que guardar los datos en archivos de texto iba a ser un dolor de cabeza, asi que mejor me puse a buscar algo para manejar MySQL. Lo que encontre en Sourceforge.net fue el proyecto mysql-python.

Con media hora de estarle echando un ojo a la documentaci???????n me basto para empezar a dise??????±ar y trabajar con la base de datos desde mi aplicaci???????n (de la cual ya llevaba algunas interfaces creadas). Me gusta como va y lo sencillo que es este modulo (mysql-python) ademas, sobra decir que esta disponible para Windows (que es lo que a mi hermano el windowsero le intereza). Asi que puedo trabajar en mi Slackware y a final de cuentas solo pasar el codigo a la maquina con windows que utiliza mi hermano.

Que si por que no le pongo GNU/Linux a la compu que usa mi hermano, sencillo, a el le encanta windows, juega Need For Speed y Microsoft Flight Simulator, cosas que no funcionan en GNU/Linux y por eso nomas no se puede... :-(.

]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/python__gtk__gtkglade__MySQL markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/python__gtk__gtkglade__MySQL Fri, 07 Apr 2006 18:15:10 -0500
<![CDATA[ gpkg 0.4 estable!! ]]> Por fin, depues de 4 meses de trabajo se me da el poder liberar gpkg en su version 0.4. gpkg incluye nuevas chucherias y ha mejorado algunas otras, a continuacion una lista de lo que hace.
  • Listar los paquetes instalado y los que han sido removidos.
  • Busquedas entre los paquetes
  • Mostrar/Ocultar paquetes en las listas durante la busqueda
  • Instalar/Actualizar/Remover sin congelarse mientras pkgtools esta trabajando.
  • Instalaci???????n/Actualizaci???????n/Desinstalaci???????n multiple de paquetes
  • La busqueda de archivos entre paquetes es mas rapida
  • La busqueda de archivos permite escojer en que paquetes se va a realizar la busqueda.
  • Instalaci???????n via Drag and Drop desde Nautilus
  • Instalaci???????n por via de comandos (gpkg -i paquete1 paquete2 ..)
  • Visor de logs.
  • Preferencias
  • La ayuda se muestra con Yelp (o el visor de ayuda preferido en Gnome)
  • Busqueda e Intalaci???????n de paquetes con swaret y slapt-get.
Update: Se han hecho unas correcciones, unos bugs que se me habian barrido y que fueron detectados por Paco Revilla Gpkg ya esta disponible para descarga en Sourceforge.net. Se encuentra en codigo fuente y empaquetado para Slackware Linux. ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/gpkg_04_estable markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/gpkg_04_estable Sat, 01 Apr 2006 12:52:41 -0600
<![CDATA[ gpkg ]]> gpkg 0.4 ya esta casi todo hecho. En estos ultimos dias he estado trabajando en la documentaci???????n, que ahora se ver??????? por medio de yelp. He corregido algunos peque??????±os bugs y he terminado de traducir algunas lineas de es_ES.

Espero dentro de la proxima semana liberar gpkg 0.4 por fin. ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/gpkg markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/gpkg Thu, 30 Mar 2006 21:16:25 -0600
<![CDATA[ TreeModelFilter con capacidades de organizaciÃ?Æ?Ã?³n ]]> Gpkg en su funcion de busqueda de paquetes ha tenido la opcion de mostrar solo las ocurrencias de la busqueda. Hacer esto en la lista es solo cuestion de crear un TreeModelFilter a partir de un modelo que ya existe. Pero tiene un inconveniente, TreeModelFilter no implementa las capacidadez de organizacion (Sorting), es decir, que en el TreeView no se puede hacer click en las cabeceras para reacomodar los elementos de la lista.

No hice mucho por lograr esto, pero por fin lo hice. Como, pues facil, no se si este bien, si haya otra forma, pero me sirvi??????? (si hay una mejor forma, dimelo :-D).

Partiremos con que ya tienes un modelo hecho.

filter = tree_view.get_model().filter_new()
sort = gtk.TreeModelSort(filter)
tree_view.set_model(filter)
 
Y aqui esta la tranza y lo "confuso". Al crear un modelo de tipo TreeModelFilter pierdes las capacidades de reorganizacion, y al crear un modelo de tipo TreeModelSort pierdes las habilidades del filtrado... mmmm, pero lo bueno es que con TreeModelSort puedes utilizar el metodo TreeModelSort.get_child() que devuelve el modelo hijo, es decir, el modelo base con el que TreeModelSort cre??????? uno nuevo. Entonces ya se pueden aplicar las propiedades al TreeModelFilter :-).

Vaya, en realidad no tengo mucho que escribir :-P, Tal vez esto es algo obvio, pero, pues puede llegar a ser util a alguien. ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/TreeModelFilter_con_capacidades_de_organizacin markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/TreeModelFilter_con_capacidades_de_organizacin Mon, 27 Mar 2006 20:21:25 -0600
<![CDATA[ TurboGears ]]>
Vi en barrapunto.com un framework bien bonito escrito en python (y para python) que ayuda en el desarrollo web, segun el autor de la nota al estilo Ruby on Rails, el framework se llama: Turbo Gears. Vi el videito de 29 megas, y se ve bastante bien la cosa.

Turbo Gears Turbo Gears
]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/TurboGears markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/TurboGears Sun, 12 Mar 2006 19:08:21 -0600
<![CDATA[ Ayuda con traductores!!!! ]]>
Obteniendo el codigo del cvs:

cvs -d: pserver:anonymous_at_cvs_dot_sourceforge_dot_net:/cvsroot/gpkg login (press enter has password).

cvs -z3 -d: pserver:anonymous_at_cvs_dot_sourceforge_dot_net:/cvsroot/gpkg co -P gpkg
tambien se puede por medio del cvs browser:
http://cvs.sourceforge.net/viewcvs.py/gpkg
O mas facil, por medio del tarbal nocturno.

http://cvs.sourceforge.net/cvstarballs/gpkg-cvsroot.tar.bz2 ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Ayuda_con_traductores markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Ayuda_con_traductores Fri, 10 Mar 2006 18:07:17 -0600
<![CDATA[ Python cambia de piel ]]> Barrapunto: Python muda de piel. Aunque el nombre "python" de este grandioso lenguaje de programaci???????n no se refiere a ningun animal rastrero (seg???????n Guido V. Rossum), el titulo del cambio de piel le viene perfecto.

]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Python_cambia_de_piel markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Python_cambia_de_piel Thu, 09 Mar 2006 16:17:57 -0600
<![CDATA[ gpkg 0.3.3 ]]> gpkg, algunos cambios son:
  • Soporte para instalacion usando Drag & Drop sobre la lista de paquetes instalados.
  • Inicio mas rapido
  • Error en el scroll de la ventana de instalaci???????n (provocado por vte y el scrollwindow)
  • Soporte para slapt-get y swaret
Aun es una version en desarrollo pero agradeceria muchisimo si los slackeros lo prueban y me comentan los errores que puedan llegar a encontrar.

Source tgz Slackware ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/gpkg_033_ markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/gpkg_033_ Sun, 05 Mar 2006 13:03:53 -0600
<![CDATA[ Escribiendo modulos de Python en C ]]> Python es que permite su extensi???????n con modulos escritos en C. Esto permite crear aplicaciones mas rapidas. Que si bien Python no es un lenguaje pesado como otros, por ser un lenguaje interpretado es obviamente un poco mas lento que C.

Para compensar esto en nuestros programas, podemos escribir las partes criticas en C, y utilizarlos desde Python como si fueran algun otro modulo escrito en Python con la ventaja de que ser???????n mucho mas rapido.

Esto ya se usa desde hace rato, y la mayoria de los programadores en Python inconscientemente lo han de hacer, por ejemplo, si usas expresiones regulares, o si usas los bindings de GTK (PyGTK) logrando que casi no se note la difernencia en los tiempos.

Tomando en cuenta esto, podemos crear nuestros propios modulos que hagan lo que nosotros queremos que hagan (modulos especificos no hay que reinventar la rueda).

Un buen uso de estos modulos seria sobre las iteraciones. En este ejemplo suponemos que queremos crear un programa que nos imprima numeros del 0 hasta un numero deseado (1500 en este caso). En python no es cosa mas que de hacer esto:

for i in range(1500):
    print i,
 
lo cual nos tomaria aproximadamente 1 segundo (0m0.758s me arroja usando time). que no es nada del otro mundo, es un simple ejemplo mundano. Y usando C, sobre una iteraci???????n tendriamos algo asi:

static PyObject *
scribe (PyObject *self, PyObject *args)
{
    const int command;
    int n = 0;

    if (!PyArg_ParseTuple(args, "i", &command))
        return NULL;

    for (n = 0; n <= command; n++){
        printf("%d ",n);
    }
    return Py_BuildValue("i",command);
}
 
En este ejemplo rascuacho el uso de la iteraci???????n con Python arroja obviamente un valor de tiempo mayor que el de C:

C:
real 0m0.092s
user 0m0.024s
sys 0m0.006s
Python:
real 0m0.838s
user 0m0.023s
sys 0m0.009s
Utilizando este esquema podriamos bien utilizar a C para las cosas mas complicadas, para los puntos criticos, y Python para las interfaces :-).

Nota: Los tiempos varian, por el cache de linux y por las demas aplicaciones que se tengan corriendo en el momento. ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Escribiendo_modulos_de_Python_en_C markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Escribiendo_modulos_de_Python_en_C Tue, 28 Feb 2006 18:22:12 -0600
<![CDATA[ Optimizando Gpkg II ]]> Gpkg, principalmente porque los pinches bindindg de VTE me han estado dando unos problemas con el metodo vte.fork_command(), aunque no estoy seguro bien por que ser??????? el fallo.

Lo poco que he hecho en esta semana ha sido reescribir lo que habia perdido por un estupido error mio, y dentro de estas cosas que ya habia borrado estaba una clase en la que se obtenia la informaci???????n para cada paquete. Anteriormente se utilizaba la clase packages, y se obtenia la informaci???????n por medio de metodos como

packages.get_package_short_name(package)
packages.get_package_full_desc(package)
packages.get_package_short_desc(package)
etc...

 
pero esto hace que por cada una de estas cosas tenga que abrir el indice y hacer una iteraci???????n buscando y acomodando las cadenas, que para un solo paquete no es nada dificil, pero para un sistema de unos 571 paquetes (como lo tengo yo) pues hace que la cosa se alente al generar las listas, pues tiene que abrir y cerrar el indice unas tres veces por paquete. Obviamente esto no es bueno, y si lo escrib??????­ asi en un principio fue porque lo hice de a putazo para ver como lucia la cosa.

La clase que escribi ahora se crea enviando el nombre del paquete como parametro, y se pueden obtener los valores como si fueran parte de un diccionario:

package = packageize("gpkg-0.3.2-noarch-1mkz")
name = packageize["name"]
short_desc = packageize["desc"]
 
Obviamente no voy a meter toooooda la informacion del paquete en una sola instancia y de a putazo, porque al hacer la iteraci???????n (cuando se generan las listas) hago mas pesada la cosa, asi que para cosas como obtener el indice o el script se necesita pedirlos como metodos.

package = packageize("gpkg-0.3.2-noarch-1mkz")
index = package.get_index()
script = package.get_script()
full_desc = package.get_description()
 
Esto hace que gpkg trabaje un poco mas rapido, claro que con respecto a gpkg-0.2 no hay una diferencia notable, pero es porque gpkg-0.3.x ahora tiene que crear mas widgets y consultar cosas con gconf, inicia el programa con libgnome, etc. pero no tarda mucho en inciar.

Gpkg cuenta con el parametro -u con el cual se pueden actualizar la de paquetes instalados sin tener que mostrar toda la gui, algo util cuando es la instalaci???????n de gpkg. Generar la lista desde 0 toma unos ~10 segundos:

markuz:$ rm ~/.gpkg/installed
markuz:$ time ./gpkg -u
Updating installed list
List updated

real 0m10.403s
user 0m1.289s
sys 0m0.323s
y el actualizarla a partir de una lista ya generada toma entre 1 y 5 segundos.

markuz:$ time ./gpkg -u
Updating installed list
List updated

real 0m1.788s
user 0m0.593s
sys 0m0.152s
Ahora, lanzar gpkg con todo y todo (inicial la aplicacion con libgnome, construir la venta principal, el resto de los widgets, actualizar listas, etc..) toma en un principio (con una lista ya generada) entre 5 y 10 segundos. pero que estando en cache puede reducirse a 2~5 segundos.

markuz:$ time ./gpkg -e
real 0m7.781s
user 0m1.734s
sys 0m0.281s
markuz:$ time ./gpkg -e
real 0m2.396s
user 0m1.723s
sys 0m0.235s
El parametro -e es para terminar la aplicaci???????n una vez que se haya generado todo (incluso mostrar la ventana principal).

Bueno, es en lo que he estado trabajando esta semana sobre gpkg, en la que sigue le dar??????© soporte para swaret y ver??????© de que forma resuelvo ese problemita que tengo con los bindings de VTE. ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Optimizando_Gpkg_II markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Optimizando_Gpkg_II Sat, 25 Feb 2006 11:38:16 -0600
<![CDATA[ Gpkg con soporte para slapt-get ]]> Gpkg Cuenta ahora con un soporte para slapt-get. De momento no es nada comparable con lo que puede hacer GSlapt (de los mismos desarrolladores de Slapt-get).

Dado que Gpkg debe ser peque??????±o, solo he agregado una opcion mas a la busqueda de paquetes, ahora, al hacer una busqueda de paquetes tambien se muestra la opcion de "buscar en:" y de ahi escogemos slapt-get y pulsamos el boton de busqueda.

De ahi nos parsear??????? la salida de la busqueda como una lista, donde podremos seleccionar los paquetes que queremos instalar, y entonces le damos "install" y el paquete se ha de instalar usando slapt-get.

Ahora, por hay que seleccionar un menu la opcion "slapt-get" ??, facil, porque tambien quiero darle soporte a swaret. Me he dado cuenta de que gpkg no podr??????? adentrarse un poco mas si no hace esas labores de instalaci???????n tambien, y como no pienso reinventar la rueda, pues es mejor utilizar algo que ya existe, no creen?.

]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Gpkg_con_soporte_para_slaptget markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Gpkg_con_soporte_para_slaptget Thu, 16 Feb 2006 18:25:00 -0600
<![CDATA[ gpkg 0.3.2 ]]> gpkg con las autotools :-). Ahora instalar gpkg no es de un simple:

markuz:$ python setup.py install
a un (mas largo pero personalizable):
markuz:$ sh configure --prefix=/usr --sysconfdir=/etc
markuz:$ make
markuz:$ make install
Y que es lo que se logra con esto?. Algunos archivos en python son configurados, sobre todo los que definen donde se van a localizar ciertos archivos (imagenes, *.glade, logs, locales, etc...).

Ademas que de esta manera la instalaci???????n de gpkg es mas amigable, mas com???????n.

He creado un paquete de a como lo tengo ahorita, que si bien no me ha fallado en mis pruebas me reservo a que esta en "pruebas", aun es c???????digo en trabajo y puede tener errores. Sin embargo puedes por favor probarlo y si encuentras bugs, podrias notificame?

Codigo fuente: gpkg-0.3.2.tar.gz Paquete para Slackware 10.2 : gpkg-0.3.2-noarch-2mkz.tgz
]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/gpkg_032 markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/gpkg_032 Sun, 12 Feb 2006 19:44:57 -0600
<![CDATA[ Utilizando las autotools para configurar scripts en python ]]> Python y pensamos en distribuirlo por lo general utilizamos el modulo "DistUtils" de Python que nos permite instalar los modulos y algunas cosas extra. Pero distutils no nos da la flexibilidad de un script como el "configure", para poder definir donde se han de instalar nuestros archivos de interface gr???????fica, o las imagenes, cual ser??????? el directorio en donde se guardara la configuracion (en caso de no usar Gconf) o donde se guardaran los logs, etc..

Para esto tenemos entonces las fenomenales Autotools ;-). Ahora, todo mundo ha de pensar, no mames.... si los scripts en Python no son algo compilado!!!. No importa si es compilado o no, el chiste es que el script se pueda configurar al gusto del cliente. Supongamos que en nuestra clase "pixmaps" definimos donde vamos a guardar las imagenes. Lo mas obvio seria ponerlo directamente:

class pixmaps:
    __init__(self):
        '''Ejemplo'''
        programname = "miprograma"
        version = "0.1"
        pixmapsdir = "/usr/share/pixmaps/miprograma/"
     .
     .
     .
     .
 
Que si bien __Deberia__ de ser la path correcta, puesto que un programa deberia ser instalado en "/usr" no en "/usr/local", no todos quieren que sea as??????­., habr??????? alguien que lo quiera instalar en su $HOME.

Utilizando Autotools podemos definir estas cosas utilizando el configure y los Makefile. He aqui la cosa, primero analicemos el script configure.ac con el que despues elaboraremos el dichoso script "configure":

AC_INIT(mipaquete,0_dot_1,markuz_at_islascruz_dot_org)
AM_INIT_AUTOMAKE(miprograma, 0.1)

AM_MAINTAINER_MODE

AM_PATH_PYTHON

PROGRAM_NAME="paquete"
VERSION="0.1"
AC_SUBST(PROGRAM_NAME)
AC_SUBST(VERSION)

AC_CONFIG_FILES([
Makefile
paquete/Makefile
])

AC_OUTPUT
Lo primero es iniciar nuestro escript, lo interezante es que aqui mismo definimos variables como "PROGRAM_NAME" y "VERSION" que despues mandamos a los makefile con "AC_SUBST()". Lo que sigue es declarar los scripts que se han de crear (usando AC_CONFIG_FILES), como el mismo Makefile y el de nuestro paquete que se encuentra en el directorio "paquete", para poder hacer esto necesitamos que exista un archivo con el mismo nombre pero con un ".in" al final, es decir, en vez de tener "Makefile", tendriamos "Makefile.in"

Para poder crear los makefile, debemos tener un Makefile.am en nuestro directorio base, y uno en cada subdirectorio, nuestro Makefile.am en nuestro directorio base deberia ser algo asi (muuuy, pero muy basicamente):

SUBDIRS = paquete
Hay muchas cosas que estoy omitiendo aqui, pero que podremos ver en el siguiente Makefile. Si nos damos cuenta tenemos una variable llamada SUBDIRS, que define los directorios en los que "make" y "automake" van a entrar y hacer lo suyo.

Ahora, el Makefile.am que debe estar en el subdirectorio "paquete" deberia contener esto:

scripts_files=pixmaps.py
scriptsdir=($pkgpythondir)/paquete

pkgdatadir=${datadir}
pkgsysconfdir=${sysconfdir}

edit = sed \
-e 's,_at_datadir\_at_,$(pkgdatadir),g' \
-e 's,_at_prefix\_at_,$(prefix),g' \
-e 's,_at_sysconfdir\_at_,$(pkgsysconfdir),g'

all: all-am

pixmaps.py: Makefile $(srcdir)/pixmaps.py.in
$(edit) $(srcdir)/pixmaps.py.in > pixmaps.py

clean:
rm -f gtk_misc.py
A la hora de que se ejecute "make" Make va a ejecutar las reglas especificadas para all-am (crear los nuevos archivos a partir de templates), dentro de esto encontramos que se manda a llamar la variable "edit", que en realidad ejecuta sed y sustituye las variables por la version ya "expandida".

Entonces para poder generar el script "configurado" tenemos que crear un template del mismo archivo con un ".in", si nos damos cuenta seria pixmaps.py.in, que deberia ser asi:

class pixmaps:
    __init__(self):
        '''Ejemplo'''
        programname = "miprograma"
        version = "0.1"
        pixmapsdir = "_at_datadir_at_/pixmaps/miprograma/"
     .
     .
     .
 
A la hora de ejecutar "make" este de acuerdo al template crear??????? el nuevo script sustituyendo las variable sencontradas, las cuales estan encerradas entre arrobas "@". asi el usuario puede decidir donde el programa ha de buscar los pixmaps. :-).

Un error seria pedir que "configure" haga esto, pues se pude hacer que configure nos genere los nuevos archivos solo sustituyendo las variables, pero no expande las variables como "sysconfdir","datadir", e incluso, si "prefix" esta vacio lo marcara como NONE. Lo cual no es muy bueno que digamos, podemos utilizarlo para sustituir peque??????±as variables que definimos ahi mismo como PROGRAM_NAME y VERSION.

Nota: las _at_ son en realidad arrobas, la cosa esta me parsea y me quita las arrobas :-P ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Utilizando_las_autotools_para_configurar_scripts_en_python markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Utilizando_las_autotools_para_configurar_scripts_en_python Wed, 08 Feb 2006 13:30:36 -0600
<![CDATA[ Escribiendo aplicaciones rapido y portable ]]> Python es un lenguaje de programaci???????n interpretado, esto le permite funcionar donde el interprete funcione, comunmente en sistemas tipo UNIX, Microsoft Windows y MacOS. GTK+ es un conjunto de bibliotecas que permiten el escribir aplicaciones con una interface gr???????fica de manera muy sencilla, con una colecci???????n de widgets y un manejo de eventos y se??????±ales muy bueno, escrito completamente en C permite que otros lenguajes puedan tomarlo y asi crear bindings como es el caso de PyGTK, Sindo que GTK+, Python y PyGTK son altamente portables, entonces, ????????Que nos impide hacer aplicaciones multiplataforma con estas herramientas?. NADA.

Y para muestra basta un bot???????n. Hace unos dias un cuate me pidi??????? ayuda sobre un programa que convirtiera de decimal a binario, octal y hexadecimal, buscando en la red encontre una funcion que hace esto, convertir de decimal a cualquier otra base entre 2 y 36. El programa que mi cuate entreg??????? era un tanto rascuacho, lo normal de cualquier alumno que apenas empieza a programar, solo pide un numero, una base y te devuelve el valor, si quieres volver a calcular tienes que volver a ejecutar el progrmar.

Entonces me di a la tarea de hacerlo con PyGTK, el programa fue escrito originalmente en python, asi que no era la gran labor :-).

Lo primero que se hace es crear la interface con Glade:

Y luego a rellenar con codigo :-)
import gtk
from gtk import glade

def base10toN(num,n):
        """Change a  to a base-n number.
        Up to base-36 is supported without special notation."""

        num_rep={10:'A',
        11:'B',
        12:'C',
        13:'D',
        14:'E',
        15:'F',
        16:'G',
        17:'H',
        18:'I',
        19:'J',
        20:'K',
        21:'L',
        22:'M',
        23:'N',
        24:'O',
        25:'P',
        26:'Q',
        27:'R',
        28:'S',
        29:'T',
        30:'U',
        31:'V',
        32:'W',
        33:'X',
        34:'Y',
        35:'Z'}
        new_num_string=''
        current=num
        while current!=0:
                remainder=current%n
                if 36>remainder>9:
                        remainder_string=num_rep[remainder]
                elif remainder>=36:
                        remainder_string='('+str(remainder)+')'
                else:
                        remainder_string=str(remainder)
                new_num_string=remainder_string+new_num_string
                current=current/n
        return new_num_string


class converse:
        def __init__(self):
                '''
                Constructor
                '
''
                self.xml = glade.XML("converse.glade",None,None)
                self.xml.signal_autoconnect(self)
                self.base = 2
                self.entry = self.xml.get_widget("entry1")
                self.result_label = self.xml.get_widget("result_label")
                try:
                        self.decimal = self.entry.get_text()
                except:
                        self.decimal = 0
                        self.entry.set_text("0")
                self.window()
       
        def window(self):
                win = self.xml.get_widget("window")
                win.connect("destroy",gtk.main_quit)
        def spin_change(self,spinbutton):
                '''
                Toma el valor de spinbutton (GtkSpinButton)'
''
                try:
                        self.base = int(spinbutton.get_value())
                        #print dir(spinbutton)
                        self.get_decimal_to_base()
                except:
                        self.result_label.set_text("Not a number")
        def entry_change(self,entry):
                '''
                Obtiene el valor del numero decimal, lo intentara convertir
                a entero, en caso de que no pueda imprimira NAN en el resultado.
                '
''
                if entry.get_text() != "":
                        try:
                                self.decimal = int (entry.get_text())
                                self.get_decimal_to_base()
                        except:
                                self.result_label.set_text("Not a Number")
                else:
                        self.decimal = 0
                       
        def get_decimal_to_base(self):
                '''
                Invoca a base10toN y muestra el resultado en
                el label de resultado.
                '
''
                print self.decimal,self.base
                r = str(base10toN(self.decimal,self.base))
                self.result_label.set_text(r)
        def main(self):
                '''
                Get in the gtk main loop
                '
''
                gtk.main() if __name__ == "__main__":
        a = converse()
        a.main()
 
Y listo: algo asi debe salir:

Ventajas:
  • La aplicaci???????n es mas amigable
  • No es necesario volver a ejecutar el programa para calcular el mismo numero en otra base u otro numero en otra base (etc..), Todo se recalcula al cambiar el numero o la base :-)
Pero.. tenemos que ser realistas, no todo mundo usa GNU/Linux, y aunque mi cuate si lo hace de vez en cuando, normalmente usa Windows. Entonces, pues quise ver que tan dificil seria montarse esta cosa en Windows.

Lo primero que hay que hacer es conseguirse las dependencias:
  • Python
  • PyGTK (2.8 para python 2.4 con pycairo :-))
  • GTK+ Para Windows. Nota: Aunque se puede obtener del FTP de Gnome, es mucho mas facil obtenerlo del proyecto Glade Win32.
  • Libglade que igual es preferible que sea de GladeWin32.
Instalamos todos estos cachivaches (que igual son necesarios en Linux pero que por lo general ya est???????n instalados en nuestra distro), entonces ejecutamos python en la path de nuestro programita (por lo de las paths relativas :-)) o mas sencillo, le damos doble click al icono del programa (que siendo un script de python deberia ser una "viborita verde"). y Listo:

Y esto.. sin cambiar ni una sola linea al c???????digo :-) ]]>
http://islascruz.org/html/index.php?Blog/SingleView/id/Escribiendo_aplicaciones_rapido_y_portable markuz@islascruz.org (Marco Antonio Islas Cruz) http://islascruz.org/html/index.php?Blog/SingleView/id/Escribiendo_aplicaciones_rapido_y_portable Fri, 03 Feb 2006 16:03:35 -0600