2020年4月17日金曜日

ラズベリーパイでradikoラジオをつくる: その10 AirPlayのジャケ写画像を表示


前回記事から日にちがたってしまいました。当時困ったことを思い出しながら書き残しておきます。shairport-sync-metadata-readerで取得した楽曲情報をLCD表示を行うには、メタデータ受信とLCD表示を並列処理する必要があり、まさかの"マルチスレッドプログラミング"となりました。別スレッドで受信したメタデータをPython 2.7Queueクラスに入れ、メインプログラムで逐次それぞ取り出す処理をしました。
スレッドの起動は次のような感じです。ひとつ問題があって、手動でPythonスクリプトを起動すると期待通り動作するのに、Linuxの自動起動に組み込んだらNGという現象がありました。どうやらshairport-syncよりメタデータ受信のスレッドが先行して起動してしまっていたらしく、shairport-syncプロセス起動を待って、スレッドを起動するようにすると期待通りの動作になりました。

import threading
if get_shairport_status() == 'active':
    if threading.active_count() == 1:
        thread_1 = threading.Thread(target=airplay.read)
        thread_1.start()

ジャケ写画像の表示は、PILpillow)ライブラリのおかげで簡素に書けました。他人のライブラリを拝借しているだけでなんですが、画像が表示されるとそれなりに達成感を感じられました。スクリプトを抜粋すると、つぎのような感じです。LCDへのデータ転送がとにかく遅いので、画像に限らず描画範囲を必要最小限にするよう心がけないと、すぐレスポンスが悪くなります。

path = coverart_path + "/" + coverart_filename
im = Image.open(path)
im = im.resize((140, 140))
im = im.rotate(90)
disp.buffer.paste(im, (75, 179))
disp.set_window(x0=75, y0=170, x1=220, y1=319)
disp.display()

あと、日本語表示をするためIPAフォントをインストールし、文字コード関連の記述を追記することになります。
font2gothic = ImageFont.truetype('ipag.ttf', 18, encoding='unic')
str = airplay.artist
str = trim_str(str.decode('utf-8'), 18)
draw_rotated_text(disp.buffer, str, (109, 2), 90, font2gothic, fill=col_orange)
使用した液晶パネルの都合で、デフォルトでは文字が半回転した右詰め表示になっていまいます。所定の表示幅に合わせて文字を左詰めするいは、余ったスペースを半角スペース埋めにしようとしたところ都合のよい関数がなくて、無理矢理つくりました。等幅フォントを前提としています。

# 全角は2文字として計数し、半角n個の文字列を切り出し
    def trim_str(self, text, n):
        bytes_count = 0
        str_count = 0
        for c in text:
            if unicodedata.east_asian_width(c) in 'FWA':
                bytes_count += 2
            else:
                bytes_count += 1
            str_count +=1
            if bytes_count > n:
                str_count -= 1
                break
        if (n - bytes_count) >0:
            return text[:str_count].ljust(n + str_count - bytes_count)
        else:
            return text[:str_count]

0 件のコメント:

コメントを投稿