multiprocessingメモ

import multiprocessing as mp
import multiprocessing.sharedctypes as mpshared


def worker(idx: int, queue: mp.Queue, shared_counter):
    while True:
        if not queue.get():
            break
        shared_counter[idx] += 1


def main():
    NUM_WORKERS = 64

    shared_counter = mpshared.RawArray('B', NUM_WORKERS)
    queues = [mp.Queue() for _ in range(NUM_WORKERS)]
    workers = [mp.Process(target=worker, args=(i, queues[i], shared_counter)) for i in range(NUM_WORKERS)]
    for w in workers:
        w.start()
    for _ in range(10):
        for q in queues:
            q.put(True)
    for q in queues:
        q.put(False)
    for w in workers:
        w.join()
    print([*shared_counter])


main()

将棋ウォーズで3rd Pary検討アプリによる棋譜取り込みが出来なくなったとされる件について

非技術者向け

  • 検討アプリで棋譜の取り込みが出来なくなったのは将棋ウォーズのアップデートに起因するが、検討アプリ側の修正で対処可能なはずなので寝て待つべし。
  • なお、そもそも将棋ウォーズからの棋譜の取り込みは、各検討アプリの独自解析により実現されていたものであり (グレーゾーン) 、それに対して将棋ウォーズが配慮する責務はないので、今回の件で将棋ウォーズを責めるのはお門違いである1

技術者向け

既存の取り込み機能を開発できるような人には、殊更な説明は不要と思われるが、一応簡単に。

  • 棋譜シェアページの刷新を行った様子。
    • Reactを使うようになっている。
    • ページへのアクセス制限は特に変わってなさそう。 (セッション不要でcurlでも取れる。)
  • それに伴い、従来の (おそらくテンプレートエンジンでレンダリングされていた) 棋譜文字列をJavaScriptに渡す部分のコードが無くなり、とある divdata-react-props 属性にJSONで渡すようになっている。
  • 雑な curl | grep はできなくなった一方、データについては構造化されて扱いやすくなった。

JSON部の取得サンプル:

import argparse
import urllib.request
import json
from html.parser import HTMLParser

args_parser = argparse.ArgumentParser()
args_parser.add_argument('url')
args = args_parser.parse_args()

req = urllib.request.Request(args.url)
with urllib.request.urlopen(req) as res:
    doc = str(res.read(), encoding='utf-8')


class RecordParser(HTMLParser):
    data = None

    def handle_starttag(self, tag, attrs):
        for attr in attrs:
            if attr[0] == 'data-react-props':
                self.data = attr[1]


record_parser = RecordParser()
record_parser.feed(doc)

if record_parser.data is None:
    exit(1)

print(record_parser.data)

  1. 零細サービスにおいて、公式APIを提供していない (欲しいが) にもかかわらず、3rd Partyでエコシステムを形成されるのは、スクレイピングの過負荷や販促物との競合という観点で迷惑である一方、その利便性によりアクティブユーザを確保できるという意味で有り難くもあったりする。今回、スクレイピングに対して非互換の実装変更が入ったが、後述のようにアクセス制限レベルは変わっていないことからして、全く配慮していないというわけではないと思われる (対局履歴ページのような制限強化も可能だったわけで) ので、まぁそんなに責めんであげたってください、と思う次第。

iPod Touch 5からXperia XZ1に移行した記録

長らく外出時の音楽再生にiPod Touch 5を使ってきたが、何度か起動しなくなり初期化を余儀なくされるなど、いよいよ限界が感じられてきたので、代替として、ひとまずメインスマホXperia XZ1に同居させてみることにした。

これまでは、スマホとイヤホンが有線でつながるのが嫌なのと、電池消費も懸念だったため、同居は検討してなかった。が、最近、値崩れしてきたELECOM製のBluetoothイヤホン LBT-HPC50EC を購入したこともあり、試してみても良いかなと言う気持ちになってきた。

さらにいえば、スマホ購入時に、64GBの外部SDカードも買って挿していたのだが、メインストレージもそこそこあるため、容量を余していたということもある。

そんなこんなで移行の記録を残しておく。

環境情報

Androidのメディア周りの仕様

iPod Touchは、細かい仕様はブラックボックスで、とにかくiTunes上でポチポチすれば良いだけだったが、Androidは果たして。

結論から言えば、ストレージルートの Music ディレクトリに音声ファイルを入れ、メディアスキャンをかければOKなのだが、このあたりの仕様、リテラシー低い層でも使えるようなレベルには仕上がってないなと正直思う。

ストレージのパス

パスについてadbで少し調査してみたところ、Xperia XZ1では、内部フラッシュメモリ/mnt/user/0/primary = /mnt/sdcard = /storage/self/primary になっていた。今回入れたいのは外部のフラッシュメモリ (外から自分で挿したもの) なわけだが、こちらはどうも /storage/0000-0000 にマウントされている様子 (このあたりのルールは未調査) 。ということで、ファイルシステム的には /storage/0000-0000/Music に音声ファイルを入れていくことになる。

もっとも、このあたりはMTPとかで転送する分にはあまり気にしなくても良い部分ではある。

ContentProviderを中心としたメディア取扱いの仕組み

Musicに入れれば良いと前述したが、より正確には、 "メディアストレージ" というシステムアプリがあり、それのスキャン対象になっていれば良い。

このあたりはAndroidContentProvider という、中央集権的なリソース管理機構に由来している。音楽再生を含め一般のアプリは、この仕組みに基づいてstorage上のファイルを参照している。メディアストレージは、ContentProviderの一角として、storage上のメディア情報を収集し、 "MediaStore" という領域に格納する役割を担っているシステムアプリのようだ。

そんなメディアストレージであるが、いつスキャンを行うのだろうか。答えは、システム起動時のようである。......あれ?つまり、言い換えれば、メディアデータを入れたら再起動をしないと認識されないということ!?正気か?

これ、個人的に一番どうなんだと思ってる部分で、この仕様、もしかするとPCのようにスマホも日々電源を切るみたいな習慣があった (本当にあったかは知らないが) 時の名残なのではないだろうか。

さて、さすがに再起動は面倒なので、いくつかワークアラウンドがあるようだ。例えば、メディアストレージアプリのキャッシュないしデータの削除をすれば良いらしい。がしかし、これはどう考えても全ファイルの再インデックス化になりそうな気がする。なので本筋は、MediaScannerConnection APIを利用する方向性だろう。MediaScannerConnectionはまさにメディアストレージのスキャンを要求するためのAPIで、スキャン先の指定もできるようだ。実は、このAPIを使えば、Music以外にファイルを置くことも可能だったのである。

APIが分かったのは良いとして、ではどうやってこれを叩くか。幸いにもPlay Storeに、まさに本目的のアプリが存在しているのでそれを使うのが良いだろう。私は安定の media.Re.Scan を使っている。とても便利。なお、ファイル転送モードでUSB接続されているとスキャンが異様に遅くなるので、スキャンの際はUSBを抜いておくのが吉。

ちなみに、MediaStoreにはプレイリストも保存できる (MediaStore.Audio.Playlists) 。MediaStoreをちゃんと使っているアプリ同士は、自然とアプリ間でプレイリストの共有ができてることになり、とても便利である。

Xperiaのオーディオ設定

Xperia固有 (walkman由来の機能?) と思われるが、オーディオ設定に色々なオプションがあったので軽くメモしておく。

  • DSEE HX
    • 謎のハイレゾ化機能。
    • 有線限定らしいのでスルー。
    • 有線でも10000円そこらのイヤホン・ヘッドホンでは、入れても意味ない気はする。
    • HD650持っているので、いつか比較してみるか。
  • ClearAudio+
    • 自動EQ。
    • EQはそんなに好きではないのでスルー。
  • サウンドエフェクト
    • イコライザとサラウンド系の謎機能。
    • ひとまずスルー。
  • ダイナミックノーマライザー
    • いわゆる「ラウドネスノーマライゼーション」か。
    • iOSのミュージックアプリにも似た機能はあるが、結構頓珍漢に調整されたりするので、正直あまり信用していないのであるが、試しに有効にしてみたところ、案外悪くはなかった。
    • 調べてみると、通常ReplayGain等は全曲通してゲインを変えるが、どうもこのダイナミックノーマライザという機能は、曲中にも動的にゲインを変えているらしい。
    • ひとまずはOFF。

Bluetoothイヤホンで音大きすぎ問題

これはAndroidに限らずだが、Bluetoothイヤホンで、最小音量でも音が大きすぎる問題というのがある。原因はイヤホンのアンプの問題とか色々あるらしい。

対策として、Androidでは、開発者オプションから、絶対音量機能を無効化するなどの方法があるが、個人的には、以下のようなアプリで最小音量をさらに調節するのが手軽だと思う。

ExtraVolumeSimple(音量微調整) - Google Play のアプリ

ExtraVolumeSimpleで必ずしも調節できるわけではない模様 (レビュー欄によると、端末再起動すれば適用されるという記載もあるが果たして) 。やはり絶対音量設定を変えるのが確実か。絶対音量を無効化すると、2重の調節が必要になるので、以下のような機器に応じて規定の音量を設定できるアプリが便利そう。

Bluetooth Volume Control - Google Play のアプリ

SDカードへの音声ファイル転送

Mediaフォルダに入れればOKというのは良いとして、ではどうやって入れるのが良いか、というお話。

Xperia Companion (旧Xperia Bridge for Mac)

Xperiaコンパニオン(Xperia Companion)|サポート | ソニーモバイル公式サイト

というSony純正のPCアプリがある。Xperia用のiTunes的なもの。音声ファイルの転送機能があり、iTunesのプレイリスト対応もしている様子。ITリテラシー低めの人はこれを使うのが一番無難だろうか。

私の場合は、以下の理由から、利用をやめた。

  • 転送が遅い
    • 転送自体は大したことはなさそうだが、独自のindexファイルを作っているのか、finalize処理が遅い (90%からが遅い感じ) 。
    • もしかしたら、前述のメディアスキャンを走らせていて、それが遅いのが原因かも知れない。 (ファイル転送モードでUSB接続しているので)
  • 音声ファイルの配置がフラット
    • iTunesでダウンロード済みのものを転送してみたところ、ファイルがフラットに配置された。それを良しとする流派はあるとは思うが、iTunesのダウンロード構成と同じ形 (<artist>/<album>) で整理したかったので、ミスマッチ。
    • SDカードに転送される以上、ファイルマネージャーで見ることも有るので、ある程度整理しておきたいし、どのようにファイルが配置されるのかを予測しづらいソフトは正直使いづらい。
  • iTunesのプレイリストは特に使っていないので、色々実装されている機能の恩恵にも預かれなさそうなこともあり。

Android File Transfer

Android File Transfer

シンプルにUSB接続経由 (MTP) でファイル転送するならこれが便利。

なお、Windowsの場合は、MTPに標準対応している (そもそもWindows由来のプロトコル) ので、おそらく普通にエクスプローラでOK。

機能がプリミティブなので使いやすいが、以下の理由で不採用。

  • ディレクトリレベルで再帰的に上書き保存できるのか未調査。
    • 普通にできるかもしれない。
    • アルバムごとに個別に転送するとかは現実的ではないので、やるならMusicディレクトリごと転送したいが、10GB近くあるので怖くて試してない。
  • D&Dのミスが怖い

adb-sync

GitHub - google/adb-sync

adbそのままでも良いが、そのラッパーコマンドとしてadb-syncというのがある。rsync風の仕様になっていて、dryrunもできるので安心。

ということで、以下のようなスクリプトを作成して、iTunes Storeで購入した楽曲をコマンド一発で同期できるようにした。

https://gist.github.com/s-shin/ff22c899187995c31926ac5c5c0f8309

sync_itunes_albums_to_android.sh # dryrun
sync_itunes_albums_to_android.sh -x

欠点は、完全にエンジニア向けの手段というぐらい。

その他

adb-syncのREADMEでも紹介されているが、MTPのFUSE実装がある。

GitHub - hanwen/go-mtpfs: Mount MTP devices over FUSE

これを使ってmountしておいて、あとはFinderでどうにかするなり、rsyncするなりはありかもしれない。

あとはそもそものそもそもとして、SDカードをPCに挿してファイルを入れれば良いという話もある。ただし抜き挿しの面倒さが強烈にネック。

プレイヤーアプリ

音声は入った。あとは再生するだけ......なのだが、アプリはどれが良いのだろうか。

ミュージック (Sony Mobile Communications)

ミュージック - Google Play のアプリ

XperiaプリインストールのSony製アプリ。今のところこれを使っている。

  • 良い点
    • デザインがそこそこかっこいい
    • ローカルの音楽再生特化。
  • 悪い点

Google Playミュージック

Google Playミュージック - Google Play のアプリ

Google製の音楽再生アプリ。

  • 良い点
    • デザインがそこそこかっこいい
  • 悪い点
    • Play Storeの定額ストリーミングサービスに関する機能が全面に出ているのが微妙
      • iOSのミュージックアプリも、Apple Music系の機能が入ってきて煩わしかったが、それと似たようなイメージ。
      • 一応ドロワーにある「ダウンロード済みのみ」を有効にすると、ストリーミング系機能のメニューがグレーアウトされるが......。

foobar2000

foobar2000 - Google Play のアプリ

その昔、Windowsでよく使っていたフリーソフトで、すごく懐かしい響きなのだが、Android版があるということで試してみた。

  • 良い点
    • ローカルの音楽再生特化。
    • 硬派な機能
      • Toolsにマニアックな設定が並んでいる。
      • ReplayGainとかもある。
  • 悪い点
    • 硬派すぎるデザイン。
    • 硬派な機能
      • 色々理解しないといけないので、諸刃の剣。
    • プレイリストが独自。

Pulsar

Pulsar 音楽プレーヤー - Google Play のアプリ

Sonyのミュージックと似た路線のアプリ。作り込みがなかなかで、現在試用中。

有料のPro版もある。違いは Pro Version を参照。

  • 良い点
    • デザインがそこそこかっこいい
      • 細部の作り込みもなかなか。
    • アーティスト・アルバムアーティストの切り替えが可能。
  • 悪い点
    • アルバムアートやアーティストの写真が結構適当
      • 不満があるなら自動取得機能を使わなければ良いという話ではある。
      • Sonyのミュージックも同様の機能があるようだが、試してないので、比較はできない。

所感

予想の範疇ではあったが、いい感じに使うには、それなりの理解が求められるなという感じ。