Giter VIP home page Giter VIP logo

python-mpd2's Introduction

python-mpd2

Build Status

python-mpd2 is a Python library which provides a client interface for the Music Player Daemon.

Difference with python-mpd

python-mpd2 is a fork of python-mpd. While 0.4.x was backwards compatible with python-mpd, starting with 0.5 provides enhanced features which are NOT backward compatibles with the original python-mpd package (see Porting Guide for more information).

The following features were added:

  • Python 3 support (but you need at least Python 3.6)
  • asyncio/twisted support
  • support for the client-to-client protocol
  • support for new commands from MPD (seekcur, prio, prioid, config, searchadd, searchaddpl, listfiles, rangeid, addtagid, cleartagid, mount, umount, listmounts, listneighbors)
  • remove deprecated commands (volume)
  • explicitly declared MPD commands (which is handy when using for example IPython)
  • a test suite
  • API documentation to add new commands (see Future Compatible)
  • support for Unicode strings in all commands (optionally in python2, default in python3 - see Unicode Handling)
  • configurable timeouts
  • support for logging
  • improved support for sticker
  • improved support for ranges

Getting the latest source code

If you would like to use the latest source code, you can grab a copy of the development version from Git by running the command:

$ git clone https://github.com/Mic92/python-mpd2.git

Getting the latest release

The latest stable release of python-mpd2 can be found on PyPI

PyPI:

$ pip install python-mpd2

Installation in Linux/BSD distributions

Until Linux distributions adapt this package, here are some ready to use packages to test your applications:

See INSTALL.rst

Installing from source

To install python-mpd2 from source, simply run the command:

$ python setup.py install

You can use the --help switch to setup.py for a complete list of commands and their options. See the Installing Python Modules document for more details.

Documentation

Documentation

Getting Started

Command Reference

Examples

Testing

Just run:

$ python setup.py test

This will install Tox. Tox will take care of testing against all the supported Python versions (at least available) on our computer, with the required dependencies

If you have nix, you can also use the provided default.nix to bring all supported python versions in scope using nix-shell. In that case run tox directly instead of using `setup.py`:

$ nix-shell --command 'tox'

Building Documentation

Install Sphinx:

$ pip install Sphinx

Change to the source directory and run:

$ python ./setup.py build_sphinx

The command reference is generated from the official mpd protocol documentation. In order to update it, install python-lxml and run the following command:

$ python ./doc/generate_command_reference.py > ./doc/topics/commands.rst

python-mpd2's People

Contributors

auchter avatar bors[bot] avatar btall avatar chme avatar chrysn avatar dependabot[bot] avatar divinedominion avatar equalsraf avatar francois2metz avatar frozencemetery avatar github-actions[bot] avatar glen3b avatar laurentb avatar mafrosis avatar maksbotan avatar mgorny avatar mgrachten avatar mic92 avatar mineo avatar multani avatar mweinelt avatar rnixx avatar rvl avatar smcv avatar soongnoonien avatar supermihi avatar sylvainde avatar timgates42 avatar xcant avatar yakshaver2000 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-mpd2's Issues

MPDClient.seekcur() is an unknown command

I'm trying to seek on the currently playing song and I'm getting the following error:

  CommandError: [5@0] {} unknown command "seekcur"

Using MPDClient.seek() works fine, but it requires specifying a song and I'd rather just to be able to default to the current song.

UnicodeDecodeError in _read_line()

Some entries in my MPD library seem to cause a UnicodeDecodeError. I'm using Python3.

Script:

#!/usr/bin/python

import mpd 

client = mpd.MPDClient()
client.connect("localhost", 6600)
print(client.mpd_version)

client.iterate = True
allinfo = client.listall()

for item in allinfo:
  print(item)

client.close
client.disconnect()

Output:

....
{'file': 'Reggae - Ragga - Ska/Asian Dub Foundation/2000 - Asian Dub Foundation - Community Music/10 - Asian Dub Foundation - The Judgement.mp3'}
{'file': 'Reggae - Ragga - Ska/Asian Dub Foundation/2000 - Asian Dub Foundation - Community Music/11 - Asian Dub Foundation - Truth Hides.mp3'}
Traceback (most recent call last):
  File "./mpd-test.py", line 12, in <module>
    for item in allinfo:
  File "/usr/lib/python3.2/site-packages/mpd.py", line 304, in _iterator_wrapper
    for item in iterator:
  File "/usr/lib/python3.2/site-packages/mpd.py", line 278, in _read_objects
    for key, value in self._read_pairs():
  File "/usr/lib/python3.2/site-packages/mpd.py", line 260, in _read_pairs
    pair = self._read_pair(separator)
  File "/usr/lib/python3.2/site-packages/mpd.py", line 248, in _read_pair
    line = self._read_line()
  File "/usr/lib/python3.2/site-packages/mpd.py", line 229, in _read_line
    line = self._rfile.readline()
  File "/usr/lib/python3.2/encodings/ascii.py", line 26, in decode
    return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 6249: ordinal not in range(128)

I am using mpd 0.17.0, Python 3.2.3 and the latest python-mpd2 from today.

Command seekcur() jumps to the next song in random mode

The command seekcur() works for all modes except random mode as expected. When i'm using the random mode, i.e. seekcur("+10"), mpd jumps to the next song and starts playing at the time position of the last song + 10 secs.

I think this is not the normal behaviour.

print(client.mpd_version): 0.18.0
mpd --version : 0.18.12
(maybe a bug, if not, please use + if you cannot figure out the correct version 0.18.+)

python-mpd2 version: 0.5.3

Fix for building with non-unicode locale

Hi. This patch allows to build python-mpd in non-unicode locale environment and is compatible with both py2 and py3. Please consider applying it to the master.

--- python-mpd-0.5.1/setup.py   2013-03-21 23:45:53.000000000 +0400
+++ python-mpd-0.5.1/setup.py   2013-04-25 22:01:52.000000000 +0400
@@ -6,6 +6,9 @@
 import sys,os
 import mpd

+if sys.version_info[0] == 2:
+    from io import open
+
 CLASSIFIERS = [
     "Development Status :: 5 - Production/Stable",
     "Intended Audience :: Developers",
@@ -45,7 +48,7 @@
         sys.exit(errno)

 def read(fname):
-    return open(os.path.join(os.path.dirname(__file__), fname)).read()
+    return open(os.path.join(os.path.dirname(__file__), fname), encoding="utf8").read()

 VERSION = ".".join(map(str, mpd.VERSION))

Don't get how the "group" keyword works

Hello,
I'm trying to list my albums grouped by artists, but I don't really get how to do that : your documentation indicates that list() can take an argument "group", so I try to do that:

    mpdclient.connect(server, port)
    mpdclient.list("album", "group", "albumartist")
mpd.CommandError: [2@0] {list} not able to parse args

Did I misunderstood your doc or do I have to do this in 2 operations (listing artists, and then listing the albums for each artist of the list) ?
Thank you

Cancelling `idle()`

Is there a way to cancel an idle() command?

In MPD you can send a noidle command to cancel a previously issued idle command. But in python-mpd2 the idle command is blocking, so there seems to be no way to cancel it.

The best approach would probably be an asynchronous approach (maybe involving future objects) with blocking helper functions around them. Would this be solved by #30?

playlist rename method can not process chinese characters on Win7?

Hi Mic92,

I got a problem using python-mpd2 version 0.4.2.

I'm running:
Python 2.7.3,
PyQt4.9.1,
mpd 0.16.8,
Windows 7 professional SP1 ( English Edition)

The problem i got is the playlist rename method.
My english is bad, but the following fuzzy code may give you some clues to understand what i mean:

import sys, mpd

sys.getfilesystemencoding()
'mbcs'

m = mpd.MPDClient()
m.connect('localhost', 6600)

old_playlist_name = "ๅคง" # Name in Chinese which means 'Big' in English, and it is already existed in m.listplaylists()
new_playlist_name = "New Name"

m.rename(old_playlist_name, new_playlist_name)

Error below (The same logic with the above code):

Traceback (most recent call last):
File "xplayer.py", line 2171, in OKPressed
handler.rename(self.selectedItem, givenName)
File "c:\Python27\lib\site-packages\mpd.py", line 491, in decorator
return wrapper(self, name, args, bound_decorator(self, returnValue))
File "c:\Python27\lib\site-packages\mpd.py", line 213, in _execute
return retval()
File "c:\Python27\lib\site-packages\mpd.py", line 486, in decorator
return function(self, _args, *_kwargs)
File "c:\Python27\lib\site-packages\mpd.py", line 314, in _fetch_nothing
line = self._read_line()
File "c:\Python27\lib\site-packages\mpd.py", line 235, in _read_line
raise CommandError(error)
mpd.CommandError: [50@0] {rename} No such playlist

The most strange thing is:

new_name = unicode(Chinese_Characters)
m.save(new_name)

Works fine.
So i really don't know why.

Please help, thanks a lot.

client.status() does not report nextsong or nextsongid

I am sorry if i am missing something very obvious but according to the docs , client.status() should return the next song and the nextsongid. If these have been deprecated, could someone point me in the right direction on how (when the playlist is in random mode) to pick a song from the current playlist and get it to play immediately.

feature request: add some commands

Hi,
I've found this module very interesting. Is it possible, to add some commands?
It would be nice when it's possible to use:
add
insert

to manipulate the queue.
Regards Jรถrg

setvol doesn't throw exception

Hi,
I have the following problem: Every once in a while my Raspberry Pi re-detects my USB Soundcard. After that, I can't set the volume via mpdclient.setvol(x), it just shows '0' in mpdclient.status()['volume']. However, no exception is thrown.
Now, here's the funny thing. Running mpc also shows volume 0%. But running mpc volume 50 errors with problems setting volume. Now, if I try setvol(x) again with mpdclient, it also raises an exception: mpd.CommandError: [52@0] {setvol} problems setting volume

I think this exception should to be thrown, without having to use mpc before.

Idle and noidle

I may have wrong, but actually the noidle command doesn't works.

If I want to stop idling to quering the status for instance, I have to cancel idling with the noidle command.

client.send_idle('player')
client.noidle()
mpd.PendingCommandError: Cannot execute 'noidle' with pending commands

I'm working on a patch to cancel the idle command when sending noidle, but any insights is welcome.

Connection got reset after long time pause

It would be nice to get help.

OS: Mac OS X 10.9.4
MPD: 0.18.13 (Installed by homebrew: brew install mpd)
python-mpd2: 0.5.3

For debugging, i inserted one line "print('Line from client: ', line)" into the _read_line method of mpd.py. Like below: (Please see the third line)

    def _read_line(self):
        line = self._rfile.readline()
        print('Line from client: ', line)
        if self.use_unicode:
            line = decode_str(line)
        if not line.endswith("\n"):
            self.disconnect()
            raise ConnectionError("Connection lost while reading line")
        line = line.rstrip("\n")
        if line.startswith(ERROR_PREFIX):
            error = line[len(ERROR_PREFIX):].strip()
            raise CommandError(error)
        if self._command_list is not None:
            if line == NEXT:
                return
            if line == SUCCESS:
                raise ProtocolError("Got unexpected '%s'" % SUCCESS)
        elif line == SUCCESS:
            return
        return line

Then i do the following:

import mpd
handler = mpd.MPDClient(use_unicode=True)
handler.timeout = 10
handler.connect('localhost', 6600)

handler.deleteid('117')
('Line from client: ', 'OK\n')           # Print the info i inserted before.

Then after several minutes later, i do the following(before the following action i do nothing at all, just wait inside the ipython prompt):
(And i can confirm that ID as '119' is already existed in the current playlist)

handler.deleteid('119')
---------------------------------------------------------------------------
error                                     Traceback (most recent call last)
<ipython-input-9-8bb006d17d74> in <module>()
----> 1 handler.deleteid('119')

/Users/zhenweigui/.dev/lib/python2.7/site-packages/mpd.pyc in decorator(self, *args)
    582 def newFunction(wrapper, name, returnValue):
    583     def decorator(self, *args):
--> 584         return wrapper(self, name, args, bound_decorator(self, returnValue))
    585     return decorator
    586

/Users/zhenweigui/.dev/lib/python2.7/site-packages/mpd.pyc in _execute(self, command, args, retval)
    227             self._write_command(command, args)
    228             if isinstance(retval, Callable):
--> 229                 return retval()
    230             return retval
    231

/Users/zhenweigui/.dev/lib/python2.7/site-packages/mpd.pyc in decorator(*args, **kwargs)
    577
    578     def decorator(*args, **kwargs):
--> 579         return function(self, *args, **kwargs)
    580     return decorator
    581

/Users/zhenweigui/.dev/lib/python2.7/site-packages/mpd.pyc in _fetch_nothing(self)
    351
    352     def _fetch_nothing(self):
--> 353         line = self._read_line()
    354         if line is not None:
    355             raise ProtocolError("Got unexpected return value: '%s'" % line)

/Users/zhenweigui/.dev/lib/python2.7/site-packages/mpd.pyc in _read_line(self)
    253
    254     def _read_line(self):
--> 255         line = self._rfile.readline()
    256         print('Line from XPlayer: ', line)
    257         if self.use_unicode:

/usr/local/Cellar/python/2.7.8_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.pyc in readline(self, size)
    445             while True:
    446                 try:
--> 447                     data = self._sock.recv(self._rbufsize)
    448                 except error, e:
    449                     if e.args[0] == EINTR:

error: [Errno 54] Connection reset by peer

In [10]:

Any thing i did wrong? Please help. Thanks.

connection lost on OSX

OSX 10.9.x
MPD: 0.18.11 (installed by homebrew)
Python 2.7.x
python-mpd2 0.5.3

import mpd

handler = mpd.MPDClient(use_unicode=True)
handler.connect('localhost', 6600)

Then sometimes, not every time, there will be problem like below:

 Traceback (most recent call last):
  File "xplayer.py", line 2586, in dropOnRow
    existedPls = [i['playlist'] for i in handler.listplaylists()]
  File "/usr/local/lib/python2.7/site-packages/mpd.py", line 583, in decorator
    return wrapper(self, name, args, bound_decorator(self, returnValue))
  File "/usr/local/lib/python2.7/site-packages/mpd.py", line 229, in _execute
    return retval()
  File "/usr/local/lib/python2.7/site-packages/mpd.py", line 578, in decorator
    return function(self, *args, **kwargs)
  File "/usr/local/lib/python2.7/site-packages/mpd.py", line 398, in _fetch_playlists
    return self._fetch_objects(["playlist"])
  File "/usr/local/lib/python2.7/site-packages/mpd.py", line 383, in _fetch_objects
    return self._wrap_iterator(self._read_objects(delimiters))
  File "/usr/local/lib/python2.7/site-packages/mpd.py", line 347, in _wrap_iterator
    return list(iterator)
  File "/usr/local/lib/python2.7/site-packages/mpd.py", line 305, in _read_objects
    for key, value in self._read_pairs():
  File "/usr/local/lib/python2.7/site-packages/mpd.py", line 284, in _read_pairs
    pair = self._read_pair(separator)
  File "/usr/local/lib/python2.7/site-packages/mpd.py", line 275, in _read_pair
    line = self._read_line()
  File "/usr/local/lib/python2.7/site-packages/mpd.py", line 260, in _read_line
    raise ConnectionError("Connection lost while reading line")
mpd.ConnectionError: Connection lost while reading line

API Docs

Without some API docs it's basically impossible to infer how to use this library. A basic function listing with parameters and their meanings would be sufficient.

Persistent MPDClient

I'm writing a web-based front end to MPD. I instantiate and connect MPDClient when my program starts. At first calling commands works fine, but after some time of inactivity,

  File "/home/ztang/music/music.py", line 19, in queue
    client.add(path)
  File "/home/ztang/music/venv/lib/python3.3/site-packages/mpd.py", line 588, in decorator
    return wrapper(self, name, args, bound_decorator(self, returnValue))
  File "/home/ztang/music/venv/lib/python3.3/site-packages/mpd.py", line 229, in _execute
    return retval()
  File "/home/ztang/music/venv/lib/python3.3/site-packages/mpd.py", line 583, in decorator
    return function(self, *args, **kwargs)
  File "/home/ztang/music/venv/lib/python3.3/site-packages/mpd.py", line 352, in _fetch_nothing
    line = self._read_line()
  File "/home/ztang/music/venv/lib/python3.3/site-packages/mpd.py", line 260, in _read_line
    raise ConnectionError("Connection lost while reading line")
mpd.ConnectionError: Connection lost while reading line

A further attempt to connect:

  File "/home/ztang/music/music.py", line 32, in queuedir
    client.add(path)
  File "/home/ztang/music/venv/lib/python3.3/site-packages/mpd.py", line 588, in decorator
    return wrapper(self, name, args, bound_decorator(self, returnValue))
  File "/home/ztang/music/venv/lib/python3.3/site-packages/mpd.py", line 227, in _execute
    self._write_command(command, args)
  File "/home/ztang/music/venv/lib/python3.3/site-packages/mpd.py", line 252, in _write_command
    self._write_line(" ".join(parts))
  File "/home/ztang/music/venv/lib/python3.3/site-packages/mpd.py", line 233, in _write_line
    self._wfile.write("%s\n" % line)
  File "/home/ztang/music/venv/lib/python3.3/site-packages/mpd.py", line 75, in _dummy
    raise ConnectionError("Not connected")
mpd.ConnectionError: Not connected

Is there a way to avoid the ConnectionError? Will I have to catch the exception and reconnect, or connect and disconnect every time I issue a command?

CommandError MPDClient.seekcur

The MPDClient.seekcur function always raises the following:

mpc.seekcur(60)
Traceback (most recent call last):
  File "<pyshell#33>", line 1, in <module>
    mpc.seekcur(60)
  File "/usr/local/lib/python2.7/dist-packages/mpd.py", line 600, in decorator
    return wrapper(self, name, args, bound_decorator(self, returnValue))
  File "/usr/local/lib/python2.7/dist-packages/mpd.py", line 238, in _execute
    return retval()
  File "/usr/local/lib/python2.7/dist-packages/mpd.py", line 595, in decorator
    return function(self, *args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/mpd.py", line 363, in _fetch_nothing
    line = self._read_line()
  File "/usr/local/lib/python2.7/dist-packages/mpd.py", line 275, in _read_line
    raise CommandError(error)
CommandError: [5@0] {} unknown command "seekcur"

Grouping count command

The grouping version of count command behave unexpectedly IMHO:

>>> cli = mpd.MPDClient()
>>> cli.connect(host='/run/mpd/socket', port=42)
>>> cli.count('group', 'albumartist')
{'albumartist': ['art00', 'art01',โ€ฆ], 
 'playtime': ['123', '321', โ€ฆ],
 'songs': ['1', '2',โ€ฆ]}
>>> #  idem with:
>>> cli.count('genre', 'Rock', 'group', 'albumartist')

I would expect a list of object of that kind instead:

>>> cli.count('group', 'albumartist')
[ {'albumartist': 'art00', 'playtime': '123', 'songs': '1'},
  {'albumartist': 'art01', 'playtime': '321', 'songs': '2'},
โ€ฆ]

This object does not require extra processing to link grouping values with its playtime/songs stats.

I had a quick look at the raw MPD output, I think this might be tricky since the delimiter changes depending on the function signature. I don't have a straight forward solution to submit.

That's it
Thanks for your work

having problem with timeout when using select on the client fileno()

I code using the send_idle() function with a follow on select() that has been largely working well. I can then use a different thread to send a no_idle command.

                MPD2.send_idle()
                # do this in event loop
                canRead = select([MPD2], [], [])[0]
                logging.debug(str(canRead))
                if canRead:
                    logging.debug('retrieving idle event')
                    event = MPD2.fetch_idle()

The above works great. However, if there is a network glitch between the client and the mpd server, the select above never returns and I can never detect and reset the connection.

If I add a timeout on the select to recover from the glitch, the Python Select documentation say the returned list (canRead) should be empty.

canRead = select([MPD2], [], [], <timeout in seconds>)[0]

However, I always get MPD2 returning in the list. When the code tries to fetch_idle(), the connection is automatically closed and a "Connection lost while reading line" is thrown.

What am I missing? Unless the select() returns an empty list on timeout, there is no way to know there was a timeout and to avoid calling fetch_idle()

Insufficient Documentation for Status

It would be great if you could add an explanation of dict returned by MPDClient.status() because I really do not understand the difference between MPDClient.status()['time'] and MPDClient.status()['elapsed']. And is there no way to get the absolute length of a song in seconds?

Locking

Sending commands in python-mpd is not thread-safe. But this feature is often required in gui apps. Therefore locking is needed.

error in client.listplaylist()

i have typo in config - ''
playlist_directory "/home/atommixz/
/.mpd/playlists"

and have error when running client.listplaylists()
Traceback (most recent call last):
File "./test1.py", line 17, in
client.listplaylists()
File "/usr/local/lib/python3.4/dist-packages/mpd.py", line 583, in decorator
return wrapper(self, name, args, bound_decorator(self, returnValue))
File "/usr/local/lib/python3.4/dist-packages/mpd.py", line 229, in _execute
return retval()
File "/usr/local/lib/python3.4/dist-packages/mpd.py", line 578, in decorator
return function(self, _args, *_kwargs)
File "/usr/local/lib/python3.4/dist-packages/mpd.py", line 398, in _fetch_playlists
return self._fetch_objects(["playlist"])
File "/usr/local/lib/python3.4/dist-packages/mpd.py", line 383, in _fetch_objects
return self._wrap_iterator(self._read_objects(delimiters))
File "/usr/local/lib/python3.4/dist-packages/mpd.py", line 347, in _wrap_iterator
return list(iterator)
File "/usr/local/lib/python3.4/dist-packages/mpd.py", line 305, in _read_objects
for key, value in self._read_pairs():
File "/usr/local/lib/python3.4/dist-packages/mpd.py", line 284, in _read_pairs
pair = self._read_pair(separator)
File "/usr/local/lib/python3.4/dist-packages/mpd.py", line 275, in _read_pair
line = self._read_line()
File "/usr/local/lib/python3.4/dist-packages/mpd.py", line 264, in _read_line
raise CommandError(error)
mpd.CommandError: [52@0] {listplaylists} No such file or directory

While MPD updating it database, it is not stable to get other data?

Hi Mic92,

Sorry to bother you again.
I work on this problem couple of days already, still have no clue, please help me out.

I am using watchdog to watch the filesystem change of MPD music directory,
once there is/are change(s) happened inside music directory,
my program will ask MPD to update it's database by using your library.

My problem is:
I found when i upload a little more audio files(more than 10 files?) to the music directory of MPD, then my program will generate lots of error.
It seems that while MPD is updating it's database, at the same time if you ask for other information will not be handled. Sometime it is OK, you can get the data you want, but sometimes it will fail, especially for method: 'handler.status()', lot of 'KeyError' information reported.

Some of the error info below:

$ python xplayer.py
Final path to be update is: 2012-07-16
Database updated for: <2012-07-16>

Final path to be update is: 2012-07-16
Final path to be update is: 2012-07-16
Database updated for: <2012-07-16>

Final path to be update is: 2012-07-16
Final path to be update is: 2012-07-16
Final path to be update is: 2012-07-16

Exception in thread Thread-2:
Traceback (most recent call last):
File "c:\Python27\lib\threading.py", line 551, in __bootstrap_inner
self.run()
File "c:\Python27\lib\site-packages\watchdog\observers\api.py", line 249, in run
self.dispatch_events(self.event_queue, self.timeout)
File "c:\Python27\lib\site-packages\watchdog\observers\api.py", line 419, in dispatch_events
self._dispatch_event(event, watch)
File "c:\Python27\lib\site-packages\watchdog\observers\api.py", line 414, in _dispatch_event
handler.dispatch(event)
File "c:\Python27\lib\site-packages\watchdog\events.py", line 342, in dispatch
self.on_any_event(event)
File "xplayer.py", line 2691, in on_any_event
update_path(file_name)
File "xplayer.py", line 179, in update_path
status = handler.status()
File "c:\Python27\lib\site-packages\mpd.py", line 491, in decorator
return wrapper(self, name, args, bound_decorator(self, returnValue))
File "c:\Python27\lib\site-packages\mpd.py", line 213, in _execute
return retval()
File "c:\Python27\lib\site-packages\mpd.py", line 486, in decorator
return function(self, _args, *_kwargs)
File "c:\Python27\lib\site-packages\mpd.py", line 331, in _fetch_object
objs = list(self._read_objects())
File "c:\Python27\lib\site-packages\mpd.py", line 276, in _read_objects
for key, value in self._read_pairs():
File "c:\Python27\lib\site-packages\mpd.py", line 255, in _read_pairs
pair = self._read_pair(separator)
File "c:\Python27\lib\site-packages\mpd.py", line 246, in _read_pair
line = self._read_line()
File "c:\Python27\lib\site-packages\mpd.py", line 227, in _read_line
line = self._rfile.readline()
File "c:\Python27\lib\socket.py", line 447, in readline
data = self._sock.recv(self._rbufsize)
error: [Errno 10035] A non-blocking socket operation could not be completed immediately

Traceback (most recent call last):
File "xplayer.py", line 1725, in timerEvent
stat = status['state']
KeyError: 'state'
Traceback (most recent call last):
File "xplayer.py", line 1725, in timerEvent
stat = status['state']
KeyError: 'state'

The below code should give you a draft image of what i'm try to do.

import mpd

from watchdog.events import FileSystemEventHandler
from watchdog.observers import Observer

from PyQt4.QtGui import *
from PyQt4.QtCore import *

......

handler = mpd.MPDClient()
handler.connect(host, port, timeout=10)

......

def getMusicDir():
    '''
    Get the 'Music Directory' of MPD.
    '''
    # ...
    return music_directory


def update_path(file_name):
    parent_dir = os.path.dirname(file_name)

    music_directory = getMusicDir()
    index = len(music_directory) + 1
    path = parent_dir[index:]

    print 'Final path to be update is: %s' % path

    status = handler.status()
    if not status.has_key('updating_db'):
        handler.update(path)
        print 'Database updated for: <%s>' % path


class FSEventHandler(FileSystemEventHandler):
    '''
    Watching changes of the 'Music Directory' of MPD,
    get the changing filename(create, modify, delete...),
    then invoke 'update_path(file_name)' function to ask MPD update database.
    '''
    def on_any_event(self, event):
        if event.is_directory:
            return

        file_name = event.src_path
        update_path(file_name)


class FSW(object):
    def __init__(self, path='.'):
        super(FSW, self).__init__()
        self.path = path

        self.init()

    def init(self):
        self.event_handler = FSEventHandler()
        self.observer = Observer()
        self.observer.schedule(
            self.event_handler, path=self.path, recursive=True)
        self.observer.start()

        try:
            while 1:
                time.sleep(1)
        except KeyboardInterrupt:
            self.observer.stop()

        self.observer.join()


class MyGUIApp(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        music_directory = getMusicDir()
        self.monitor = FSW(music_directory)
        ......

    # Other code...


if __name__ == '__main__':
    app = QApplication(sys.argv)

    myapp = MyGUIApp()
    myapp.show()

    sys.exit(app.exec_())

Please update documentation

Debian package repository now served from http://deb.kaliko.me/
The signing key remains the same, a package is available to install it though.

Package is built for python2/python3 for Debian testing suite, no backport built, please request if needed.

/etc/apt/sources.list.d/python-mpd2.list :

deb http://deb.kaliko.me/debian/ testing main
deb-src http://deb.kaliko.me/debian/ testing main

CommandError: [50@0] {add} Not found

Sorry to bother you again, but, I seem to be doing something wrong again:

mpdclient.client.add(track)

File "/usr/lib/python2.7/site-packages/mpd.py", line 600, in decorator

return wrapper(self, name, args, bound_decorator(self, returnValue))

File "/usr/lib/python2.7/site-packages/mpd.py", line 238, in _execute

return retval()

File "/usr/lib/python2.7/site-packages/mpd.py", line 595, in decorator

return function(self, *args, **kwargs)

File "/usr/lib/python2.7/site-packages/mpd.py", line 363, in _fetch_nothing

line = self._read_line()

File "/usr/lib/python2.7/site-packages/mpd.py", line 275, in _read_line

raise CommandError(error)

CommandError: [50@0] {add} Not found

UnicodeDecodeError when work with MPD 0.19.x

I have lots of audio files in Chinese in my muisc_directory.

I use python-mpd to interact with MPD.
It works well with MPD 0.17.4, but after i upgrade to MPD 0.19.7, UnicodeDecodeError occurs.

With below code to show you how it happened:

handler = mpd.MPDClient(use_unicode=True)
handler.timeout = 10
handler.connect(host, port)

Below error triggered during execution: (While invoking: handler.playlistinfo() )

  File "C:/Users/gui/.code/xplayer/xplayer.py", line 532, in init_ui
    plsInfo = handler.playlistinfo()
  File "C:\Users\gui\.py2\lib\site-packages\mpd.py", line 600, in decorator
    return wrapper(self, name, args, bound_decorator(self, returnValue))
  File "C:\Users\gui\.py2\lib\site-packages\mpd.py", line 238, in _execute
    return retval()
  File "C:\Users\gui\.py2\lib\site-packages\mpd.py", line 595, in decorator
    return function(self, *args, **kwargs)
  File "C:\Users\gui\.py2\lib\site-packages\mpd.py", line 406, in _fetch_songs
    return self._fetch_objects(["file"])
  File "C:\Users\gui\.py2\lib\site-packages\mpd.py", line 394, in _fetch_objects
    return self._wrap_iterator(self._read_objects(delimiters))
  File "C:\Users\gui\.py2\lib\site-packages\mpd.py", line 358, in _wrap_iterator
    return list(iterator)
  File "C:\Users\gui\.py2\lib\site-packages\mpd.py", line 316, in _read_objects
    for key, value in self._read_pairs():
  File "C:\Users\gui\.py2\lib\site-packages\mpd.py", line 298, in _read_pairs
    pair = self._read_pair(separator)
  File "C:\Users\gui\.py2\lib\site-packages\mpd.py", line 286, in _read_pair
    line = self._read_line()
  File "C:\Users\gui\.py2\lib\site-packages\mpd.py", line 268, in _read_line
    line = decode_str(line)
  File "C:\Users\gui\.py2\lib\site-packages\mpd.py", line 32, in <lambda>
    decode_str = lambda s: s.decode("utf-8")
  File "C:\Users\gui\.py2\lib\encodings\utf_8.py", line 16, in decode
    return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xd0 in position 12: invalid continuation byte

Key error: 'time' or Key error 'elapsed' ?

Hi
probably not a bug but i'm using 0.5.5 and client status do no seem to report time or elapsed on a mpd 0.16 server?
Also client.status()['time'] or client.status()['elapsed'] return a KeyError: 'time' or KeyError: 'elapsed'

could you please clarify the usage or is it a limitation of the versions Im using atm.
a command line mpc status return the expected value: for ex 0:05/7:40 (1%)
mpc status
www.litteratureaudio.com -
[playing] #1/6 0:05/7:40 (1%)
volume: 45% repeat: on random: off single: off consume: off

See satus below:
status= {'songid': '2038', 'playlistlength': '6', 'playlist': '2496', 'repeat': '1', 'consume': '0', 'mixrampdb': '0.000000', 'random': '0', 'state': 'stop', 'xfade': '0', 'volume': '45', 'single': '0', 'mixrampdelay': 'nan', 'nextsong': '1', 'song': '0', 'nextsongid': '2039'}
Traceback (most recent call last):
File "radiotilt0.4.py", line 250, in
end = client.status()['time'].split(":")
KeyError: 'time'

regards
Mobilis

Lack of consistency over handling of server disconnections

Creating a client, and then having the server stop gives one exception the first time client.status is called, and then a different exception after that. Subsequent reconnects also fail.

 >>> import mpd
 >>> import os
 >>> c = mpd.MPDClient()
 >>> os.system("/etc/rc.d/mpd start")
 0
 >>> c.connect("localhost", 6600)
 >>> c.status()
 {'songid': '5', 'playlistlength': '16', 'playlist': '2', 'repeat': '1', 'consume': '0', 'mixrampdb': '0.000000', 'random': '0', 'state':
 'play', 'xfade': '0', 'volume': '44', 'single': '0', 'mixrampdelay': 'nan', 'nextsong': '6', 'time': '60:232', 'song': '5', 'elapsed':
 '60.140', 'bitrate': '320', 'nextsongid': '6', 'audio': '44100:24:2'}
 >>> os.system("/etc/rc.d/mpd stop")
 0
 >>> c.status()
 Traceback (most recent call last):
   File "<input>", line 1, in <module>
   ....
   File "/usr/lib/python2.7/site-packages/mpd.py", line 248, in _read_pair
     line = self._read_line()
   File "/usr/lib/python2.7/site-packages/mpd.py", line 233, in _read_line
     raise ConnectionError("Connection lost while reading line")
 ConnectionError: Connection lost while reading line
 >>> c.status()
 Traceback (most recent call last):
   File "<input>", line 1, in <module>
   .....
   File "/usr/lib/python2.7/socket.py", line 303, in flush
     self._sock.sendall(view[write_offset:write_offset+buffer_size])
 error: [Errno 32] Broken pipe
 >>> os.system("/etc/rc.d/mpd start")
 0
 >>> c.connect("localhost", 6600)
 Traceback (most recent call last):
   File "<input>", line 1, in <module>
   File "/usr/lib/python2.7/site-packages/mpd.py", line 420, in connect
     raise ConnectionError("Already connected")
 ConnectionError: Already connected

BrokenPipeError (?) when idle for a long time

Hi and thank you for this project!

When mpd is idle (after calling client.stop()) for a couple of hours, I cannot successfully call client.play() again. I am aware of ConnectionErrors that can occur so I catch them in my script. In this case, however, I get a BrokenPipeError (sometimes I don't get an error at all, but nevertheless mpd won't start to play reproducibly).

I wrote a test script (find it here: https://gist.github.com/speendo/0d9c1a028d045de3f7a6) to track the error down.

I ran this script on my raspberry pi with nohup python3 test_mpd.py &.

Here's a traceback of the Error (found in nohup.out):

Traceback (most recent call last):
  File "test_mpd.py", line 62, in <module>
    client.play()
  File "/usr/local/lib/python3.4/dist-packages/mpd.py", line 600, in decorator
    return wrapper(self, name, args, bound_decorator(self, returnValue))
  File "/usr/local/lib/python3.4/dist-packages/mpd.py", line 236, in _execute
    self._write_command(command, args)
  File "/usr/local/lib/python3.4/dist-packages/mpd.py", line 263, in _write_command
    self._write_line(" ".join(parts))
  File "/usr/local/lib/python3.4/dist-packages/mpd.py", line 243, in _write_line
    self._wfile.flush()
  File "/usr/lib/python3.4/socket.py", line 391, in write
    return self._sock.send(b)
BrokenPipeError: [Errno 32] Broken pipe

And here's the log:

2015-12-15 08:35:26,497 INFO: Log started
2015-12-15 08:35:26,500 INFO: Attempt to (re-)connect to mpd server
2015-12-15 08:35:26,503 INFO: Calling MPD connect('localhost', 6600, timeout=None)
2015-12-15 08:35:26,566 INFO: Finished attempt to (re-)connect to mpd server
2015-12-15 08:35:26,568 INFO: <bound method MPDClient.decorator of <mpd.MPDClient object at 0xb6a38590>>
2015-12-15 08:35:26,570 INFO: Add playlist entry
2015-12-15 08:35:26,573 DEBUG: Calling MPD clear()
2015-12-15 08:35:26,578 DEBUG: Calling MPD add('http://uwstream2.somafm.com:9016',)
2015-12-15 08:35:26,582 INFO: Start playing for the first time
2015-12-15 08:35:26,585 DEBUG: Calling MPD play()
2015-12-15 08:35:36,597 INFO: This obviously works. Switching off now for 4 hours.
2015-12-15 08:35:36,604 DEBUG: Calling MPD stop()
2015-12-15 12:35:36,725 INFO: Trying to switch on again now
2015-12-15 12:35:36,727 DEBUG: Calling MPD play()

Can you help me find the source of this problem (or even solve it)?

status(): I/O operation on closed file.

Hi, I think this issue is related to some of the others (#31, #64). After some time of working great, I consistently get this exception:

  File "example.py", line 90, in update
    self.status = self.client.status()
  File "mpd.py", line 629, in decorator
    return wrapper(self, name, args, bound_decorator(self, returnValue))
  File "mpd.py", line 252, in _execute
    self._write_command(command, args)
  File "mpd.py", line 279, in _write_command
    self._write_line(" ".join(parts))
  File "mpd.py", line 258, in _write_line
    self._wfile.write("%s\n" % line)
ValueError: I/O operation on closed file.

It is connected to a mopidy instance, which continues to function. I suspect the connection is broken, but I'm not sure if mpd2 should handle this, or I should proceed like the users in the referenced issues and reconnect myself.

Command responses are random

Commands cause random seemingly unrelated errors (eg. Expected key 'volume', got 'repeat' for Adding to playlist)

support bytes string in python3?

Hello,
Song information may be or not be encoded as UTF-8 string, and as I know, mpd does not convert them into UTF-8. So would it be better not forcing UTF-8 encoding in python3?
I did this for python3 in my own branch.

Better support for deleting a range of files in the current playlist

MPD supports the command
delete a:b
to delete all files from position a to b in the current playlist. To use this in python-mpd2, one must do something like


which is not very nice; I think the possibility to write

instead would be better. I didn't figure out how to implement this because I don't completely understand the way commands are created in python-mpd2, otherwise I'd supply a pull request. :-)

Declare compatibility with Python3 in PyPi

Hi,
I just noticed that your package does not appear in the "Python 3 Packages" section of PyPi. Since Py3k support is one of the outstanding features of this library (and also to promote porting programs to python 3) this should be changed.

As far as I can see it suffices to add the line

Programming Language :: Python :: 3

in setup.py.

MPDClient is Old Style Class

Is there a reason why the MPDClient class is old-style (eg. doesn't have a signature of class MPDClient(object):)?

How to load a stored playlist range?

I am having trouble interpreting the documentation for the stored playlist load function, to load a specific entry in a stored playlist using a range.

for example, to load entry #2 in a playlist, I have tried:
client.load('playlistname', '2:2')
client.load('playlistname', '2', '2')
client.load('playlistname', ('2', '2'))
client.load('playlistname', (2, 2))
client.load('playlistname', ['2', '2'])

I always get a: mpd.CommandError: [2@0] {load} wrong number of arguments for "load"

Can some one give me an example?

don't show duplicated tags as strings '[x, x]'

sometimes tags in mpd protocol can be duplicates of one another.
This esp. happens if one tagged his library using beets.

This is how raw protocol serves those tags:

currentsong
file: ogg/Brandi Carlile/2008 Creep Live/01-Creep.ogg
Last-Modified: 2015-04-30T02:18:24Z
Album: Creep Live
Title: Creep
Track: 1
Artist: Brandi Carlile
Date: 2008
AlbumArtist: Brandi Carlile
Genre: Rock
Track: 1
Time: 273
Pos: 13
Id: 181945
OK

in python-mpd2 the 2 "track" values will be represented as one string value:

>>> print(file['track'])
[1, 1]
>>> type(file['track'])
<class 'str'>

python-mpd2 could check for key:value on parsing and if multi-values for one key are identical simply merge them. Otherwise represent them as a list.

Alternatively represent all duplicate tags as lists, even if all values are identical. Personally I prefer the first option :)

priorid command seems not work (my mpd version 0.16.7)

In [10]: c.priorid(200, '24')

CommandError Traceback (most recent call last)
/home/honey/ in ()
----> 1 c.priorid(200, '24')

/usr/lib/python2.7/site-packages/python_mpd2-0.4.0-py2.7.egg/mpd.pyc in decorator(self, *args)
476 def newFunction(wrapper, name, returnValue):
477 def decorator(self, *args):
--> 478 return wrapper(self, name, args, bound_decorator(self, returnValue))
479 return decorator
480

/usr/lib/python2.7/site-packages/python_mpd2-0.4.0-py2.7.egg/mpd.pyc in _execute(self, command, args, retval)
202 self._write_command(command, args)
203 if isinstance(retval, Callable):
--> 204 return retval()
205 return retval
206

/usr/lib/python2.7/site-packages/python_mpd2-0.4.0-py2.7.egg/mpd.pyc in decorator(_args, *_kwargs)
471 """ bind decorator to self """
472 def decorator(_args, *_kwargs):
--> 473 return function(self, _args, *_kwargs)
474 return decorator
475

/usr/lib/python2.7/site-packages/python_mpd2-0.4.0-py2.7.egg/mpd.pyc in _fetch_nothing(self)
301
302 def _fetch_nothing(self):
--> 303 line = self._read_line()
304 if line is not None:
305 raise ProtocolError("Got unexpected return value: '%s'" % line)

/usr/lib/python2.7/site-packages/python_mpd2-0.4.0-py2.7.egg/mpd.pyc in _read_line(self)
222 if line.startswith(ERROR_PREFIX):
223 error = line[len(ERROR_PREFIX):].strip()
--> 224 raise CommandError(error)
225 if self._command_list is not None:
226 if line == NEXT:

CommandError: [5@0] {} unknown command "priorid"

currentsong() does not return song title

It appears that currentsong() does not return the song's title, just the file name (as well as other useful bits of information), or am I just using it wrong?

asyncio port

python-mpd could be ported to asyncio (tulip), which would make it easy to integrate in a multitude of main loops from web servers to guis.

i've started porting, and have the very basics running (tcp connection, not blocking on connection and issuing basic commands, integration in gtk3 using gbulb), but it's only a small part. (haven't touched unix sockets (should be trivial) or idle (should interact greatly); iterate mode would have to be standard in this mode, even if it's not exposed).

i'm not sure yet where this takes the code base. my changes so far are small, but i don't think it's feasible to have ifs everywhere around to keep the same code working both blockingly and via asyncio. it might be possible to provide a blocking mode from that code base (where every blocking call is a thinly wrapped nonblocking call), but unless the python2.7 backport makes progress, that'll be python3.3+ only anyway.

(porting to asyncio is just starting, so patterns for keeping both a classical and an asynchronous interfaces can be expected to show up. let's see where this goes.)

this is currently an "i spend an hour on it when i need a break" project for me, so if you want to see progress soon, you'll have to join in or wait for me to be bored with everything else again :-)

correct syntax for find?

I'm using mpd2 along with PiMusicBox to control Spotify on a Rpi. I'm struggling to get good search results back from Spotify via MPD. I do the following

for a specific track by a specific artist

result = client.find("artist", artist_to_find, "title", track_to_find)

or just for an artist:

result = client.find("artist", artist_to_find)

The artist/track search usually gets results but the artist only search often returns nothing - even if the search (artist_to_find) is something like "David Bowie".

Can anyone advise the best way to get Spotify results via MPD?

Thanks

Client that waits long time gets SocketError broken pipe Or ConnectionError exception

I am new to python and python-mpd2 so I may be using this package incorrectly, but I cannot determine the source of my problem. I have a python-mpd2-based client on one RaspberryPi and a standard mpd on another Pi.

My client connects to the remote mpd and then listens for IR remote commands. When the IR remote command is sent, the client formats the request and relays it to the mpd. So far I have volume up and down working nicely. The client never disconnects and supposedly keeps the connection to the mpd open all the while.

However, if I leave the client for a period of time (an hour or so), just listening for IR commands, when I finally send a command, the client fails with a broken pipe (socket.error?) or sometimes a "ConnectionError: Connection lost while reading line". The mpd is still running and playing, although another mpd client (mpc) elsewhere has been been manipulating it.

Is it normal to expect that the original socket connection would be dropped over time or usage by a different mpd client? I have read all the documents I can find, and have failed to find any reason for the problem. I am expecting to have to catch the error and re-connect, but I'd like to know the root cause.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.