Moode Audio Player for Raspberry Pi

After a slight issue with a faulty PCB, I have finally been able to put together a PiFace shim and a KY040 rotary encoder without it looking like a mess of jumpers and hookup wire.

Here's the current version of the IQ_rot source:
https://cloud.pembo.it/index.php/s/g0oDM6AoUoxVJVK

It is not able to detect a double or long press, but that is my next intention.

Now, I just need to find a supplier who can ship one of those cheap amplifier boards without cracked solder or a broken audio cable as 'standard'....
 
Hi,

The next Moode update will include a bump to MPD 0.19.17 :)

-Tim
 

Attachments

  • moode-r26-mpd17.png
    moode-r26-mpd17.png
    274.5 KB · Views: 378
Hi Tim,

Thanks for the response. The USB stick does not show up in the /media folder and the stick is formatted with the ext3 filesystem.

Kind regards,
Frank

Hi Frank,

There is no filter for ext3 in udisks-glue config. Just add the sections below to /etc/udisks-glue.conf and u should be all set. I'll add this to next Moode update.

-Tim

filter ext3disks {
optical = false
partition_table = false
usage = filesystem
type = ext3
}

match ext3disks {
automount = true
automount_options = {sync,noexec,nodev,noatime,nodiratime}
}

 
Airplay behaving strangely

Dear diyAudio/Moode community,
yesterday I freshly installed moode 2.6 on a Raspberry Pi 2 with a HifiBerry Amp+.
I set this soundcard in preferences and activated Airplay and Airplay metadata. Nothing more nothing less.
Webradio plays flawlessly.
But when I try to airplay something from my iPhone (6 Plus, iOS 9.3.4), the speakers stay silent... Until I turn up the volume on the iPhone to the absolute maximum. Suddenly the sound is boosting out of the speakers - totally careless of which volume I set in the moode web interface. Really strange.
Streaming via DLNA/UPNP renderer (Android 6, Bubble UPNP app) works totally as expected and I can even adjust the volume via volume switch on the smartphone.
What can I do about the strange airplay behaviour?
Many thanks and best regards
Muhackl
 
Hi Frank,

There is no filter for ext3 in udisks-glue config. Just add the sections below to /etc/udisks-glue.conf and u should be all set. I'll add this to next Moode update.

-Tim

filter ext3disks {
optical = false
partition_table = false
usage = filesystem
type = ext3
}

match ext3disks {
automount = true
automount_options = {sync,noexec,nodev,noatime,nodiratime}
}


Thanks Tim, that did the trick!
 
Dear diyAudio/Moode community,
yesterday I freshly installed moode 2.6 on a Raspberry Pi 2 with a HifiBerry Amp+.
I set this soundcard in preferences and activated Airplay and Airplay metadata. Nothing more nothing less.
Webradio plays flawlessly.
But when I try to airplay something from my iPhone (6 Plus, iOS 9.3.4), the speakers stay silent... Until I turn up the volume on the iPhone to the absolute maximum. Suddenly the sound is boosting out of the speakers - totally careless of which volume I set in the moode web interface. Really strange.
Streaming via DLNA/UPNP renderer (Android 6, Bubble UPNP app) works totally as expected and I can even adjust the volume via volume switch on the smartphone.
What can I do about the strange airplay behaviour?
Many thanks and best regards
Muhackl

Hi,

Airplay volume is always set by the sender (iPhone/iTunes, etc). Moode volume gets overridden.

-Tim
 
Hi,

Thanks for the nice compliment, truly appreciated :)

#2 and 3 - what client are u using where the UI elements are too small?

#1 - file type could be displayed but extracting the encoded-at rate from each file in the Playlist as its displayed really bogs down the UI...

Regard
Tim
Thanks for your response Tim

Safari on an iPad air.
The library view could just do with the option of having one font size higher as an option and in the playback tab the previous track, Play Pause and Next Track icons could be just a little larger. I guess these are 100% personal preference things but if at all possible (and easy!) to provide an option for slightly larger playback control.
Thanks for the feedback on the encoding information, performance is always the best option!
 
mpd status when using airplay

I' using the following python script to detect is moOde is playing, and if not turn off my amplifier after some time.

Code:
# Import the libraries to use time delays, send os commands and access GPIO pins
import RPi.GPIO as GPIO 
import time 
import os 
import mpd 

# Setup Variables
RedLedPin = 13 # Set pin number for "Standby" LED
GreenLedPin = 15 # Set pin number for "ON" LED
MainRelayPin = 11 # Set pin number for relay output
counter = 0 # counter for determining the time that has passed since MoOde player has stopped
SleepTime = 60 # The delay between each Status check, set to 60 = 1 minute to save CPU 
StandbyTime = 4 # The amount of time before "Standby" defined in multiples of SleepTime: StandbyTime*SleepTime (60*4 = 240sec = 4 minutes)

# Setup GPIO pins
GPIO.setmode(GPIO.BOARD) # Set pin numbering to board numbering 
GPIO.setup(MainRelayPin, GPIO.OUT) # Setup pin MainRelayPin as an output 
GPIO.setup(RedLedPin, GPIO.OUT) # Setup pin RedLedPin as an output 
GPIO.setup(GreenLedPin, GPIO.OUT) # Setup pin GreenLedPin as an output 

# Amplifier state control procedure
def AmpControl_ON(state):
    if state == True:
        GPIO.output(MainRelayPin, GPIO.HIGH)
        GPIO.output(RedLedPin, GPIO.LOW)
        GPIO.output(GreenLedPin, GPIO.HIGH)
    else:
        GPIO.output(MainRelayPin, GPIO.LOW)
        GPIO.output(RedLedPin, GPIO.HIGH)
        GPIO.output(GreenLedPin, GPIO.LOW)

# Setup MDPClient and connect to MPD on localhost
Client = mpd.MPDClient() # create client object 
Client.timeout = None
Client.idletimeout = None

while True:
    try:
        Client.connect("localhost", 6600) # connect to localhost:6600 
    except:
        continue
    break


# Set GPIO pins to their initial ON state
AmpControl_ON(True)

# main loop
while True:

    amp_on = GPIO.input(MainRelayPin)# Get status from Relay GPIO pin

        if Client.status()['state'] == "play":
            if not amp_on:
                    # Set GPIO pins to initial ON state
            #print "MPD state = play! Entering ON state"
            AmpControl_ON(True)
               #print ("Amp is on = {0}".format(GPIO.input(MainRelayPin))) 

        else: # Either stopped or paused
            if amp_on:
            counter = 0 
            while counter < StandbyTime:
                time.sleep(SleepTime)
                counter = counter + 1
                #print ("Checking MPD status! {0} seconds have passed since last MPD was last playing.".format((counter)*SleepTime))
                if Client.status()['state'] == "play":
                    break
                
            if Client.status()['state'] != "play": # Still stopped/paused after StandbyTime*SleepTime
                #print ("MPD has not been playing for {0} seconds! Entering standby!".format((counter)*SleepTime))
                        # Set GPIO pins to standby state
                AmpControl_ON(False)
                #print ("Amp is on = {0}".format(GPIO.input(MainRelayPin)))

         #print "Waiting for change in MPD state......."
    Client.idle('player')
    #print "Change in MPD-player subsystem detected! continuing"

# Close connection to MPD (not used since the main loop never exits)
#Client.close() # send the close command
#Client.disconnect() # disconnect from the server
The script works great when playing things from the playlist, but as soon as I stream anything via AirPlay, the Client.status()['state'] is not "play" but "stop" eventhough something is obviously playing via Airplay.

Is this correct?
If yes, is there any way I can detect if something is streaming via Airplay with python?

regards
Max
 

Attachments

  • ampcontroller2.zip
    1.3 KB · Views: 39
I' using the following python script to detect is moOde is playing, and if not turn off my amplifier after some time.

Code:
# Import the libraries to use time delays, send os commands and access GPIO pins
import RPi.GPIO as GPIO 
import time 
import os 
import mpd 

# Setup Variables
RedLedPin = 13 # Set pin number for "Standby" LED
GreenLedPin = 15 # Set pin number for "ON" LED
MainRelayPin = 11 # Set pin number for relay output
counter = 0 # counter for determining the time that has passed since MoOde player has stopped
SleepTime = 60 # The delay between each Status check, set to 60 = 1 minute to save CPU 
StandbyTime = 4 # The amount of time before "Standby" defined in multiples of SleepTime: StandbyTime*SleepTime (60*4 = 240sec = 4 minutes)

# Setup GPIO pins
GPIO.setmode(GPIO.BOARD) # Set pin numbering to board numbering 
GPIO.setup(MainRelayPin, GPIO.OUT) # Setup pin MainRelayPin as an output 
GPIO.setup(RedLedPin, GPIO.OUT) # Setup pin RedLedPin as an output 
GPIO.setup(GreenLedPin, GPIO.OUT) # Setup pin GreenLedPin as an output 

# Amplifier state control procedure
def AmpControl_ON(state):
    if state == True:
        GPIO.output(MainRelayPin, GPIO.HIGH)
        GPIO.output(RedLedPin, GPIO.LOW)
        GPIO.output(GreenLedPin, GPIO.HIGH)
    else:
        GPIO.output(MainRelayPin, GPIO.LOW)
        GPIO.output(RedLedPin, GPIO.HIGH)
        GPIO.output(GreenLedPin, GPIO.LOW)

# Setup MDPClient and connect to MPD on localhost
Client = mpd.MPDClient() # create client object 
Client.timeout = None
Client.idletimeout = None

while True:
    try:
        Client.connect("localhost", 6600) # connect to localhost:6600 
    except:
        continue
    break


# Set GPIO pins to their initial ON state
AmpControl_ON(True)

# main loop
while True:

    amp_on = GPIO.input(MainRelayPin)# Get status from Relay GPIO pin

        if Client.status()['state'] == "play":
            if not amp_on:
                    # Set GPIO pins to initial ON state
            #print "MPD state = play! Entering ON state"
            AmpControl_ON(True)
               #print ("Amp is on = {0}".format(GPIO.input(MainRelayPin))) 

        else: # Either stopped or paused
            if amp_on:
            counter = 0 
            while counter < StandbyTime:
                time.sleep(SleepTime)
                counter = counter + 1
                #print ("Checking MPD status! {0} seconds have passed since last MPD was last playing.".format((counter)*SleepTime))
                if Client.status()['state'] == "play":
                    break
                
            if Client.status()['state'] != "play": # Still stopped/paused after StandbyTime*SleepTime
                #print ("MPD has not been playing for {0} seconds! Entering standby!".format((counter)*SleepTime))
                        # Set GPIO pins to standby state
                AmpControl_ON(False)
                #print ("Amp is on = {0}".format(GPIO.input(MainRelayPin)))

         #print "Waiting for change in MPD state......."
    Client.idle('player')
    #print "Change in MPD-player subsystem detected! continuing"

# Close connection to MPD (not used since the main loop never exits)
#Client.close() # send the close command
#Client.disconnect() # disconnect from the server
The script works great when playing things from the playlist, but as soon as I stream anything via AirPlay, the Client.status()['state'] is not "play" but "stop" eventhough something is obviously playing via Airplay.

Is this correct?
If yes, is there any way I can detect if something is streaming via Airplay with python?

regards
Max

Hi Max,

Yes, just run the sql query below from cmd line and check the returned value. If its "1" then Airplay stream is active. If its "0" then no Airplay stream.

sqlite3 /var/www/db/player.db "select value from cfg_engine where param='airplayactv'"

Regards,
Tim
 
Hi Max,

Yes, just run the sql query below from cmd line and check the returned value. If its "1" then Airplay stream is active. If its "0" then no Airplay stream.

sqlite3 /var/www/db/player.db "select value from cfg_engine where param='airplayactv'"

Regards,
Tim

Cool :D. Many Thanks Tim. Now I just need to stuff it into the python code. I'll post when I have it working.

Regards
Max
 
Hi Max,

Yes, just run the sql query below from cmd line and check the returned value. If its "1" then Airplay stream is active. If its "0" then no Airplay stream.

sqlite3 /var/www/db/player.db "select value from cfg_engine where param='airplayactv'"

Regards,
Tim

Hi Tim

That didn't quite work as expected:confused:. The code hangs in the idle statement, which it is supposed to. I can read the state of Airplay using the above statement, but the idle statement hangs untill a change in the player subsystem occurs, and this does not happen with Airplay.

Do I need to rewrite the loop code, so it doesn't use client.idle or is there a smart way of getting Airplay to triger an event in the player subsystem of MPD or any subsystem at all?

Regards Max
 
Hi Tim

That didn't quite work as expected:confused:. The code hangs in the idle statement, which it is supposed to. I can read the state of Airplay using the above statement, but the idle statement hangs untill a change in the player subsystem occurs, and this does not happen with Airplay.

Do I need to rewrite the loop code, so it doesn't use client.idle or is there a smart way of getting Airplay to triger an event in the player subsystem of MPD or any subsystem at all?

Regards Max

Hi Max,

MPD and Airplay receiver are separate apps and don't communicate directly with one another. There is /var/www/command/spspre.sh and spspost.sh scripts that are called by shairport-sync just before it starts a stream and just after a stream ends (plus a 10 sec timeout).

-Tim
 
File cover art bug/problem or a feature?

It seems to me that the player takes cover art from the first file if there is no cover art in some other file. Why is that? Quite confusing.

Coverart fetch sequence is supposed to be:

1) Check currently playing file for embedded art
2) Check for image file in the folder containing the song file

-Tim
 
Coverart fetch sequence is supposed to be:

1) Check currently playing file for embedded art
2) Check for image file in the folder containing the song file

-Tim

1. it works
2. don't have image file in the folder
3. takes embedded art from the first audio file. If I remove that file, it takes from the next 'first' file.

Example:

a) First artist is A with embedded art, everything is fine and shows that cover art, next artist in the folder is B without embedded art and it still shows file A embedded cover art.

b) If I delete that file A, now is the first file B with embedded cover art and when player switches to the file C without cover art, it still shows file B cover art. Next file could be D or J or X or Y it still shows cover art from the file B. But if this D, J, X, Y or some file has embedded cover art then it shows it.

I think it would be nice to show Moode Player logo if there is no embedded art or image file in the folder. What do you think? Can it be done?
 
Hi Max,

MPD and Airplay receiver are separate apps and don't communicate directly with one another. There is /var/www/command/spspre.sh and spspost.sh scripts that are called by shairport-sync just before it starts a stream and just after a stream ends (plus a 10 sec timeout).

-Tim

Damm it!:D but it makes sense that AirPlay and MPD are separate. Initially, I thought the client.idle statement was a really good idea, Guess it’s back to notepad++:eek: and a timed loop.
 
1. it works
2. don't have image file in the folder
3. takes embedded art from the first audio file. If I remove that file, it takes from the next 'first' file.

Example:

a) First artist is A with embedded art, everything is fine and shows that cover art, next artist in the folder is B without embedded art and it still shows file A embedded cover art.

b) If I delete that file A, now is the first file B with embedded cover art and when player switches to the file C without cover art, it still shows file B cover art. Next file could be D or J or X or Y it still shows cover art from the file B. But if this D, J, X, Y or some file has embedded cover art then it shows it.

I think it would be nice to show Moode Player logo if there is no embedded art or image file in the folder. What do you think? Can it be done?

Hi,

I'm able to repro this and its due to coverart module fallback routine looking for any image in the containing folder, file or embedded if the currently playing song has no embedded image and there are no image files matching the list below.

Folder.jpg,folder.jpg
Folder.png,folder.png
Cover.jpg,cover.jpg
Cover.png,cover.png

I can probably change the logic so the fallback routine only looks for image files and does not also check for embedded images but I have to think a bit about whether this would create a situation when one problem is solved but another is created.

I'll add to the TODO list.

Regards,
Tim