1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2013 Alexis Laferrière <alexis.laf@xymus.net>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # Backend to a hardware interface to control an MPD server from a Raspberry Pi
19 # It supports two inputs: a play/pause button and a rotary encoder to adjust
22 # The each data output of the volume control are connected to the board
24 module physical_interface_for_mpd_on_rpi
30 class PhysicalInterface
31 var mpd
= new MPDConnection(server
, port
, password
)
32 protected fun password
: String do return "password"
33 fun server
: String do return "localhost"
34 fun port
: Int do return 6600
36 var but_play
: Switch is noinit
37 var but_playlist_a
: Switch is noinit
39 var vol
: RotaryEncoder is noinit
42 var lcd
: HD44780 is noinit
44 var lcd_backlight
: RPiPin is noinit
45 var lcd_backlight_delay
= 1000
47 var buzzer
: Buzzer is noinit
51 # commandline options for privileges drop
52 var opts
= new OptionContext
53 var opt_ug
= new OptionUserAndGroup.for_dropping_privileges
54 #opt_ug.mandatory = true
55 opts
.add_option
(opt_ug
)
57 # parse and check command line options
59 if not opts
.errors
.is_empty
then
61 print
"Usage: {sys.program_name} [options]"
66 assert bcm2835_init
else print
"Failed to init"
69 var user_group
= opt_ug
.value
70 if user_group
!= null then user_group
.drop_privileges
73 but_play
= new Switch(new RPiPin.p1_13
, new PUDControl.down
)
76 but_playlist_a
= new Switch(new RPiPin.p1_15
, new PUDControl.down
)
79 var vol3
= new RPiPin.p1_03
80 vol3
.fsel
= new FunctionSelect.inpt
81 vol3
.pud
= new PUDControl.up
84 var vol5
= new RPiPin.p1_05
85 vol5
.fsel
= new FunctionSelect.inpt
86 vol5
.pud
= new PUDControl.up
88 vol
= new RotaryEncoder(vol3
,vol5
)
91 var lcd_rs
= new RPiPin.p1_23
92 var lcd_en
= new RPiPin.p1_21
93 var lcd_d4
= new RPiPin.p1_19
94 var lcd_d5
= new RPiPin.p1_26
95 var lcd_d6
= new RPiPin.p1_24
96 var lcd_d7
= new RPiPin.p1_22
97 lcd
= new HD44780(lcd_rs
, lcd_en
, lcd_d4
, lcd_d5
, lcd_d6
, lcd_d7
)
101 lcd_backlight
= new RPiPin.p1_18
102 lcd_backlight
.fsel
= new FunctionSelect.outp
105 var buzzer_pin
= new RPiPin.p1_11
106 buzzer_pin
.fsel
= new FunctionSelect.outp
107 buzzer
= new Buzzer(buzzer_pin
)
115 var force_lcd_update
= false
118 if but_play
.changed
and but_play
.is_down
then
121 force_lcd_update
= true
124 if but_playlist_a
.changed
and but_playlist_a
.is_down
then
126 force_lcd_update
= true
134 mpd
.relative_volume
= -vol_step
137 mpd
.relative_volume
= vol_step
139 force_lcd_update
= true
143 if tick
% 100 == 0 or force_lcd_update
then
144 var status
= mpd
.status
145 var song
= mpd
.current_song
148 if status
== null then
149 lcd
.text
= "Unknown status"
150 else if song
== null then
151 lcd
.text
= "No song playing"
153 if status
.playing
then
156 else status_char
= "#"
158 var tr
= status
.time_ratio
160 if tr
!= null then pos
= (status
.time_ratio
*10.0).to_i
.to_s
162 lcd
.text
= "{status_char} {song.artist}\n{pos} {song.title}"
167 if force_lcd_update
then last_event
= tick
169 var diff_with_last_event
= tick
- last_event
170 if diff_with_last_event
== 0 then
171 lcd_backlight
.write
(true)
172 else if diff_with_last_event
== lcd_backlight_delay
then
173 lcd_backlight
.write
(false)
184 var status
= mpd
.status
186 if status
!= null then
187 playing
= status
.playing
189 print
"Cannot get state"
195 print
"playing -> stop"
198 print
"stopped -> play"
207 mpd
.load_playlist
("alexis")
210 fun bell
do buzzer
.buzz
(1.5, 20)
213 var phy
= new PhysicalInterface