PiFaceCAD를 이용해 음악 플레이어를 만들어보자
기능 ( 버튼과 리모콘을 이용해 구현)
- 현재 시간 표시
- Next, Play or Stop, Prev 곡 선택
- 현재 곡 제목 표시 (화면을 넘어갈 시 왼쪽으로 흐르게 한다.)
- 볼륨 조절, 음소거 가능
준비물
- Raspberry PI
- PiFace CAD
- IR 리모콘 또는 IR센서가 내장된 스마트폰(IR 리모콘 어플을 받을 것)
- 스피커 혹은 이어폰
1. PiFace CAD 를 사용하기 위한 SW 설치
2. IR Remote 설정하기
3. Configuring LIRC
위와 같이 설정 가능한 command들의 list가 나오게 된다.
위의 코드를 실행해 자신만의 configuration 을 만들자
실행하면 아래와 같은 창이 나오게 된다. 잘 따라 가보자
그리고 재부팅을 하고나서 잘 등록이 되었는지 확인해보자.
위의 명령어를 실행하고 리모콘의 버튼을 눌러 제대로 입력을 받는지 확인한다. 입력이 제대로 되면 다음과 같이 자신이 등록한 키가 버튼을 누를 때마다 나오게된다.
버튼과 그 버튼의 이름이 잘 나오는 것을 확인할 수 있다.
이제 각 버튼에 대한 configuration을 하자.
~/.lircrc 내용을 위와 같이 수정한다. 내가 아까 입력한 button의 이름을 button에 넣고 config에는 해당 button에 대한 반환값을 자신 임의대로 넣어주자.
위 코드를 실행하면 해당 버튼을 눌렀을 때에 설정한 값이 잘 나오는지 확인할 수 있다.
나는 리모콘의 버튼과 config를 아래와 같이 설정하였다.
리모콘 버튼 설정
Configuration
4. 음악 플레이어 준비하기
5. 본격적으로 음악 플레이어 만들기
from pygame import mixer # Load the required library
import pifacecad
import time
import datetime
import threading
pin = -1 # PiFaceCAD button
remote = -1 # IR remote control button
volume = 50 # current volume
play = True # current playing status (playing : True, pause: False)
mute = False # current mute status
curSong = 0 # current song number
stridx = 0 # current printed song string index
song = ['We Don\'t Talk Anymore.mp3','Closer.mp3','Shape Of You.mp3','Starving.mp3','The Ocean.mp3'\
,'Happy.mp3','Daft Punk.mp3', 'Chandelier.mp3','The Greatest.mp3', 'Lean On.mp3']
# init LCD
cad = pifacecad.PiFaceCAD()
cad.lcd.backlight_on()
cad.lcd.blink_off()
cad.lcd.cursor_off()
# bitmap
bmp_note = pifacecad.LCDBitmap([2,3,2,2,14,30,12,0])
bmp_play = pifacecad.LCDBitmap([0,8,12,14,12,8,0,0])
bmp_pause = pifacecad.LCDBitmap([0,27,27,27,27,27,0,0])
bmp_clock = pifacecad.LCDBitmap([0,14,21,23,17,14,0,0])
bmp_vol1 = pifacecad.LCDBitmap([1,3,15,15,15,3,1,0])
bmp_vol2 = pifacecad.LCDBitmap([8,16,0,24,0,16,8,0])
cad.lcd.store_custom_bitmap(0, bmp_note)
cad.lcd.store_custom_bitmap(1, bmp_play)
cad.lcd.store_custom_bitmap(2, bmp_pause)
cad.lcd.store_custom_bitmap(3, bmp_clock)
cad.lcd.store_custom_bitmap(4, bmp_vol1)
cad.lcd.store_custom_bitmap(5, bmp_vol2)
코드의 첫 부분에는 라이브러리의 import와 사용할 전역변수 선언, 노래 리스트 저장, LCD 초기화, LCD에 출력할 bitmap을 저장하였다.
def showTime(): # print current hour and minute
now = datetime.datetime.now()
nowTime = now.strftime('%H:%M')
cad.lcd.set_cursor(10,1)
cad.lcd.write_custom_bitmap(3)
cad.lcd.write(nowTime)
cad.lcd.set_cursor(0,0)
showTime()은 현재 시간과 분을 LCD 오른쪽 아래에 출력 하는 함수이다. 주기적으로 출력하여 시간을 바꾸어 출력해준다.
def updateVolume(): # print current volume without bitmap
global volume
cad.lcd.set_cursor(2,1)
if mute:
cad.lcd.write('mute')
else:
cad.lcd.write(str(volume).rjust(4))
cad.lcd.set_cursor(0,0)
def writeVolume(): # print current volume
global volume
global mute
cad.lcd.set_cursor(0,1)
cad.lcd.write_custom_bitmap(4)
cad.lcd.write_custom_bitmap(5)
updateVolume()
updateVolume() 은 현재 볼륨 상태(0~100)를 LCD왼쪽 아래에 출력한다. 음소거 중 일 경우에는 'mute' 문자열을 출력한다.
writeVolume()은 스피커 모양 비트맵을 함께 출력한다.
def writeBottomLine(): #print LCD bottom line
global play
showTime()
writeVolume()
cad.lcd.set_cursor(7,1)
if play:
cad.lcd.write_custom_bitmap(1)
else:
cad.lcd.write_custom_bitmap(2)
cad.lcd.set_cursor(0,0)
writeBottomLine()은 말그대로 LCD의 아랫줄을 출력하는 함수이다. showTime() 함수와 writeVolume() 함수를 통해 시간과 볼륨을 출력하고, 현재 재생상태를 읽어서 재생 중이라면 재생모양 비트맵을, 일시정지중이라면 일시정지 비트맵을 출력한다.
def writeTopLine(): #print LCD top line and rotate when length > 16
global curSong
global stridx
cad.lcd.set_cursor(0,0)
str = song[curSong]
if len(str)>16:
str_rotate = (str+' '+str)[stridx:stridx+15]
stridx += 1
if stridx == len(str)+4:
stridx = 0
cad.lcd.write(str_rotate)
else :
cad.lcd.write(str)
writeTopLine()은 LCD의 윗줄을 출력하는 함수이다. 윗줄에는 노래 제목이 들어가게 되는데, LCD 최대 길이인 16글자를 넘어 갈 경우가 있을 수도 있다. 이 함수는 글자가 16자 이상이라면 한번 실행할 때마다 한 칸씩 흐르게 되어있다. 따라서 main함수에서 writeTopLine()함수를 1초에 한번씩 실행하게 하여 글자가 16자 이상이라면 흐르게 하도록 하자.
def update_pin_text(event):
global pin
pin = event.pin_num
def print_ir_code(event):
global remote
remote = int(event.ir_code)
listener = pifacecad.SwitchEventListener(chip=cad)
for i in range(8):
listener.register(i, pifacecad.IODIR_FALLING_EDGE, update_pin_text)
listener.activate()
remote_listener = pifacecad.IREventListener(prog='myprogram')
for i in range(8):
remote_listener.register(str(i), print_ir_code)
remote_listener.activate()
listener는 PiFace CAD 의 버튼에 대한 인터럽트이고, remote_listener는 IR리모콘에 대한 인터럽트이다. listener는 PiFace CAD버튼이 눌렸을 때 update_pin_text함수를 실행 시키고, remote_listener는 리모콘이 눌렀을 때 print_ir_code 함수를 실행하게 된다. event.pin_num는 누른 버튼의 번호이고, event.ir_code는 리모콘 버튼에 대응하는 config 값이다. 내가 사용할 버튼들을 listener의 register에 등록하고 그에 대한 콜백함수(update_pin_text, print_ir_code)도 입력한다. 콜백함수에서는 버튼에 대한 값을 전역 변수에 저장하도록 하였다. pin과 remote의 값을 통해 음악플레이어를 조종할 것이다.
음악들은 pygame의 mixer를 통해 재생하고, 조종한다.
mixer.music 에는 여러 함수가 있지만, 여기서 사용할 함수들만 소개하겠다.
pygame.mixer.music.load : 파일을 불러온다.
pygame.mixer.music.play : 불러온 파일을 재생한다.
pygame.mixer.music.get_volume : 현재 볼륨을 반환한다.
pygame.mixer.music.set_volume : 해당 값으로 볼륨을 설정한다.
pygame.mixer.music.get_busy : 불러온 파일 스트림이 진행중인지 확인한다.
pygame.mixer.music.pause : 음악을 일시 정지 한다
pygame.mixer.music.unpause : 음악의 일시정지를 푼다.
인터럽트를 통해 pin과 remote에 어떠한 값이 들어왔을 때 그에 대응하는 mixer.music의 함수를 실행시키는 방식으로 구현해보자.
def musicMainfunc():
global pin
global remote
global volume
global play
global mute
global curSong
global stridx
curSong = 0
pin = -1
remote = -1
mixer.init()
mixer.music.set_volume(float(volume)/100)
while True:
if curSong == len(song):
curSong = 0
cad.lcd.clear()
cad.lcd.blink_off()
cad.lcd.cursor_off()
mixer.music.load(song[curSong])
mixer.music.play()
writeTopLine()
count_t = time.time()
while mixer.music.get_busy() == True:
writeBottomLine()
if time.time()-count_t > 1: # writeTopLine every 1 second
writeTopLine()
count_t = time.time()
# song control
if pin == 1 or remote == 1: # prev song
curSong-=2
if curSong==-2:
curSong=len(song)-2
pin = -1
remote = -1
stridx = 0
break;
elif pin == 3 or remote == 3: # next song
pin = -1
remote = -1
stridx = 0
break;
elif pin == 2 or remote == 2: # play and pause
if play:
mixer.music.pause()
play = False
else:
mixer.music.unpause()
play = True
pin = -1
remote = -1
# volume control
elif pin == 6 or remote == 6: # volume down
while True:
volume -= 3
if volume < 0:
volume = 0
mixer.music.set_volume(float(volume)/100)
updateVolume();
sleep(0.2)
if not cad.switches[6].value:
break
pin = -1
remote = -1
elif pin == 7 or remote == 7: # volume up
while True:
volume += 3
if volume > 100:
volume = 100
mixer.music.set_volume(float(volume)/100)
updateVolume();
sleep(0.2)
if not cad.switches[7].value:
break
pin = -1
remote = -1
elif pin == 5 or remote == 5: # mute
if mute:
mixer.music.set_volume(float(volume)/100)
mute = False
else:
mixer.music.set_volume(0)
mute = True
pin = -1
remote = -1
elif pin == 4 or remote == 4: # quit
pin = -1
remote = -1
mixer.quit()
return
curSong+=1
위에서 부터 pin과 remote 값이 1이 되면 이전 곡을 튼다. 3이 되면 다음곡을 틀고, 2가 되면 일시 정지 및 재생을 한다. 6과 7은 볼륨을 낮추고 올리며, 5는 음소거를 하고 해제한다. 마지막으로 4는 mixer를 종료한다.
정리하여 PiFace CAD 버튼과 리모콘 버튼의 역할은 다음과 같다.
1. 이전 곡 <- KEY_CHANNELDOWN
2. 재생 및 일시정지 <- KEY_OK
3. 다음 곡 <- KEY_CHANNELUP
4. 종료 <- KEY_MENU
5. 음소거 및 해제 <- KEY_MUTE
6. 볼륨 낮추기 <- KEY_VOLUMEUP
7. 볼륨 올리기 <- KEY_VOLUMEDOWN
이제 위의 코드들을 합치고 musicMainfunc()을 실행시키면 PiFaceCAD를 이용해 음악플레이어를 확인할 수 있다. 아래의 데모영상을 보고 잘 구현되었는지 확인해보자.
'Raspberry' 카테고리의 다른 글
Korean Alexa with Raspberry pi (1) | 2017.05.09 |
---|---|
Raspberry Pi로 LED 제어하기 (0) | 2017.04.11 |
Pi Camera를 이용해 Timelapse 촬영하기 (0) | 2017.04.08 |
Raspberry 부팅시에 자동으로 파이썬 스크립트 실행하기 (0) | 2017.04.02 |
PiFaceCAD를 이용해 인터넷 라디오 스트리머 만들기 (0) | 2017.03.29 |