Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem with constant connection failures. #90

Open
chross opened this issue Feb 2, 2018 · 1 comment
Open

Problem with constant connection failures. #90

chross opened this issue Feb 2, 2018 · 1 comment

Comments

@chross
Copy link

chross commented Feb 2, 2018

I'm fairly new to python and want to code an app that will control mpd via keyboard (and later GPIO) input on a Raspberry Pi 3.
I got the code running so far, my playlists have numbers for names (i.e. 8.m3u, 4.m3u, etc..) and now I want to replace the whole playlist of mpd with the new selected one. For example playlist 8 is playing, when entering 4 into the console and hitting enter, mpd should stop, clear, load playlist 4, and play. This works on the first time when starting up the script, but then fails every time (socket timeout.

I also tried the PersistentMPDClient.py script but that did not work either. How do I debug mpd or in general find the issue?

# -*- coding: utf-8 -*-
from __future__ import print_function
import threading
import time
import sys
import RPi.GPIO as GPIO
import socket
import mpd

GPIO.setmode(GPIO.BOARD)			#GPIO pin numbering mode
GPIO.setwarnings(False)

class PersistentMPDClient(mpd.MPDClient):
    def __init__(self, socket=None, host=None, port=None):
        super(PersistentMPDClient, self).__init__()
        self.socket = socket
        self.host   = host
        self.port   = port

        self.do_connect()
        # get list of available commands from client
        self.command_list = self.commands()

        # commands not to intercept
        self.command_blacklist = ['ping']

        # wrap all valid MPDClient functions
        # in a ping-connection-retry wrapper
        for cmd in self.command_list:
            if cmd not in self.command_blacklist:
                if hasattr(super(PersistentMPDClient, self), cmd):
                    super_fun = super(PersistentMPDClient, self).__getattribute__(cmd)
                    new_fun = self.try_cmd(super_fun)
                    print("Setting interceptor for {}".format(cmd))
                    setattr(self, cmd, new_fun)
                else:
                    print("Attr {} not available!".format(cmd))

    # create a wrapper for a function (such as an MPDClient
    # member function) that will verify a connection (and
    # reconnect if necessary) before executing that function.
    # functions wrapped in this way should always succeed
    # (if the server is up)
    # we ping first because we don't want to retry the same
    # function if there's a failure, we want to use the noop
    # to check connectivity
    def try_cmd(self, cmd_fun):
        def fun(*pargs, **kwargs):
            try:
#                print("Attemping to ping...")
                self.ping()
            except (mpd.ConnectionError, OSError) as e:
#                print("lost connection.")
#                print("trying to reconnect.")
                self.do_connect()
            return cmd_fun(*pargs, **kwargs)
        return fun

    # needs a name that does not collide with parent connect() function
    def do_connect(self):
        try:
            try:
#                print("Attempting to disconnect.")
                self.disconnect()
            # if it's a TCP connection, we'll get a socket error
            # if we try to disconnect when the connection is lost
            except mpd.ConnectionError as e:
#                print("Disconnect failed, so what?")
                pass
            # if it's a socket connection, we'll get a BrokenPipeError
            # if we try to disconnect when the connection is lost
            # but we have to retry the disconnect, because we'll get
            # an "Already connected" error if we don't.
            # the second one should succeed.
            except BrokenPipeError as e:
#                print("Pipe closed, retrying disconnect.")
                try:
#                    print("Retrying disconnect.")
                    self.disconnect()
                except Exception as e:
                    print("Second disconnect failed, yikes.")
                    print(e)
                    pass
            if self.socket:
#                print("Connecting to {}".format(self.socket))
                self.connect(self.socket, None)
            else:
#                print("Connecting to {}:{}".format(self.host, self.port))
                self.connect(self.host, self.port)
        except socket.error as e:
            print("Connection refused.")
#            print(e)

mpc = PersistentMPDClient(None,"localhost", 6600)

print("Python version: ",sys.version)

while True:
	try:
		inp = raw_input('Enter Number: ')
		if int(inp):
			print("Playlist number: ",inp)
			mpc.command_list_ok_begin()
			mpc.stop()
			mpc.clear()
			mpc.load(inp)
			mpc.play()
			results = mpc.command_list_end()
		else:
			if inp == "vol+":
				print("Volume up")
				currvol = mpc.status("volume")
				if currvol < 100: mpc.setvol(currvol+10)
			if inp == "vol-":
				print("Volume down")			
				currvol = mpc.status("volume")
				if currvol > 0: mpc.setvol(currvol-10)
	except ValueError:
		if not inp:
			raise ValueError('empty string')
@DivineDominion
Copy link
Contributor

So when you say "socket timeout", do you get a socket.error or a mpd.ConnectionError?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants