SSブログ

Volumioプラグインを一つにしました [Volumio]

OPAです。
Volumioの曲名とサウンドメーターのプラグインを一つにまとめました。
DSC_0098.JPG


あと要望としてあった、曲停止時にスクリーンセーバー的なものを入れました。
DSC_0099.JPG


設定画面でいろいろと設定できます。

設定画面.JPG


  • ランダムモードを無効・有効に設定します
  • サウンドメータのモードを設定します(VU Meter/Peak Meter/Spectrum)
  • I2C アドレスを反転させます
  • 曲名表示用のIC2アドレスを設定します(0x3C)
  • VUメータ表示用I2Cアドレスを設定します(0x3D)
  • GPIO PINによるアドレス切り替えを有効にします
  • GPIO PINを選択します(2~27)
  • スクリーンセーバーを選択します(BLANK/WATCH/LINE)

https://www.dropbox.com/s/jqwikzb5xg0l4tf/ssd1306I2c_Integration_display_20190429_2.zip?dl=0

I2Cアドレスは、秋月電子様のモジュール以外は試していないので、動作は確認できていません。またGPIO PINによるI2Cアドレスの切り替えは、Raspbery Pi Zero wのGPIO26以外は試していません。
volumioのバグか不明ですが、マルチルームにすると曲名が正しく更新されません。もしかしたら本プラグインの負荷が高く、node.jsのイベント処理がついていけなくなっているのかもしれません。検証できていません。
Raspbery Pi zero w / Raspbery Pi 3B(GPIO PINのIc2アドレス切り替えは試していない)で確認しています。Raspbery Pi以外のプラットフォームは動作しません。node.jsモジュールのonoffモジュールがプラットフォーム依存になっているためです。
いろいろと制限ありますが、公開しますのでお試しください。
2019/4/23 追記
Raspbery Pi zero wだと、Volumioから送られてくる情報が更新されない場合があるようで、もしかしたらmpdから取得するように変更するかもしれません。

2019/4/28 追記
mpdモードを追加しました。volumioのwebsocketによるイベント処理だとうまく更新されてきません。mpdから直接情報を取るようにしてみました。しばらくこれで様子見です。また、mpdモードでは、出力フォーマット(ビットレート、サンプリング周波数)の情報をprocファイルシステムから取得できるようになっています。

2019/4/29更新>
再インストール時に、前のパッケージを削除するようにしました。

nice!(1)  コメント(0) 

週末の出来事(別館)開設!! [Volumio]

OPAです。

ファイルウェブのコミュニティに本ブログの別館を開設しました。

http://community.phileweb.com/mypage/entry/5253/20190326/62095/

プラグインを使用している方、感想などありましたらコメントいただければ幸いです。


nice!(0)  コメント(0) 

Volumioプラグインの更新 [Volumio]

OPAです。
曲名を表示するプラグインを更新しました。曲の時間と経過を示すプログレスバーの表示、 再生時に♫マークを出すようにしてみました。

https://www.dropbox.com/s/v53ujubne1a2229/ssd1306I2c_20190321_1.zip?dl=0
※2019/3/21 シャットダウン時に表示がクリアされない問題を直しました。
曲(時間).JPG

nice!(1)  コメント(0) 

Raspberry Pi Zero WにVolumioをインストールしてみた [Volumio]

OPAです。
以前作成した、PCM5102AのDAC基板と有機ELディスプレイ基板を使って、Raspberry Pi Zero WにVolumioをインストールしてみました。WiFiで接続できるメリットもありますが、不安定なWiFiでもあるので、ネットワークでの音楽共有ファイルを取得するのでなく、USBメモリで音楽ファイルを扱います。

組立前

0224_分割.JPG


組立後

0224_組立.PNG

Volumio2をダウンロード

https://volumio.org/
メニューのDownloadを選択し、RASPBERRY PIのファイルをダウンロードします。

ダウンロードしたファイルを解凍

圧縮されたvolumio-2.555-2019-02-18-pi.img.zipを解凍し、volumio-2.555-2019-02-18-pi.imgイメージファイルを取り出します。
ダウンロードするタイミングでファイル名は異なります。

イメージを書き込む

PCにSDカードを入れ、イメージライターを使ってイメージファイルをSDカードに書き込みます。

0224_イメージライター.PNG


Writeボタンを押下してイメージを書き込みします。

Raspberry Pi Zero WにSDカードを挿入

イメージを書き込んだSDカードをRaspberry Pi Zero Wに挿入します。

プラグインをダウンロード

曲名を表示する自作プラグインをダウンロードします。

https://www.dropbox.com/s/2zlv0r6gqaugadg/ssd1306I2c_20190224_1.zip?dl=0

Dropboxの画面で右上にあるダウンロードボタンを押下してファイルをダウンロードします。

USBメモリと電源を入れる

曲の入ったUSBメモリと、電源を接続してVolumioを起動します。

PCのWiFi接続先を切り替える

私のPCのネットワーク接続は、WiFiを使用しています。Volumioはホットスポットモードで起動しますので接続を切り替えます。

0224_WiFi.PNG

Volumioというアクセスポイントがあるので、選択します。パスワードはvolumio2です。

volumioのセットアップ

ブラウザで、
http://volumio.local/
に接続します。

言語の選択


0224_volumioセットアップ1.PNG

デバイス名の設定


0224_volumioセットアップ2.PNG

ここでは、Volumio3と名前を付けます。

DACの設定


0224_volumioセットアップ3.PNG

I2S DACを有効にして、HiFiBerry DAC(PCM5102A)を選択します。

WiFiの設定


0224_volumioセットアップ4.PNG

普段使用しているWiFiのアクセスポイントを選択して接続します。接続が成功すると以下のように画面が表示されます。

0224_volumioセットアップ5.PNG

ドライブの設定


0224_volumioセットアップ6.PNG

ネットワークドライブ(NAS)は使用しないので新規に追加しません。

セットアップ完了


0224_volumioセットアップ7.PNG

Doneボタンを押下してセットアップを完了します。

再起動


0224_volumioセットアップ8.PNG

再起動ボタンを押下して再起動します。

WiFiを切り替える

普段使用しているWiFiのアクセスポイントに戻します。ブラウザで、
http://volumio3.local/
に接続できるか確認します。(しばらく経ってから)

デバッグモードを設定する

http://volumio3.local/DEV/
にアクセスします。

0224_volumioセットアップ9.PNG

SSHのENABLEボタンを押下します。特に画面に結果等は表示されません。

プラグインをインストール

ダウンロードしたプラグインをWinSCPを使用してファイルをアップロードします。

0224_scpログイン.PNG

ホスト名にvolumio3.local、ユーザ名にvolumio、パスワードにvolumioを指定して接続します。
プラグインを選択して、ファイルを転送します。

0224_scp転送.PNG

TeraTermでvolumio3.localにアクセスします。

0224_tera接続.PNG


0224_tera接続.PNG

ユーザ名にvolumio、パスワードにvolumioを指定して接続します。
ターミナル上で以下のコマンドを実行してプラグインをインストールします。
volumio@volumio3:~$ miniunzip ssd1306I2c_20190224_1.zip
volumio@volumio3:~$ cd ssd1306I2c
volumio@volumio3:~/ssd1306I2c$ volumio plugin install

インストールが完了すると以下のように表示されます。

0224_プラグインインストールDone.PNG

曲名を表示するプラグインの設定

ブラウザを開き、設定メニューからプラグインを選択し画面を表示します。
インストール済みのプラグインのタブを選択し、SSD1306 I2C Displayプラグインが表示されていることを確認し、アクティブに変更します。

0224_SSD1306プラグイン.PNG

設定ボタンを押下します。

0224_SSD1306プラグイン設定.PNG

必要に応じて設定します。

GPIO Buttonsプラグインのインストール

作った有機ELディスプレイ基板にはGPIOのボタンがありますので、GPIO Buttonsプラグインをインストールして、ブラウザから操作せずにコントロールできるようにします。
プラグインの検索タブを押下し、System Toolsを選択します。

0224_GPIOプラグインインストール.PNG

インストールボタンを押下して、GPIO Buttonsプラグインをインストールします。
インストール済みのプラグインのタブを押下し、GPIO Buttonsプラグインをアクティブにします。

0224_GPIOプラグイン.PNG

設定ボタンを押下します。
以下のように設定します。

0224_GPIOプラグイン設定.JPG

Play/Pause GPIO Pin 27
Previous GPIO Pin 22
Next GPIO Pin 17
Shutdown GPIO Pin 13
Saveボタンを押下して保存します。

キューに曲を追加

ブラウザで、一覧表示を選択します。

0224_ホーム画面.PNG

音楽ライブラリを選択します。

0224_キューに追加.PNG

USBのメニューからキューに追加を選択し、USBメモリにある音楽ファイルをキューに追加します。

再生

再生ボタンを押下して、曲が再生され有機ELディスプレイに曲名が表示されるか確認します。

0224_動作.PNG


以上です。参考まで。

nice!(0)  コメント(0) 

有機ELディスプレイを使ったVolumioのプラグインを更新しました [Volumio]

OPAです。
有機ELディスプレイを使ったVolumioのプラグインを更新しました。 機能的には変更はありませんが、新しいバージョンのVolumioだとインストールが できないのが分かったので見直しをしました。

◆曲名を表示するプラグイン
https://www.dropbox.com/s/2zlv0r6gqaugadg/ssd1306I2c_20190224_1.zip?dl=0

◆サウンドメーターを表示するプラグイン
https://www.dropbox.com/s/pr14ej0sghph5fy/soundmeter_20190224_1.zip?dl=0

nice!(0)  コメント(0) 

IR Remote Controllerプラグインに別のコントローラを追加する [Volumio]

OPAです。
volumioで赤外線リモコン用のプラグインがあるのですが、アップルのリモコンとかしか対応していません。なので、秋月電子様で売っている赤外線リモコン(オプトサプライ赤外線リモコン)用の設定ファイルを作成して動かしてみました。

リモコン.JPG

赤外線リモコン受信モジュールOSRB38C9AAを接続します。出力はGPIO26(PIN37)に接続しました。
プラグインをインストールします。IR Remote ControllerはAccessoriesにあります。
/boot/config.txtファイルに以下を追加します。

dtoverlay=lirc-rpi,gpio_in_pin=26,gpio_in_pull=up

以下のディレクトリに「OE13KIR」ディレクトリを作成します。
/data/plugins/system_controller/ir_controller/configurations
OE13KIRディレクトリに2つのファイルを作成します。
lircd.conf
begin remote

  name  /etc/lirc/lircd.conf
  bits           32
  flags SPACE_ENC|CONST_LENGTH
  eps            30
  aeps          100

  header       9041  4462
  one           595  1648
  zero          595   533
  ptrail        593
  gap          107446
  toggle_bit_mask 0x0

      begin codes
          KEY_POWER                    0x08F71BE4
          KEY_A                        0x08F71FE0
          KEY_B                        0x08F71EE1
          KEY_C                        0x08F71AE5
          KEY_UPPER_LEFT               0x08F78D72
          KEY_UPPER                    0x08F705FA
          KEY_UPPER_RIGHT              0x08F7847B
          KEY_LEFT                     0x08F708F7
          KEY_CENTER                   0x08F704FB
          KEY_RIGHT                    0x08F701FE
          KEY_LOWER_LEFT               0x08F78877
          KEY_LOWER                    0x08F700FF
          KEY_LOWER_RIGHT              0x08F7817E
      end codes

end remote


lircrc
begin
prog = irexec
button = KEY_POWER
config = poweroff
end
begin
prog = irexec
button = KEY_CENTER
config = /usr/local/bin/volumio toggle
end
begin
prog = irexec
button = KEY_UPPER
config = /usr/local/bin/volumio volume plus
end
begin
prog = irexec
button = KEY_LOWER
config = /usr/local/bin/volumio volume minus
end
begin
prog = irexec
button = KEY_LEFT
config = /usr/local/bin/volumio previous
end
begin
prog = irexec
button = KEY_RIGHT
config = /usr/local/bin/volumio next
end
begin
prog = irexec
button = KEY_A
config = /usr/local/bin/volumio repeat
end
begin
prog = irexec
button = KEY_B
config = /usr/local/bin/volumio random
end

このプラグイン、再起動するとデーモンが起動しないので、再起動してもデーモンが起動するように設定します。

sudo systemctl enable lirc


あとは、プラグインの設定画面で、OE13KIRを選択すれば使えるようになります。
nice!(1)  コメント(3) 

有機ELディスプレイ(OLED)を使ったサウンドメーターのvolumioプラグイン公開 [Volumio]

OPAです。秋月電子様の「0.96インチ 128×64ドット有機ELディスプレイ(OLED)」を使ってvolumioのサウンドメータープラグインを作ってみました。この有機ELディスプレイは、I2Cインタフェースで制御しますが、アドレスを2つ切り替えることができ、2つ同時に制御することができます。有機ELディスプレイの裏面にチップ部品がついていて、それを片方に付け替えることでアドレスを切り替えることができます。
以下の写真は、付け替えたものです。

SSD1306_0x7A.jpg


作ったプラグインは、3つのモードが存在し、表示を切り替えられます。

SoundMeter_VU.JPG


SoundMeter_Peak.JPG


SoundMeter_Spec.JPG

I2Cインタフェースやらpythonやらで、厳密にタイミングよく表示されていないと思いますので、導入する人はあくまでもおもちゃとして使ってください。
このプラグインを導入するために、先に公開した曲名を表示するプラグインも修正していますので、両方使う人は、先のプラグインをアンインストールしてから再度、新しいプラグインを導入してください。

曲名を表示するプラグイン

https://www.dropbox.com/s/6we0921ryzkr34l/ssd1306I2c_20180623_1.zip?dl=0

※プラグインの設定画面で、起動時にランダムモードするかしないかのオプションを追加しました。

サウンドメータープラグイン

https://www.dropbox.com/s/mntiivl8nj6k2m9/soundmeter_20180623_1.zip?dl=0

※プラグインの設定画面で、表示モードを3つ選択できます。
/boot/config.txt ファイルに以下のエントリを追加すると表示が速くなります。

dtparam=i2c_arm_baudrate=400000

本プラグインは、Raspberry Pi2で動作を確認しています。ほかのボードでは試していないのでインストールできないかもしれませんのであしからず。自己責任でお願いします。
前の投稿で、圧縮されたファイルを展開してからvolumioに転送していましたが、miniunzipというコマンドが内蔵されていたため、圧縮したまま転送して、volumio上で展開することができました。
nice!(0)  コメント(9) 

秋月電子様の0.96インチ 128×64ドット有機ELディスプレイ(OLED)のvolumioプラグイン公開 [Volumio]

OPAです。
秋月電子様の0.96インチ 128×64ドット有機ELディスプレイ(OLED)を使った曲名等を表示するvolumioのプラグインを公開します。野良プラグインですので標準のインストール方法ではインストールできませんのであしからず。
以下、野良プラグインのインストール方法です。

SSHの設定

デフォルトでSSHが使えないので、Volumioの設定を変更します。ここでは、volumioのホスト名を、 volumio2.localにしています。
http://volumio2.local/DEV/
にアクセスして、SSHをenableに設定します。

DEVページ.JPG


プラグインのダウンロード

以下から、「ssd1306I2c.zip」をダウンロードします。
https://www.dropbox.com/s/kg1p6fcxdf3scn3/ssd1306I2c.zip?dl=0

※2018/4/30追記
T2さんの要望で、曲名が短い場合、スクロールしないようにしてみました。 また、サンプリングレートの表記の"KHz"を"kHz"にしました。ただし、volumio自身が"KHz"を 返却しているのでvolumioとの表記方法と異なります。
https://www.dropbox.com/s/stj9fxrjo7l6z9z/ssd1306I2c_20180430_1.zip?dl=0

圧縮ファイルを展開します。WinSCPを起動し、volumio2.localに接続します。
ユーザ名「volumio」、パスワード「volumio」です。
展開したフォルダをvolumio2.localに転送します。

winscp.JPG


プラグインのインストール

ターミナルソフト(TeraTermなど)を起動し、volumio2.localに接続します。
volumioコマンドでプラグインをインストールします。

volumio@volumio2:~$ ls
ssd1306I2c
volumio@volumio2:~$ cd ssd1306I2c/
volumio@volumio2:~/ssd1306I2c$ volumio plugin install

This command will install the plugin on your device

Compressing the plugin
Plugin succesfully compressed
Progress: 10
Status :Downloading plugin
Progress: 30
Status :Creating folder on disk
Progress: 40
Status :Unpacking plugin
Progress: 50
Status :Checking for duplicate plugin
Progress: 60
Status :Copying Plugin into location
Progress: 70
Status :Installing dependencies
  :
  :
Status :Installing dependencies
Progress: 90
Status :Adding plugin to registry
Progress: 100
Status :Plugin Successfully Installed
Done!
volumio@volumio2:~/ssd1306I2c$

プラグインの起動

volumioにアクセスして、設定メニューからプラグインを選択します。
「インストール済みのプラグイン」タブを選択し、ssd1306_i2cプラグインをONにします。

プラグイン設定.JPG


自己責任でお願いします。以上です。

Rpi3.jpg

nice!(1)  コメント(6) 

Volumio2で音楽6 [Volumio]

有機ELディスプレイに曲名や歌手名を出すためにプログラムを書きましたが、時々表示されなくなってしまうことがありました。どうもpythonの変数の使い方が間違っていて、例外が出ていたようです。 ちょっと直してみました。
#!/usr/bin/python
# -*- coding: utf-8 -*-
 
import os
import sys
import smbus
import time
import signal
import threading

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_CMDMODE    = 0x00
	OLED_DATAMODE   = 0x40

	def __init__(self,target=0x3C):
		self.OLED_TARGET = target
		self.buffer = [0] * SSD1306.OLED_PAGE_COUNT * SSD1306.OLED_WIDTH
		self.zero   = [0] * 16
		self.__bus  = smbus.SMBus(1)

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

	def command(self,*cmd):
		self.__bus.write_i2c_block_data(self.OLED_TARGET,SSD1306.OLED_CMDMODE,list(cmd))

	def contrast(self,level):
		self.command(SSD1306.SETCONTRAST,level)

	def clear(self):
		self.command(SSD1306.COLUMNADDR, 0x00, 128-1, SSD1306.PAGEADDR, 0x00, 8-1)
		for i in range(0, len(self.buffer), 16):
			self.__bus.write_i2c_block_data(self.OLED_TARGET,SSD1306.OLED_DATAMODE,self.zero)

	def show(self):
		self.command(SSD1306.DISPLAYON)

	def display(self,pix):
 		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(SSD1306.COLUMNADDR, 0x00, 128-1, SSD1306.PAGEADDR, 0x00, 8-1)
		for i in range(0, len(self.buffer), 16):
			self.__bus.write_i2c_block_data(self.OLED_TARGET,SSD1306.OLED_DATAMODE,self.buffer[i:i+16])

class SSD(SSD1306):
	
	def __init__(self):
		super(SSD,self).__init__()
		
		self.jpfont = ImageFont.truetype('/usr/share/fonts/truetype/takao-gothic/TakaoPGothic.ttf',12, index=0, encoding="unic")
		self.image = Image.new('1', (SSD1306.OLED_WIDTH, SSD1306.OLED_HEIGHT),0)
		self.draw  = ImageDraw.Draw(self.image)

	def init(self):
		super(SSD,self).init()
		
	def set(self,album,title,artist,info):
		self.clean()
		self.display(album,title,artist,info)

	def clean(self):
		self.clear()
		self.draw.rectangle((0,0,SSD1306.OLED_WIDTH-1, SSD1306.OLED_HEIGHT-1), outline=0, fill=0)
	
	def max_length(self,text):
		length = len(text)
		for i in range(0,length-1,1):
			w = self.jpfont.getsize(text[0:i])[0]
			if w > 128:
				return i - 1
		return length

	def display(self,album,title,artist,info):
		self.draw.text( (0,0), album , font=self.jpfont, fill=1 )
		width = self.jpfont.getsize(title)[0]
		if width > 128 - 1:
			length = len(title)
			first_length = self.max_length(title)
			self.draw.text( (0,12), title[0:first_length], font=self.jpfont, fill=1 )
			self.draw.text( (0,24), title[first_length:length-1], font=self.jpfont, fill=1 )
		else:
			self.draw.text( (0,12), title, font=self.jpfont, fill=1 )

		self.draw.text( (0,36), artist, font=self.jpfont, fill=1 )

		self.draw.text( (0,50), info  , font=self.jpfont, fill=1 )

		super(SSD,self).display(self.image.load())

class socketio(object):
 
	def __init__(self):
		self.ssd = SSD()
		self.ssd.init()
		self.loopFlag = True

		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)
	
	def on_pushState(self,args):

		s = ''
		b = ''
		i = ''

		if 'samplerate' in args :
			s = args['samplerate']
			s = str(s)
			s.strip
		else:
			s = ''
			
		if 'bitdepth' in args:
			b = args['bitdepth']
			b = str(b)
			b.strip
		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

		print(args['album'].encode('utf-8'))
		print(args['title'].encode('utf-8'))
		print(args['artist'].encode('utf-8'))
		if s =='' and b == '':
			i = 'NaN'
		else:
			i = '%s | %s' % (s,b)
		print(i)

		self.ssd.set( args['album'],args['title'],args['artist'], i )
	

	def setRandom(self):
		self.socketIO.emit('setRandom',{'value' : 'true'})
		self.socketIO.emit('getState')

	def loop(self):
		while True:
			if self.loopFlag == False:
				break
			self.socketIO.wait(seconds=1)
		
	def stop(self):
		self.loopFlag = False
 
def daemonize():

	pid = os.fork()

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

	if pid == 0:

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

		signal.signal(signal.SIGINT, signal_handler)
		signal.signal(signal.SIGTERM, signal_handler)
		
		volumio = socketio()
		volumio.init()
		volumio.setRandom()
		volumio.loop()

if __name__ == '__main__':
	daemonize()


SSD1306へのアクセス部分と描画部分、通信部分を分離したので見通しが良くなったと思います。
nice!(0)  コメント(2) 

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

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

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