01 Oktober 2016

Raspberry Pi Simple Audio Player



Raspberry Pi Simple Audio Player(RPISAP) adalah pemain audio yang sangat simple penggunaannya.  Pasangkan bekalan kuasa kepada Raspberry Pi, lagu atau fail audio akan terus dimainkan secara otomatik. Tekan suis untuk PAUSE atau pergi ke NEXT TRACK. Tekan suis SHUTDOWN untuk shutdown tanpa merosakkan fail operasi. Aktiviti dapat dilihat pada LED atau skrin. Pasangkan pemacu USB untuk tukar dan memainkan lagu lain. Ianya dilakukan secara otomatik.

Imej fail atau imej yang sudah ditulis kepada kad SD juga boleh dipos dengan kos yang berpatutan.
Sila emel kepada saya untuk keterangan lanjut di meorbu@gmail.com.


Raspberry Pi Simple Audio Player(RPISAP) telah diuji berfungsi pada Raspberry Pi 1A, Raspberry Pi 1B dan Raspberry Pi2.

Raspberry Pi Simple Audio Player(RPISAP) juga boleh dibina sendiri dengan cara yang diterangkan dibawah untuk kegunaan sendiri.

Berasaskan daripada Raspberry One Button Audio Book(RPOBAP) yang boleh dilihat dilaman web blogs.fsfe.org. RPOBAP mendapat sambutan untuk orang kurang upaya kerana penggunaannya yang sangat mudah yang tidak memerlukan tetapan yang khusus. Hanya tekan satu butang untuk play, pause dan reverse track. Kebanyakan yang memberi komen disitu menyatakan ia memudahkan untuk golongan orang kurang upaya atau orang-orang yang tidak mampu untuk melakukan pergerakan yang banyak. Jadi sama ada untuk mendengar lagu, rakaman suara atau lain-lain, pemain audio Raspberry Pi One Button Audio Player sangat membantu.
Konsep penggunaan RPOBAP sangat mudah. Pengguna perlu salin lagu ke pemacu USB yang dilabelkan dengan nama 1GB. Kemudian pemacu tersebut di pasang kepada RPOBAP dan fail lagu akan disalin ke RPOBAP secara automatik. Kemudian keluarkan pemacu tersebut dan tekan suis di RPOBAP untuk mainkannya. Tekan suis sekali dan lagu akan pause. Tekan kembali dan lagu akan disambung main semula. Tekan suis selama tiga saat dan lagu akan diulang semula.
Raspberry Pi Simple Audio Player(RPISAP) terhasil dari konsep itu namun ditambah sokongan dengan paparan display dan suis shutdown. Dengan mengekalkan konsep asal tambahan paparan adalah untuk memaparkan informasi fail lagu yang dimainkan tanpa perlu masuk kepaparan desktop. Bermakna kita hanya menggunakan paparan text console sahaja. Ini dapat menjimatkan penggunaan CPU dan memori disamping ruang simpanan data juga diluaskan. Penambahan suis shutdown pula adalah untuk memastikan sistem fail tidak rosak apabila RPISAP tidak dipadam(shutdown) dengan betul apabila kuasa yang dibekalkan kepadanya diputuskan dengan tiba-tiba ketika sedang beroperasi. Jadi penambahan suis shutdown adalah penting untuk memastikan kepanjangan hayat RPISAP.
Sememangnya banyak suis dan fungsi lain boleh ditambahkan kepada RPISAP tetapi oleh kerana untuk mengekalkan konsep asal supaya ianya murah dan mudah digunakan oleh sesiapa sahaja, mencukupilah dengan hanya menambahkan suis shutdown sahaja.
Untuk membina RPISAP kita perlu mengikut langkah-langkah yang saya terangkan ini.
Pertama sekali kita perlu memasang perisian Rasbian. Hanya Rasbian minimum, iaitu tanpa paparan desktop sudah mencukupi dan ianya boleh dipasangkan kepada kad memori 2 Gigabyte sahaja. Fail Rasbian minimum boleh dimuat turun dari sini. Cara pemasangan Rasbian minimum boleh dilihat di sini.
Kedua, perlu memasang satu led, dua suis dan beberapa perisian seperti yang dinyatakan dilaman Raspberry Pi One Button Audio Book namun perlukan beberapa langkah tambahan untuk menjadikannya Raspberry Pi Simple Audio Player. Oleh itu, skrip python RPISAP juga adalah berbeza dari RPOBAB dengan penambahan beberapa arahan baru.

Berikut adalah langkah-langkah yang perlu dilakukan untuk membina Raspberry Pi Simple Audio Player,

1. Pasangkan dua suis dan led seperti didalam gambar.

 Gambarajah litar skema pemasangan suis dan LED.
Gambarajah contoh penyambungan pada PCB. Suis kiri PAUSE dan suis kanan SHUTDOWN.

2. Pastikan sistem operasi Rasbian minimum telah dipasangkan dan berfungsi dengan baik.
3. Update raspbian terlebih dahulu.
   $ sudo apt-get update
4. Pasangkan perisian seperti berikut,
   $ sudo apt-get install mpd
   $ sudo apt-get install mpc
   $ sudo apt-get install python-mpd
   $ sudo apt-get install python-pyudev
   $ sudo apt-get install fbi

bina folder untuk menyimpan data lagu,
   $ sudo mkdir -p /music/usb
   $ sudo ln -s /var/lib/mpd /music/mpd
   $ sudo ln -s /var/lib/mpd/music /music/mp3

5. Untuk memastikan perisian telah dipasang dengan betul dan folder telah dibina, uji dengan mengikut langkah seperti berikut,

Namakan pemacu usb "RPISAP" dan salin satu file lagu mp3 kedalamnya (tanpa folder).
Pasangkan pemacu usb itu ke Raspberry Pi.
Di text console jalankan,
   $ sudo mount /dev/sda1 /music/usb
   $ sudo /etc/init.d/mpd stop
   $ sudo rm /music/mp3/*
   $ sudo cp /music/usb/* /music/mp3/
   $ sudo umount /music/usb

Keluarkan pemacu usb
   $ sudo rm /music/mpd/tag_cache
   $ sudo /etc/init.d/mpd start
   $ mpc clear
   $ mpc ls
   $ mpc ls | mpc add
   $ sudo /etc/init.d/mpd restart
   $ mpc play

Pasangkan headphone atau sambungkan ke amplifier. Pastikan bunyi lagu mp3 dapat dimainkan. Jika lagu tidak dimainkan, bermakna langkah-langkah diatas tidak berjaya. Cuba semak kembali langkah-langkah diatas dan pastikan ianya telah diikut dengan betul.
Tahniah jika anda telah dapat mendengar lagu mp3 dimainkan dan kita boleh terus dengan langkah-langkah seterusnya untuk membina RPISAP.

6. Bina skrip python seperti berikut atau emel saya untuk pos skrip yang telah siap dan simpan dengan nama rpisap.py di folder /home/pi. Kita akan menjalankan RPISAP melaluinya nanti.

#!/usr/bin/env python
#  Original Copyright (C) 2012 Michael Clemens for Raspberry Pi One Button Audio Book
#
#  Edited by meorBu 2016 modified for Raspberry Pi Simple Audio Player
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see .

import RPi.GPIO as GPIO
import os
import pyudev
import time
import subprocess
import sys

from mpd import (MPDClient, CommandError)
from socket import error as SocketError
from time import sleep

# Configure MPD connection settings
HOST = 'localhost'
PORT = '6600'
CON_ID = {'host':HOST, 'port':PORT}

# Configure IO ports
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.IN)
GPIO.setup(24, GPIO.OUT)

## Some functions
def mpdConnect(client, con_id):
        """
        Simple wrapper to connect MPD.
        """
        try:
                client.connect(**con_id)
        except SocketError:
                return False
        return True

def loadMusic(client, con_id, device):
        os.system("mount "+device+" /music/usb")
        os.system("/etc/init.d/mpd stop")
        os.system("rm /music/mp3/*")
        print("\n\033[32mCOPY FILES FROM USB DRIVE\033[0m\n")
        os.system("cp /music/usb/* /music/mp3/")
        os.system("umount /music/usb")
        os.system("rm /music/mpd/tag_cache")
        os.system("/etc/init.d/mpd start")
        os.system("mpc clear")
        sleep(2.0)
        os.system("mpc listall | mpc add")
        sleep(2.0)
        os.system("/etc/init.d/mpd restart")
        print("\n\n\033[32mFILE HAD BEEN COPIED TO RPISAP\n\033[0m")
        os.system("mpc playlist | cat -n")

def flashLED(speed, time):
        for x in range(0, time):
                GPIO.output(24, GPIO.LOW)
                sleep(speed)
                GPIO.output(24, GPIO.HIGH)
                sleep(speed)

def updateLED(client):
        # adjust LED to actual state
        if client.status()["state"] == "play":
                GPIO.output(24, GPIO.LOW)
                sys.stdout.write("\r   P L A Y   >            ")
                sys.stdout.flush()
        else:
                GPIO.output(24, GPIO.HIGH)
                sys.stdout.write("\r   P A U S E  | |         ")
                sys.stdout.flush()

def checkForUSBDevice(name):
        res = ""
        context = pyudev.Context()
        for device in context.list_devices(subsystem='block', DEVTYPE='partition'):
                if device.get('ID_FS_LABEL') == name:
                        res = device.device_node
        return res

def main():
        ## MPD object instance
        client = MPDClient()
        mpdConnect(client, CON_ID)

        os.system('mpc volume 95')      
        os.system('mpc -q repeat on')
        

        timebuttonisstillpressed = 0

        flashLED(0.5, 5)
        updateLED(client)

        client.play()

        lastsong = None

        while True:
                device = checkForUSBDevice("RPISAP") # RPISAP is the name of the thumb drive
                if device != "":
                        # USB thumb drive has been inserted, new music will be copied
                        flashLED(0.3, 2)
                        os.system('clear')
                        print " "
                        print ("\033[32mUSB DRIVE CONNECTED\033[0m")
                        print " "
                        client.disconnect()
                        loadMusic(client, CON_ID, device)
                        mpdConnect(client, CON_ID)
                        print ("\nRPISAP STATUS\n")
                        os.system("mpc stats")
                        flashLED(0.3, 3)
                        print " "
                        print ("\033[32mCOMPLETED, PLEASE REMOVE USB\033[0m")
                        print " "
                        # wait until thumb drive is unplugged again
                        while checkForUSBDevice("RPISAP") == device:
                                sleep(1.0)
                        os.system("sudo fbi -d /dev/fb0 --noverbose -a -once -t 3 /etc/splash.png")
                        flashLED(0.3, 4)
                        client.play()
                        updateLED(client)
                if GPIO.input(17) == True:
                        if timebuttonisstillpressed == 0:
                                # button has been pressed, pause or unpause now
                                if client.status()["state"] == "stop":
                                        client.play()
                                        updateLED(client)                                      
                                else:
                                        client.pause()
                                updateLED(client)
                        elif timebuttonisstillpressed > 2:
                                # go forward one track if button is pressed > 3 secs
                                client.next()
                                sys.stdout.write("\r   N E X T  T R A C K  > >")
                                sys.stdout.flush()
                                flashLED(0.3, 3)
                                timebuttonisstillpressed = 0
                                updateLED(client)
                        timebuttonisstillpressed = timebuttonisstillpressed + 0.1
                else:
                        timebuttonisstillpressed = 0
                        updateLED(client)
                currentsong = client.currentsong()
                if currentsong != lastsong:
                   os.system('setterm -blank 0')
                   os.system('setterm -cursor off')
                   os.system('clear')
                   print "\n\n\n  ----------------------------------------"
                   print "  * RASPBERRY  PI  SIMPLE  AUDIO  PLAYER *"
                   print "  ----------------------------------------"
                   print "\n  [[ CURRENT SONG ]]\n"
                   os.system('mpc current -f "[   Artist -  %artist%]\n[   Album  -  %album%]\n[   Track  -  %position%]\n[   Title  -  %title%]\n[   Time   -  %time% sec]"')
                   print "\n  [[ STATUS ]]\n"
                   lastsong = currentsong
                sleep(0.1)

# Script starts here
if __name__ == "__main__":
    main()

7. Cuba jalankan skrip python tadi,
   $ sudo python /home/pi/rpisap.py

Jika skrip python yang ditulis tadi sempurna, file lagu mp3 tadi akan dipaparkan di display dengan beberapa info. Ianya pasti terus dimainkan dan bunyinya dapat didengari. Jika tidak, semak semula skrip python yang ditulis tadi. Jika sudah berjaya, pasangkan pemacu usb dengan nama 'RPISAP' tadi,fail lagu mp3 dari dalam pemacu USB akan disalin secara otomatik ke folder /music/mp3 di RPISAP. Semasa proses ini berlaku lampu LED akan menyala mengikut proses yang dilakukan.
Semasa pemacu USB dipasang, lampu LED akan menyala berkelip dua kali. Selepas siap menyalin lampu LED akan menyala berkelip tiga kali. Kemudian selepas pemacu USB dicabut lampu LED akan menyala berkelip empat kali dan fail lagu mp3 akan terus dimainkan secara otomatik. Semua log proses yang berlaku ini dapat dilihat pada paparan skrin yang mana tidak untuk Raspberry Pi One Button Audiobook.

Contoh paparan semasa proses menyalin data dari USB yang dapat dilihat pada skrin.

8. Setiap kali fail lagu bertukar, log info akan dipaparkan di paparan display. Semua lagu akan dimainkan berterusan dan diulang semula. Tekan butang play untuk pause. Tekan kembali untuk sambung main semula. Tekan butang play berterusan selama lebih tiga saat untuk melompat satu fail kedepan.

Contoh paparan skrin semasa PLAY.

Contoh paparan skrin semasa PAUSE.

9. Semua proses itu adalah proses asas yang terdapat pada Raspberry Pi One Button Audiobook namun diolah dengan beberapa kod baru.

10. Untuk penambahan suis shutdown bina skrip seperti berikut atau emel saya untuk pos skrip yang telah siap dan simpan dengan nama shutdown.py di folder /home/pi. Ianya akan dijalankan secara senyap dibahagian belakang proses.

import RPi.GPIO as GPIO
import time
import os

GPIO.setmode(GPIO.BCM)
GPIO.setup(22, GPIO.IN)

while True:
        if(GPIO.input(22)):
                os.system("sudo shutdown -h  now")
                break
        time.sleep(0)


11. Untuk penambahan imej splash ataupun plymouth khas Raspberry Pi Simple Audio Player, boleh download imej diatas dan tulis kod bash seperti berikut.

#! /bin/sh
### BEGIN INIT INFO
# Provides:          asplashscreen
# Required-Start:
# Required-Stop:
# Should-Start:
# Default-Start:     S
# Default-Stop:
# Short-Description: Show custom splashscreen
# Description:       Show custom splashscreen
### END INIT INFO


do_start () {

    /usr/bin/fbi -T 1 -noverbose -a /etc/splash.png
    exit 0
}

case "$1" in
  start|"")
    do_start
    ;;
  restart|reload|force-reload)
    echo "Error: argument '$1' not supported" >&2
    exit 3
    ;;
  stop)
    # No-op
    ;;
  status)
    exit 0
    ;;
  *)
    echo "Usage: asplashscreen [start|stop]" >&2
    exit 3
    ;;
esac

:

Boleh memohon kod bash yang telah siap melalui emel saya.

Proses terakhir untuk melengkapkan Raspberry Pi Simple adalah seperti berikut.

1. Pertama sekali kita harus boot terus ke konsol text tanpa melalui proses log masuk. Edit fail seperti berikut,
  $ sudo nano /etc/systemd/system/getty.target.wants /getty@tty1.service
pergi kebahagian [Service] tambah pada arahan ExecStart,
  ExecStart=-/sbin/agetty --autologin pi --noclear %1 $TERM
tekan key Ctrl dan X kemudian key Y kemudiah Enter untuk simpan. Apabila reboot nanti, Raspberry Pi akan terus login ke konsol text menggunakan user pi tanpa perlu login skrin.

2. Untuk dapat melihat proses log di paparan skrin, skrip python mesti dijalankan secara otomatik selepas login. Edit fail profile,
   $ sudo nano /etc/profile
dibahagian bawah sekali tambahkan
   $ sudo python /home/pi/rpisap.py
skrip akan dijalankan secara otomatik selepas login.

3. Skrip shutdown mesti dijalankan secara background atau latar. Edit fail seperti berikut,
   $ sudo crontab -e
dibahagian bawah sekali tambahkan,
   @reboot python /home/pi/shutdown.py &
Apabila suis shutdown ditekan selepas reboot, Raspberry Pi Simple Audio Player akan shutdown dengan sempurna tanpa mengganggu sistem fail.

4. Untuk imej splash atau plymouth, salin imej splash ke folder home/pi/etc/. Kemudian salin kod bash dengan nama asplashscreen ke folder /etc/init.d/. Buatkan script itu boleh dilancarkan,
    $ sudo chmod a+x /etc/init.d/asplashscreen
    $ sudo insserv /etc/init.d/asplashscreen

Kini apabila reboot, splash screen akan dipaparkan, skrip rpisap.py akan berjalan dan Raspberry Pi Simple Audio Player telah lengkap dipasangkan. Lagu akan dimainkan secara otomatik. Salin fail mp3 ke pemacu USB kemudian pasangkan ke RPISAP dan fail mp3 akan disalin ke RPISAP. Keluarkan pemacu apabila selesai dan fail mp3 akan dimainkan secara otomatik.
Suis shutdown juga akan berfungsi apabila ditekan. RPISAP akan shutdown dengan selamat tanpa merosakkan fail-fail penting didalamnya.
Tahniah jika anda telah berjaya membina Raspberry Pi Simple Audio Player. Jika sebaliknya, semak semula sama ada langkah-langkah diatas telah diikuti dengan betul.

Setelah semua selesai, RPISAP boleh digunakan tanpa sambungan skrin, keyboard dan mouse. Proses PLAY, PAUSE, JUMP TRACK dan penyalinan fail dari pemacu USB boleh melihat kepada LED sahaja.

Selamat mencuba.