pyxmms trouble

Florent Rougon flo at via.ecp.fr
Wed May 5 06:06:28 EDT 2004


[ Please note that I am not subscribed to this group. A friend of mine
  kindly pointed me to this thread (since I am the author of PyXMMS). If
  you want to be sure that I read other posts in this thread, please Cc
  me. ]

David Smith <dsmith at programmablesolutions.net> wrote:

> Hi:

Hi,

>     I am a newbie to python and in general programming. My problem is
> that I am trying to use the pyxmms remote to add songs to the xmms

Don't confuse PyXMMS and PyXMMS-remote... the latter is a command-line
interface to the former.

> playlist. However, no matter whether I open the interpreter or put it in
> a file and run the script the output is the same. It just sits there
> with no error msg of any kind and doesn't add the file to the playlist.

libxmms/xmmsctrl.c is not very helpful with respect to errors. For
instance:

void xmms_remote_playlist_add(gint session, GList * list)
{
        gchar **str_list;

        [...]

        xmms_remote_playlist(session, str_list, num, TRUE);
        g_free(str_list);
}

You see, PyXMMS has no way to tell whether an error happened in this
function.

> I then have to ctrl-c to break it and alot of times this makes the
> keyboard stop working and I have to restart X to get it working again. 

Ugh, that sounds a bit excessive. Did you make sure that all xmms
processes were dead?

   ps -el | grep xmms                 ("| less" instead of "| grep xmms"
                                       to see the column headers first)
   kill <pid>                         and if this is not enough:
   kill -<signumber> <pid>            with signumber being 1, then 15 if
                                      it wasn't enough, then 9 (the last
                                      one should not fail except in
                                      very, very bad situations)

>     Here is the I'm using code:

[...]

> os.popen2('/usr/bin/xmms')

There is a problem here: you are effectively opening two pipes, one
connected to xmms's stdin and one connected to its stdout; but you never
read from them since you don't even reference them from a variable.

First, you miss xmms' messages (yes, it might give you error messages!).
Second, in case xmms happens to output enough stuff on one of these
pipes (I believe it is 4096 bytes on Linux), it will simply block until
you start reading from the pipe(s) that is/are full. That is what I
would call suboptimal behavior.

You should make sure your code avoids this blocking issue. One way is to
make as in <PyXMMS-source>/src/control.py, line 321:

        child_pid = os.fork()
        if child_pid == 0:
            # We are in the child, me MUST NOT trigger any exception (look at
            # _spawnvef in Python's os.py).
            try:
                os.execvp(abs_prog_name, (abs_prog_name, "-p") + tuple(seq))
            except:
                # We cannot know in the father process if the child's execvp
                # failed, but AFAIK, there is no simple solution since I don't
                # want the father to wait for the child's completion. init
                # will be a good father. :-)
                os._exit(127)


> time.sleep(5)

Mmm, I don't usually start XMMS this way (and in the previous example,
the first command given to XMMS is its -p command-line option, which
avoids the problem of having to wait until XMMS is ready), so I'm not
sure what the best practice is here. If I were you, I would try to wait
before XMMS' control socket appears in /tmp[1] and see if it is
responsive from that point on. I think that should be enough: libxmms
(called by PyXMMS) would be able to write your first request to the
socket and defer the answer until XMMS is ready and writes it to the
socket.

> print xmms.control.is_main_win(0)
> if xmms.control.is_main_win(0) == 1:

Well, you don't need the "== 1" part but it will work of course. Since
Python introduced True and False, you should try to be consistent with
that choice and simply use "if xmms.control.is_main_win(0):". (and yes,
one day, PyXMMS will probably yield True and False where booleans are
returned but this was written before True and False existed in Python)

> seq = "/home/eomer/tumes.m3u"
> xmms.control.playlist_add_allow_relative(seq, 0)

Ahhh. That is your problem. Let me quote PyXMMS' documentation:

  playlist_add_allow_relative(seq, session=0)
      Add files/URLs to the playlist, allowing relative file names.

      seq     -- a sequence of files/URLs
      session -- the XMMS session to act on

  Return None.

Your 'seq' is not a sequence of files and/or URLs. Oh, wait. Yes, it is!
And that is why you don't get a TypeError or something from PyXMMS
(PyXMMS does perform error handling where it is possible). But this is
most probably not the sequence you want, since its elements are:

  "/", "h", "o", "m", "e", "/", "e", "o", "m", etc.

Now you wonder why XMMS cannot add these files to the playlist...

> Under the interpretor I do access it differently (and I opened xmms
> myself):
> import xmms.control
> xmms.control.playlist_add('/home/eomer/tumes.m3u', 0)
>
> 	I have used both of these functions both ways. Both produce the same
> result. The playlist_clear function works perfectly. Also I have tried
> other files that aren't actually m3u lists. All have the same effects.

Interactive use is nice, but if something is wrong in a script, it is
also wrong in the interactive shell...

> 	I am running Xmms 1.2.10 (just in case you need to know :D). Oh also if
> you know a better way to open xmms from the script and allow the script
> to still run please feel free to comment. 

I think that was done above.

> Oh, this is just an experiment not life or death (yet :)).

What? I didn't save your life?! Oh shhhhh***t...


PS : you could solve most of your problems by studying the code of
     PyXMMS-remote since this can be considered as example code for most
     PyXMMS functions (well, the ones from xmms.control; for
     xmms.config, there are examples in the documentation).


[1] /tmp/xmms_${USER}.${XMMS_SESSION}, I believe.

-- 
Florent



More information about the Python-list mailing list