Merge: Nitsmell : Adding new code smells and print console updated
[nit.git] / contrib / physical_interface_for_mpd_on_rpi / physical_interface_for_mpd_on_rpi.nit
index 91ab731..1c73e64 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# This programs interprets the input of a physical interface thought the
-# GPIO pins of a Raspberry Pi to control an MPD server.
+# Backend to a hardware interface to control an MPD server from a Raspberry Pi
 #
-# It suppot two inputs: a play/pause button and a rotary encoder to adjust
+# It supports two inputs: a play/pause button and a rotary encoder to adjust
 # the volume.
 #
 # The each data output of the volume control are connected to the board
@@ -28,137 +27,188 @@ import bcm2835
 import mpd
 import privileges
 
-redef class Object
-       fun mpd: MPDConnection do return once new MPDConnection("localhost", 6600, "password")
-end
+class PhysicalInterface
+       var mpd = new MPDConnection(server, port, password)
+       protected fun password: String do return "password"
+       fun server: String do return "localhost"
+       fun port: Int do return 6600
 
-fun hit_play_stop
-do
-       # get current status
-       var status = mpd.status
-       var playing = false
-       if status != null then
-               playing = status.playing
-       else
-               print "Cannot get state"
-               return
-       end
+       var but_play: Switch is noinit
+       var but_playlist_a: Switch is noinit
 
-       if playing then
-               # stop
-               print "playing -> stop"
-               mpd.pause
-       else
-               print "stopped -> play"
-               mpd.play
-       end
-end
+       var vol: RotaryEncoder is noinit
+       var vol_step = 2
 
-# commandline options for privileges drop
-var opts = new OptionContext
-var opt_ug = new OptionDropPrivileges
-#opt_ug.mandatory = true
-opts.add_option(opt_ug)
-
-# parse and check command line options
-opts.parse(args)
-if not opts.errors.is_empty then
-       print opts.errors
-       print "Usage: {program_name} [options]"
-       opts.usage
-       exit 1
-end
+       var lcd: HD44780 is noinit
+
+       var lcd_backlight: RPiPin is noinit
+       var lcd_backlight_delay = 1000
+
+       var buzzer: Buzzer is noinit
+
+       init
+       do
+               # commandline options for privileges drop
+               var opts = new OptionContext
+               var opt_ug = new OptionUserAndGroup.for_dropping_privileges
+               #opt_ug.mandatory = true
+               opts.add_option(opt_ug)
+
+               # parse and check command line options
+               opts.parse(args)
+               if not opts.errors.is_empty then
+                       print opts.errors
+                       print "Usage: {sys.program_name} [options]"
+                       opts.usage
+                       exit 1
+               end
+
+               assert bcm2835_init else print "Failed to init"
+
+               # drop privileges!
+               var user_group = opt_ug.value
+               if user_group != null then user_group.drop_privileges
+
+               # Play button
+               but_play = new Switch(new RPiPin.p1_13, new PUDControl.down)
 
-assert bcm2835_init else print "Failed to init"
-
-# drop privileges!
-var user_group = opt_ug.value
-if user_group != null then user_group.drop_privileges
-
-# Debug LED
-var out = new RPiPin.p1_11
-out.fsel = new FunctionSelect.outp
-out.write(false)
-
-# Play button
-var inp = new RPiPin.p1_13
-inp.fsel = new FunctionSelect.inpt
-inp.pud = new PUDControl.down
-
-# Vol +
-var vol3 = new RPiPin.p1_03
-vol3.fsel = new FunctionSelect.inpt
-vol3.pud = new PUDControl.up
-
-# Vol -
-var vol5 = new RPiPin.p1_05
-vol5.fsel = new FunctionSelect.inpt
-vol5.pud = new PUDControl.up
-
-var vol = new RotaryEncoder(vol3,vol5)
-var vol_step = 2
-
-# LCD
-var lcd_rs = new RPiPin.p1_23
-var lcd_en = new RPiPin.p1_21
-var lcd_d4 = new RPiPin.p1_19
-var lcd_d5 = new RPiPin.p1_26
-var lcd_d6 = new RPiPin.p1_24
-var lcd_d7 = new RPiPin.p1_22
-var lcd = new HD44780(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, lcd_d7)
-lcd.setup
-lcd.clear
-
-var last_in = false
-var led_on = false
-var tick = 0
-loop
-       var force_lcd_update = false
-
-       # play button
-       var lev = inp.lev
-       if lev != last_in then
-               last_in = lev
-               if lev then hit_play_stop
-               force_lcd_update = true
+               # Playlist a button
+               but_playlist_a = new Switch(new RPiPin.p1_15, new PUDControl.down)
+
+               # Vol +
+               var vol3 = new RPiPin.p1_03
+               vol3.fsel = new FunctionSelect.inpt
+               vol3.pud = new PUDControl.up
+
+               # Vol -
+               var vol5 = new RPiPin.p1_05
+               vol5.fsel = new FunctionSelect.inpt
+               vol5.pud = new PUDControl.up
+
+               vol = new RotaryEncoder(vol3,vol5)
+
+               # LCD
+               var lcd_rs = new RPiPin.p1_23
+               var lcd_en = new RPiPin.p1_21
+               var lcd_d4 = new RPiPin.p1_19
+               var lcd_d5 = new RPiPin.p1_26
+               var lcd_d6 = new RPiPin.p1_24
+               var lcd_d7 = new RPiPin.p1_22
+               lcd = new HD44780(lcd_rs, lcd_en, lcd_d4, lcd_d5, lcd_d6, lcd_d7)
+               lcd.setup
+               lcd.clear
+
+               lcd_backlight = new RPiPin.p1_18
+               lcd_backlight.fsel = new FunctionSelect.outp
+
+               # Buzzer
+               var buzzer_pin = new RPiPin.p1_11
+               buzzer_pin.fsel = new FunctionSelect.outp
+               buzzer = new Buzzer(buzzer_pin)
        end
 
-       # volume
-       var s = vol.update
-       if s != null then
-               if s == '<' then
-                       print "vol down"
-                       mpd.relative_volume = -vol_step
-               else # >
-                       print "vol up"
-                       mpd.relative_volume = vol_step
+       fun run
+       do
+               var tick = 0
+               var last_event = 0
+               loop
+                       var force_lcd_update = false
+
+                       # play button
+                       if but_play.changed and but_play.is_down then
+                               print "but"
+                               hit_play_stop
+                               force_lcd_update = true
+                       end
+
+                       if but_playlist_a.changed and but_playlist_a.is_down then
+                               play_playlist_a
+                               force_lcd_update = true
+                       end
+
+                       # volume
+                       var s = vol.update
+                       if s != null then
+                               if s == '<' then
+                                       print "vol down"
+                                       mpd.relative_volume = -vol_step
+                               else # >
+                                       print "vol up"
+                                       mpd.relative_volume = vol_step
+                               end
+                               force_lcd_update = true
+                       end
+
+                       # update lcd
+                       if tick % 100 == 0 or force_lcd_update then
+                               var status = mpd.status
+                               var song = mpd.current_song
+
+                               var status_char
+                               if status == null then
+                                       lcd.text = "Unknown status"
+                               else if song == null then
+                                       lcd.text = "No song playing"
+                               else
+                                       if status.playing then
+                                               last_event = tick
+                                               status_char = ">"
+                                       else status_char = "#"
+
+                                       var tr = status.time_ratio
+                                       var pos = "-"
+                                       if tr != null then pos = (status.time_ratio*10.0).to_i.to_s
+
+                                       lcd.text = "{status_char} {song.artist}\n{pos} {song.title}"
+                               end
+                       end
+
+                       # manage backlight
+                       if force_lcd_update then last_event = tick
+
+                       var diff_with_last_event = tick - last_event
+                       if diff_with_last_event == 0 then
+                               lcd_backlight.write(true)
+                       else if diff_with_last_event == lcd_backlight_delay then
+                               lcd_backlight.write(false)
+                       end
+
+                       10.bcm2835_delay
+                       tick += 1
                end
-               force_lcd_update = true
        end
 
-       # update lcd
-       if tick % 100 == 0 or force_lcd_update then
+       fun hit_play_stop
+       do
+               # get current status
                var status = mpd.status
-               var song = mpd.current_song
+               var playing = false
+               if status != null then
+                       playing = status.playing
+               else
+                       print "Cannot get state"
+                       return
+               end
 
-               var status_char
-               if status == null then
-                       lcd.text = "Unknown status"
-               else if song == null then
-                       lcd.text = "No song playing"
+               if playing then
+                       # stop
+                       print "playing -> stop"
+                       mpd.pause
                else
-                       if status.playing then
-                               status_char = ">"
-                       else status_char = "#"
+                       print "stopped -> play"
+                       mpd.play
+               end
 
-                       var tr = status.time_ratio
-                       var pos = "-"
-                       if tr != null then pos = (status.time_ratio*10.0).to_i.to_s
+               bell
+       end
 
-                       lcd.text = "{status_char} {song.artist}\n{pos} {song.title}"
-               end
+       fun play_playlist_a
+       do
+               mpd.load_playlist("alexis")
        end
 
-       10.bcm2835_delay
-       tick += 1
+       fun bell do buzzer.buzz(1.5, 20)
 end
+
+var phy = new PhysicalInterface
+phy.run