SSブログ

Volumio2で音楽5 [Volumio]

有機ELディスプレイに曲名や歌手名を出すためにプログラムを書きます。
root@volumio:~# /var/tmp/mkinitramfs_8pJogT/bin/vi SSD1306.py

以下のプログラムを書きます。
#!/usr/bin/python
# -*- coding: utf-8 -*-

import os
import sys
import smbus
import time
import signal
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
from socketIO_client import SocketIO

PIDFILE='/var/run/SSD1306.pid'

class SSD1306(object):

	DISPLAYOFF = 0xAE
	DISPLAYON = 0xAF
	DISPLAYALLON = 0xA5
	DISPLAYALLON_RESUME = 0xA4
	NORMALDISPLAY = 0xA6
	INVERTDISPLAY = 0xA7
	SETREMAP = 0xA0
	SETMULTIPLEX = 0xA8
	SETCONTRAST = 0x81
	CHARGEPUMP = 0x8D
	COLUMNADDR = 0x21
	COMSCANDEC = 0xC8
	COMSCANINC = 0xC0
	EXTERNALVCC = 0x1
	MEMORYMODE = 0x20
	PAGEADDR = 0x22
	SETCOMPINS = 0xDA
	SETDISPLAYCLOCKDIV = 0xD5
	SETDISPLAYOFFSET = 0xD3
	SETHIGHCOLUMN = 0x10
	SETLOWCOLUMN = 0x00
	SETPRECHARGE = 0xD9
	SETSEGMENTREMAP = 0xA1
	SETSTARTLINE = 0x40
	SETVCOMDETECT = 0xDB
	SWITCHCAPVCC = 0x2    
	
	OLED_WIDTH      = 128
	OLED_HEIGHT     =  64
	OLED_PAGE_COUNT =   8
	OLED_SIZE       = ( OLED_WIDTH , OLED_HEIGHT )
	
	OLED_TARGET     = 0x3C
	OLED_CMDMODE    = 0x00
	OLED_DATAMODE   = 0x40
	
	def command(self, *cmd):
		self.__bus.write_i2c_block_data(self.OLED_TARGET,self.OLED_CMDMODE,list(cmd))
	
	def cleanup(self):
		self._hide()
		self.clear()
		self.__bus.close()
	
	def clear(self):
		self.display(Image.new("1",self.OLED_SIZE))
	
	def show(self):
		self.command(self.DISPLAYON)
	
	def hide(self):
		self.command(self.DISPLAYOFF)
		
	def contrast(self,level):
		self.command(self.SETCONTRAST,level)
	
	def __init__(self):
		self.buffer = [0] * self.OLED_PAGE_COUNT * self.OLED_WIDTH;

		self.__bus = smbus.SMBus(1)
		
	def init(self):
		self.command(
			self.DISPLAYOFF,
			self.SETDISPLAYCLOCKDIV, 0x80,
			self.SETMULTIPLEX,       0x3F,
			self.SETDISPLAYOFFSET,   0x00,
			self.SETSTARTLINE,
			self.CHARGEPUMP,         0x14,
			self.MEMORYMODE,         0x00,
			self.SETSEGMENTREMAP,
			self.COMSCANDEC,
			self.SETCOMPINS,         0x12,
			self.SETPRECHARGE,       0xF1,
			self.SETVCOMDETECT,      0x40,
			self.DISPLAYALLON_RESUME,
			self.NORMALDISPLAY)
		self.contrast(0xCF)
		self.clear()
		self.show()
	
	def display(self,image):

		pix = image.load()
		index = 0
		for page in range(8):
			for x in range(128):
				bits = 0
				for bit in [0, 1, 2, 3, 4, 5, 6, 7]:
					bits = bits << 1
					bits |= 0 if pix[(x, page*8+7-bit)] == 0 else 1
				self.buffer[index] = bits
				index += 1
		
		self.command(self.COLUMNADDR, 0x00, 128-1, self.PAGEADDR, 0x00, 8-1)
		
		for i in range(0, len(self.buffer), 16):
			self.__bus.write_i2c_block_data(self.OLED_TARGET,self.OLED_DATAMODE,self.buffer[i:i+16])
		

class socketio(object):

	def __init__(self):
		self.album = ''
		self.title = ''
		self.artist= ''
		self.samplerate = ''
		self.bitdepth   = ''
		
	def init(self):
		self.socketIO = SocketIO('localhost', 3000)
		self.socketIO.on('pushState', self.on_pushState)
		self.ssd = SSD1306()
		self.ssd.init()
	
	def max_length(self,font,text):
		length = len(text)
		for i in range(0,length-1,1):
			w = font.getsize(text[0:i])[0]
			if w > 128:
				return i + 1
		return length
	
	def on_pushState(self,args):
	
		s = ''
		b = ''
		
		if 'samplerate' in args :
			s = args['samplerate']
		else:
			s = ''
			
		if 'bitdepth' in args:
			b = args['bitdepth']
		else:
			b = ''

		if self.album == args['album'] and self.title == args['title'] and self.artist == args['artist'] and self.samplerate == s and self.bitdepth == b :
			return
			
		self.album = args['album']
		self.title = args['title']
		self.artist= args['artist']
		self.samplerate = s
		self.bitdepth   = b
	
		image = Image.new('1', (self.ssd.OLED_WIDTH, self.ssd.OLED_HEIGHT),0)
		draw = ImageDraw.Draw(image)
		draw.rectangle((0,0,self.ssd.OLED_WIDTH-1, self.ssd.OLED_HEIGHT-1), outline=0, fill=0)
		jpfont = ImageFont.truetype('/usr/share/fonts/truetype/takao-gothic/TakaoPGothic.ttf',12, encoding="unic")
		
		draw.text((0,0 ), self.album , font=jpfont, fill=1)
		e = 0
		length = len(self.title)
		e = self.max_length(jpfont,self.title)
		if e < length:
			draw.text((0,12), self.title[0:e-2] , font=jpfont, fill=1)
			draw.text((0,24), self.title[e-2:length] , font=jpfont, fill=1)
		else:
			draw.text((0,12), self.title , font=jpfont, fill=1)
			
		draw.text((0,36), self.artist, font=jpfont, fill=1)
		
                if 'samplerate' in args and 'bitdepth' in args:
                        f = '%s | %s' % (self.samplerate, self.bitdepth)
                        #draw.text((0,50), str(self.samplerate) + '|' + str(self.bitdepth), font=jp
                        draw.text((0,50), f, font=jpfont, fill=1)
                else:
                        draw.text((0,50), '', font=jpfont, fill=1)

                self.ssd.display(image)

                print('-----')
                print(self.album.encode('utf-8'))
                print(self.title.encode('utf-8'))
                print(self.artist.encode('utf-8'))
                if 'samplerate' in args and 'bitdepth' in args:
                        #print(str(self.samplerate) + "|" + str(self.bitdepth))
                        print(f)
                else:
                        print('-NaN-')
                print('-----')

	def setRandom(self):
		self.socketIO.emit('setRandom',{'value' : 'true'})
		self.socketIO.emit('getState')
		while True:
			self.socketIO.wait(seconds=1)

def main_loop():
	volumio = socketio()
	volumio.init()
	volumio.setRandom()
	os.remove(PIDFILE)
	sys.exit()


def signal_handler(signal,handler):
	os.remove(PIDFILE)
	sys.exit()

def daemonize():
	pid=os.fork()
	if pid > 0:
		pidf = open(PIDFILE,'w')
		pidf.write(str(pid)+'\n')
		pidf.close()
		sys.exit()

	if pid == 0:
		signal.signal(signal.SIGINT, signal_handler)
		signal.signal(signal.SIGTERM, signal_handler)
		main_loop()

if __name__ == '__main__':
	daemonize()

次に、起動時にデーモンとして動くように登録します。
root@volumio:~# /var/tmp/mkinitramfs_8pJogT/bin/vi /etc/systemd/system/ssd1306.service

以下の入力します。
[Unit]
Description=Volumio2 SSD1306 display

[Service]
ExecStart=/root/SSD1306.py
Restart=always
Type=forking
PIDFile=/var/run/SSD1306.pid

[Install]
WantedBy=multi-user.target

コマンドを入力して有効にします。
root@volumio:~# chmod +x SSD1306.py
root@volumio:~# systemctl enable ssd1306.service

再起動すれば、アルバム名、曲名、歌手名、サンプルレートが表示されます。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。