Repository: ultrabug/py3status

Issue:
mpris blocks py3status on startup
Some of the last code changes on the mpris module and maybe some package updates on my arch linux has the effect that py3status won't start again after "[restart](http://i3wm.org/docs/userguide.html#_reloading_restarting_exiting)" i3.

If I disable the mpris module all is working great.

i3 bar config:
```
bar {
    output              DVI-D-0
    status_command      py3status --debug --dbus-notify --include ~/.config/i3status
    position            top
    mode                dock
    workspace_buttons   yes
    tray_output         DVI-D-0
    separator_symbol    "  "

    font pango: Noto Sans, FontAwesome Bold 12
    colors {
        separator               #333333
        background              #000000
        statusline              #ffffff
        focused_workspace       #ffffff #4a90d9
        active_workspace        #000000 #eeeeee
        inactive_workspace      #ffffff #000000
        urgent_workspace        #000000 #90d94a
    }
}
```

py3status config:
```
order = "mpris"
```

log:
```
Jan 29 14:57:27 /py3status[5209]: ========
Jan 29 14:57:27 /py3status[5209]: Starting py3status version 3.5rc0 python 3.6.0
Jan 29 14:57:27 /py3status[5209]: py3status started with config {'cache_timeout': 60, 'interval': 1, 'minimum_interval': 0.1, 'dbus_notify': True, 'include_paths': ['/home/mlu/.config/i3status'], 'version': '3.5rc0', 'debug': True, 'log_file': None, 'standalone': False, 'i3status_config_path': '/home/mlu/.config/i3status/config'}
Jan 29 14:57:27 /py3status[5209]: i3status thread mocked with config {'general': {'color_bad': '#FF0000', 'color_degraded': '#FFFF00', 'color_good': '#00FF00', 'color_separator': '#333333', 'colors': False, 'interval': 5, 'output_format': 'i3bar'}, 'order': ['mpris'], 'mpris': {}, 'on_click': {}, 'i3s_modules': [], 'py3_modules': ['mpris'], '.module_groups': {}}
Jan 29 14:57:27 /py3status[5209]: events thread started
Jan 29 14:57:27 /py3status[5209]: user_modules={}
Jan 29 14:57:27 /py3status[5209]: loading module "mpris" from py3status.modules.mpris
Jan 29 14:57:27 /py3status[5209]: module "mpris" click_events=new has_kill=new methods=odict_keys(['mpris'])
```


Discussion:
Confirmed. Python2and3 tested NOT OK.
```
lasers~/src/py3status/py3status/modules git:(master) python2 mpris.py 
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C
```
```
# New Terminal
lasers~/src/py3status/py3status/modules git:(master) python3 mpris.py 
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C
```
I can't `^C` at all... Had to kill my baby terminals.

>Some of the last code changes on the mpris module and...

Recent code changes on `mpris.py`... 
1d3653f02f1381c515e0f70ea1d97f8f8f55cc2e -- Thu Jan 26 13:57:20 -- Ultrabug
* Merge pull request #668 from ritze/mpris-startup-fix
* Detect players starting after py3status

`0000000` -- Wed Jan 18 06:29:02 -- simplify descriptions: vii (by lasers)
`0000000` -- Wed Jan 18 03:51:43 -- simplify descriptions: ii (by lasers)
`0000000` -- Tue Jan 17 15:30:44 -- simplify descriptions (by lasers)
2d78f558e62b5fd1311b14cc610d27c64b87e1ca -- Sun Jan 15 13:34:03 -- Use player_id only, when player really added (by ritze)
4bd0a556a61f5a615e691fefc5a18a0065de4367 -- Sun Jan 15 13:08:10 -- Detect players starting after py3status (by ritze)
`0000000` -- Thu Nov 17 15:48:16 -- flake8 fixes for tests (by tobes)

>... and maybe some package updates on my arch linux...

[aur/python2-pydbus](https://aur.archlinux.org/packages/python2-pydbus/) -- Last Updated: 	2017-01-24 20:29
[aur/python-pydbus](https://aur.archlinux.org/packages/python-pydbus/) -- Last Updated: 	2017-01-24 20:29

Hopefully, this little piece of information may be somehow useful in troubleshooting.

EDIT: You fix code... New pydbus package came in... Ultrabug merges...? Was that somewhat it? 
It maybe some strange issue.

I've just a strange issue I think related to python 2.7.13 it seemed to find an old version of py3status `pip` installed rather than my `python setup.py` one.  (I realise this is my bad but it is annoying when something like this changes)  So it may be partly your setup.

I get mpris running under python2 but it has some issues, I think the thread has a small error somewhere.

I think I'll take a look I think this is a great module when it's behaving.

If the thread dies we do not get informed.  I've a branch that adds 'safe' threads for modules.  Basically its a wrapper that will catch and report exceptions but I'll also get it to kill the threads better.  Threading is hard especially due to the lack of feedback on crashes, so having a helper like `py3.register_thread(function)` or similar would allow for that. and the thread could be started/stopped automatically.  It should also help with the ^C issue.

The modules hangs in `_add_player` always with the same player_id at this line:

```
player = self._dbus.get(player_id, SERVICE_BUS_URL)
```

If I check this bus with Qt QDbusViewer I get an error after 20 seconds:

> Error: Call to object / at :1.44: org.freedesktop.DBus.Error.NoReply (Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.) failed

Maybe we should add an timeout in the code to catch this sort of faults.
@ritze

>  always with the same player_id at this line:

what is the actual player_id that gives you the error?
@tobes 
> what is the actual player_id that gives you the error?

It's `:1.44`

I don't know which application this is or how I could determinate the corresponding application.
@tobes @ritze Having the same issue here on Ubuntu 16.04
mpris module was working fine yesterday, shutdown and come back the next day and now it's hanging and stopping py3status from starting. No packages or config have changed in that time.

Tried executing the python script as found in /usr/local/lib/python2.7/dist-packages/py3status/modules/mpris.py, and had to kill the terminal window just like @lasers, as ^C was having no effect.
Got some improvements wth this bug.
I removed all try/except blocks and got traceback:

> Traceback (most recent call last):
>   File "mpris.py", line 560, in <module>
>     module_test(Py3status)
>   File "/usr/local/lib/python3.5/dist-packages/py3status-3.5rc0-py3.5.egg/py3status/module_test.py", line 47, in module_test
>     module.post_config_hook()
>   File "mpris.py", line 165, in post_config_hook
>     self._start_listener()
>   File "mpris.py", line 437, in _start_listener
>     self._get_players()
>   File "mpris.py", line 423, in _get_players
>     if not self._add_player(player):
>   File "mpris.py", line 373, in _add_player
>     player = self._dbus.get(player_id, SERVICE_BUS_URL)
>   File "/usr/local/lib/python3.5/dist-packages/pydbus/proxy.py", line 59, in get
>     return CompositeInterface(introspection)(self, bus_name, object_path)
>   File "/usr/local/lib/python3.5/dist-packages/pydbus/proxy.py", line 118, in CompositeInterface
>     raise KeyError("object does not export any interfaces; you might need to pass object path as the 2nd argument for get()")
> KeyError: 'object does not export any interfaces; you might need to pass object path as the 2nd argument for get()'
Works perfect for me. Thanks @valdur55 for your fix.

Resolving patch:
diff --git a/py3status/modules/mpris.py b/py3status/modules/mpris.py
--- a/py3status/modules/mpris.py
+++ b/py3status/modules/mpris.py
@@ -95,7 +95,7 @@
     mpDris2 (mpris extension for mpd)
     vlc
 
-@author Moritz Lüdecke, tobes
+@author Moritz Lüdecke, tobes, valdur55
 """
 
 from datetime import timedelta
@@ -375,30 +375,27 @@ def _add_player(self, player_id):
         """
         Add player to mpris_players
         """
-        try:
-            player = self._dbus.get(player_id, SERVICE_BUS_URL)
-            if player_id.startswith(SERVICE_BUS):
-                if player.Identity not in self._mpris_names:
-                    self._mpris_names[player.Identity] = player_id.split('.')[-1]
-                    for p in self._mpris_players.values():
-                        if not p['name'] and p['identity'] in self._mpris_names:
-                            p['name'] = self._mpris_names[p['identity']]
-                            p['full_name'] = u'{} {}'.format(p['name'], p['index'])
-                return False
-            status = player.PlaybackStatus
-            state_priority = WORKING_STATES.index(status)
-            identity = player.Identity
-            if identity not in self._mpris_name_index:
-                self._mpris_name_index[identity] = 0
-            index = self._mpris_name_index[identity]
-            self._mpris_name_index[identity] += 1
-            name = self._mpris_names.get(identity)
-            subscription = player.PropertiesChanged.connect(
-                self._player_monitor(player_id)
-            )
-        except:
+        if not player_id.startswith(SERVICE_BUS):
             return False
 
+        player = self._dbus.get(player_id, SERVICE_BUS_URL)
+
+        self._mpris_names[player.Identity] = player_id.split('.')[-1]
+        for p in self._mpris_players.values():
+            if not p['name'] and p['identity'] in self._mpris_names:
+                p['name'] = self._mpris_names[p['identity']]
+                p['full_name'] = u'{} {}'.format(p['name'], p['index'])
+
+        status = player.PlaybackStatus
+        state_priority = WORKING_STATES.index(status)
+        identity = player.Identity
+        if identity not in self._mpris_name_index:
+            self._mpris_name_index[identity] = 0
+        index = self._mpris_name_index[identity]
+        self._mpris_name_index[identity] += 1
+        name = self._mpris_names.get(identity)
+        subscription = player.PropertiesChanged.connect(self._player_monitor(player_id))
+
         self._mpris_players[player_id] = {
             '_dbus_player': player,
             '_id': player_id,
@@ -426,9 +423,8 @@ def _remove_player(self, player_id):
     def _get_players(self):
         bus = self._dbus.get('org.freedesktop.DBus')
         for player in bus.ListNames():
-            if player.startswith(':') or player.startswith(SERVICE_BUS):
-                if not self._add_player(player):
-                    continue
+            self._add_player(player)
+
         self._set_player()
 
     def _start_listener(self):


Test patch: