• プラグイン実験室

    @パパリウス さま

    プラグインの有効/無効を切り替えるプラグインを試作中です。

    これ、本当に良いですね。というか、自分で作ろうかなぁって考えていました:relaxed:
    あとはプラグインを1つのファイルにアーカイブ化して、インストール可能な仕組みがあれば
    ほぼ完成では無いでしょうか?
    (例えば、「プラグインを保存する専用フォルダを用意して、再起動時にそのフォルダにアーカイブファイルが存在すれば自動的に解凍→インストール」という方法ならばシェルスクリプトのみで対応出来ますよね。
    当然プラグインのアーカイブ時の書式は決めなければなりませんが。)

    あと、config.txtですがドライバへのオプション渡し(スレーブモード指定など)は、
    取りあえずはテキストボックスに手動で追記頂くことにしましょうか。
    (裏でinnomaker-hifi-dac-hatのスレッドを見ていて思い出しました。)

  • @sunatomo さん

    そうそう。
    私もパッケージマネージャ的な機能を盛り込めたらいいなぁと思っています:wink:


    手動で追記で問題ないと思います。
    ,slaveをつけたりするのは、実験するときだけですし:relieved:

    dtoverlayのオプションはカンマ区切りですね。
    いまの実装だとカンマがURLエンコードされて %2C で保存されちゃいますので、ympd_event.sh側で%2Cをカンマに逆変換すればいいですかね。:sweat:

  • こちらの記述を参考にして、ympd_event.shの方をもう少し変更してみました。
    ・設定ファイルから必要な設定を読み込む部分をparam関数として外出し
    ・上記のurldecode関数を実装しw指定の場合はパラメータをURLデコードした
     (私が動作確認した限りではカンマも正常に取得出来ています)
    ympd_event-.20191118.sh

  • @sunatomo さん

    ympd_event.shの修正、どうもありがとうございます。
    次のバージョンに取り込ませていただこうと思います。


    プラグイン実験室でsunatomoさんとやりとりさせていただき、久しぶりにympdのソースを見直す機会を得ました。

    むくむくとインスピレーションも湧いてきまして、この勢いでプラグイン機構の実装を全面的に見直そうと思っています。

    これまでのプラグインとの互換性は失いますが、

    • インストールやon/off切り替えはsshでの作業が不要
    • 作るのが楽
    • メンテナンスが楽
    • 配布が楽

    なものを目指したいと思います。

    ympdを弄るのはとても楽しいです:relieved:

  • 結局そこまで凝る必要は無かったのですが、やってしまいました。
    config.txt.png
    機能としては以下の通り。
    ・SupportのI2S DAC対応表を取り込みし、Javascriptの配列化しています。
     (将来的に対応カードが判明した場合は配列にリストを加えれば対応出来ます。
     また、配列をJSONファイルにすれば外部読み込み対応可能です)
    ・テキストボックスにカーネルドライバ名を直接入力もしくはリストから選択すると、
     当該ドライバ名と同ドライバで動作するデバイス名称が下のCardに表で表示されます。
     (dtoverlayにカンマ付きでオプションを指定していてもカード名で検索するので追従します。)
    あとはチップセットも対応表の配列には入っていますので、
    これまで分類して表示できればさらに良いかも(とりあえず、今回はここまでということで)。
    config.txt.20191120.html.zip

    <script>
      var i2sc=[
    {"d":"Sabreberry32","c":"ES9018Q2C","k":"sabreberry32"},
    {"d":"Audiophonics ES9018 DAC","c":"ES9018K2M","k":"i-sabre-k2m"},
    {"d":"Allo Boss DAC","c":"Burr Brown PCM5122","k":"allo-boss-dac-pcm512x-audio"},
    {"d":"Allo DigiOne","c":"Cirrus Logic WM8805","k":"allo-digione"},
    {"d":"Allo MiniBoss DAC","c":"Burr Brown PCM5122","k":"allo-boss-dac-pcm512x-audio"},
    {"d":"Allo Piano 2.1 Hi-Fi DAC","c":"Burr Brown PCM5142","k":"allo-piano-dac-plus-pcm512x-audio"},
    {"d":"Allo Piano Hi-Fi DAC","c":"Burr Brown PCM5122","k":"allo-piano-dac-pcm512x-audio"},
    {"d":"Audiophonics ES9023 DAC","c":"ESS Sabre ES9023","k":"hifiberry-dac"},
    {"d":"Audiophonics ES9023 DAC LTE","c":"ESS Sabre ES9023","k":"hifiberry-dac"},
    {"d":"Audiophonics ES9023 DAC TXCO","c":"ESS Sabre ES9023","k":"hifiberry-dac"},
    {"d":"Audiophonics ES9028 DAC","c":"ESS Sabre ES9028Q2M","k":"rpi-dac"},
    {"d":"Audiophonics PCM5102 DAC","c":"Burr Brown PCM5102A","k":"hifiberry-dac"},
    {"d":"Audiophonics PCM5122 DAC","c":"Burr Brown PCM5122","k":"hifiberry-dacplus"},
    {"d":"Audiophonics TDA1387 DAC","c":"Philips TDA1387","k":"hifiberry-dac"},
    {"d":"Buffalo I","c":"ESS Sabre ES9008","k":"rpi-dac"},
    {"d":"Buffalo II/IIIse","c":"ESS Sabre ES9018","k":"rpi-dac"},
    {"d":"DDDAC1794 NOS","c":"Burr Brown PCM1794","k":"rpi-dac"},
    {"d":"DIAL-DAC","c":"Burr Brown PCM1793","k":"rpi-dac"},
    {"d":"DIYINHK ES9023 DAC","c":"ESS Sabre ES9023","k":"hifiberry-dac"},
    {"d":"Denafrips Pontus R2R DAC (I2S)","c":"Altera MAX II CPLD","k":"rpi-dac"},
    {"d":"Dion Audio LOCO","c":"PCM5242 DAC","k":"dionaudio-loco"},
    {"d":"Durio Sound PRO","c":"Burr Brown PCM5102A","k":"hifiberry-dac"},
    {"d":"G2 Labs BerryNOS","c":"Philips TDA1543","k":"hifiberry-dac"},
    {"d":"G2 Labs BerryNOS","c":" RedPhilips TDA1543","k":"hifiberry-dac"},
    {"d":"HIFI DAC","c":"Burr Brown PCM5102A","k":"hifiberry-dac"},
    {"d":"HIFI DAC+","c":"Burr Brown PCM5122","k":"hifiberry-dacplus"},
    {"d":"HIFI Digi","c":"Wolfson WM8804G","k":"hifiberry-digi"},
    {"d":"HIFI Digi+","c":"Wolfson WM8804G","k":"hifiberry-digi"},
    {"d":"HiFiBerry Amp(Amp+)","c":"Burr Brown TAS5713","k":"hifiberry-amp"},
    {"d":"HiFiBerry DAC","c":"Burr Brown PCM5102A","k":"hifiberry-dac"},
    {"d":"HiFiBerry DAC+","c":"Burr Brown PCM5122","k":"hifiberry-dacplus"},
    {"d":"HiFiBerry DAC+ Light","c":"ESS Sabre ES9023","k":"hifiberry-dac"},
    {"d":"HiFiBerry DAC+ Pro","c":"Burr Brown PCM5122","k":"hifiberry-dacplus"},
    {"d":"HiFiBerry Digi(Digi+)","c":"Cirrus Logic WM8804","k":"hifiberry-digi"},
    {"d":"HiFiBerry Digi+ Pro","c":"Cirrus Logic WM8804","k":"hifiberry-digi-pro"},
    {"d":"Hifimediy ES9023","c":"ESS Sabre ES9023","k":"hifiberry-dac"},
    {"d":"IQaudIO Pi-AMP+","c":"Burr Brown TPA3118","k":"iqaudio-dacplus"},
    {"d":"IQaudIO Pi-DAC","c":"Burr Brown PCM5122","k":"iqaudio-dac"},
    {"d":"IQaudIO Pi-DAC PRO","c":"Burr Brown PCM5242","k":"iqaudio-dacplus"},
    {"d":"IQaudIO Pi-DAC+","c":"Burr Brown PCM5122","k":"iqaudio-dacplus"},
    {"d":"IQaudIO Pi-DACZero","c":"Burr Brown PCM5122","k":"iqaudio-dacplus"},
    {"d":"IQaudIO Pi-Digi+","c":"Wolfson WM8804","k":"iqaudio-digi-wm8804-audio"},
    {"d":"IQaudIO Pi-DigiAMP+","c":"Burr Brown TAS5756","k":"iqaudio-dacplus"},
    {"d":"IanFIFO II","c":"Altera Max II CPLD","k":"hifiberry-dac"},
    {"d":"JustBoom AMP HAT(Zero)","c":"Burr Brown TAS5756","k":"justboom-dac"},
    {"d":"JustBoom DAC HAT(Zero)","c":"Burr Brown PCM5122 (PCM5121)","k":"justboom-dac"},
    {"d":"JustBoom Digi HAT(Zero)","c":"Wolfson WM8804G","k":"justboom-digi"},
    {"d":"Lucid Labs Raspberry Pi DAC","c":"Burr Brown PCM5102A","k":"hifiberry-dac"},
    {"d":"Mamboberry HiFi DAC+","c":"ESS Sabre ES9032","k":"hifiberry-dac"},
    {"d":"Mamboberry LS DAC+","c":"ESS Sabre ES9023p","k":"hifiberry-dac"},
    {"d":"Pi2Design 503HTA Hybrid Tube Amp","c":"Burr Brown PCM5102A","k":"hifiberry-dac"},
    {"d":"Pimoroni pHAT DAC","c":"Burr Brown PCM5102A","k":"hifiberry-dac"},
    {"d":"PlainAMP","c":"Burr Brown TAS5756","k":"iqaudio-dacplus"},
    {"d":"PlainDAC","c":"Burr Brown PCM5100","k":"hifiberry-dac"},
    {"d":"PlainDAC+","c":"Burr Brown PCM5121","k":"hifiberry-dacplus"},
    {"d":"PlainDSP","c":"Burr Brown PCM5121","k":"hifiberry-dacplus"},
    {"d":"RPi-DAC","c":"Burr Brown PCM1794A","k":"rpi-dac"},
    {"d":"RaspyPlay4","c":"Burr Brown PCM5122","k":"iqaudio-dac"},
    {"d":"Red Rocks Audio DigiDAC1","c":"Wolfson WM8742 (DAC) WM8804 (S/PDIF)","k":"rra-digidac1-wm8741-audio"},
    {"d":"SB32+PRO DoP","c":"ESS Sabre ES9218P","k":"hifiberry-dacplus"},
    {"d":"Soekris DAM1021/1121 (I2S)","c":"FPGA based","k":"rpi-dac"},
    {"d":"Suptronics x400","c":"Burr Brown PCM5122","k":"iqaudio-dacplus"},
    {"d":"Terra-BerryDAC 2","c":"AK4490EQ","k":"hifiberry-dac"}
    ];
    
      var ary1 = [];
      var ary2 = [];
      for (var i = 0, lmt = i2sc.length; i < lmt; i++) {
        ary1.push(i2sc[i].k);
      }
      ary2 = removeArrayDuplicates(ary1);
    
      var scd = document.getElementById('scard');
      for (var i = 0, lmt = ary2.length; i < lmt; i++) {
        var opt = document.createElement("option");
        opt.value = ary2[i];
        scd.appendChild(opt);
        opt = null;
      }
    
      $('#i2s').attr('list', 'scard');
      change();
    
      function removeArrayDuplicates(array) {
        var exist = {}, result = [];
    
        for (var i = 0, l = array.length; i < l; i++) {
          var tmp = array[i];
        
          if (!exist[tmp]) {
            exist[tmp] = true;
            result.push(tmp);
          }
        }
    
        return result;
      }
    
      function change() {
        var flg = 0;
        $('#k').text(' ');
        $('#d').text(' ');
        var sample = $('#i2s').val().split(',');
        for(var i = 0, lmt = i2sc.length; i < lmt; i++) {
          if (sample[0] === i2sc[i].k) {
            if(flg === 0) {
              $('#k').text(i2sc[i].k);
              $('#d').text(i2sc[i].d);
            } else {
              $('#d').text($('#d').text() + ',' + i2sc[i].d);
            }
            flg++;
          }
        }
      }
    </script>
    <form>
      <label class="control-label">dtoverlay</label><br/>
      <input id="i2s" class="config" type="text" uri="/boot/config.txt" key="dtoverlay" style="width:100%;" autocomplete="off" onfocut="change();" onkeyup="change();"/><br/>
      <datalist id="scard">
      </datalist>
    </form>
    <br/>
    <table style="width:100%" border="1">
    <tr><th>Driver</th><th>Card</th></tr>
    <tr><td id="k"> </td><td id="d"> </td></tr>
    </table>
    
  • ラジオストリームをRADIOに追加するプラグイン(V.0.9.3)
    これは以前に掲載したインターネットラジオURLをRADIOフォルダに保存するためのプラグインをv.0.9.3に対応させたものです。
    保存先は/home/pi/plugins/14-add_radioを想定しています。
    SAVE_RADIO.png

    app.json

    {
    	"menu": "SAVE RADIO",
    	"icon": "settings_input_antenna",
    	"note": "add new radio station to RADIO folder"
    }
    

    form.html

    <script type="text/javascript">
      $('#nm')
        .focusout(function(f) {
          $(this).val(ku($(this).val()));
        });
      function ku(v) {
        return  v.replace(/ /g, '_');
      }
    </script>
    <div style="padding:20px;">
      <p>Save Radio Stram URL to RADIO Folder</p>
      <label class="control-label">Radio Station Name</label><br/>
      <input type="text" id="nm" class="run" /><br/>
      <label class="control-label">stream URL</label><br/>
      <input type="text" id="url" class="run" />
    *white space (" ") in "Radio Station Name" string has been replaced to "_"
    </div>
    
    

    run.sh

    #!/bin/bash
    
    ttl=$1
    url=$2
    
    out=/var/lib/mpd/music/RADIO/"${ttl}".pls
    
    /usr/local/sbin/rmtrw.sh 2
    
    if [ -n "$ttl" ] && [ -n "$url" ]; then
      if [ -e "${out}" ]; then
        exit 1
      fi
    
      echo "[playlist]" > "${out}"
      echo "NumberOfEntries=1" >> "${out}"
      echo "File1=${url}" >> "${out}"
      echo "Title1=${ttl}" >> "${out}"
      echo "Length1=-1" >> "${out}"
      echo "Version=2" >> "${out}"
    
      chown pi.pi "${out}"
      mpc -q update RADIO
      sync
    fi
    
    /usr/local/sbin/rmtro.sh 2
    
    exit $retval
    

    インストール方法
    1./home/pi/pluginsに14-add_radioフォルダを作って下さい。
    2.app.json・form.html・run.shをソースコードから複写して下さい。
     (SSHのシェル上でnanoエディタで各ファイルを新規作成で開き、そのままコピペするだけでOK)
    3./home/pi/plugins/attachフォルダにてln -s ../14-add_radio .と入力して下さい。

    使い方
    プラグインの使い方は簡単
    RadioStationNameに保存したいラジオ局の名称を、stream URLにはそのラジオ局のURLを入れてOKを押せば、当該ラジオ局のplsファイルが/var/lib/mpd/music/RADIOに作られるという仕組みです。
    stream URLが正しいものかは確認していませんので事前にADD STREAMで確認して下さい。
    (ADD STREAMは入力したURLをキューに追加します。これで再生出来ればOK)

    ちょっと解説(新しいrun.shへパラメータを渡す際の注意事項)
    v.0.9.3以降で対応するform.htmlですが、class="run"でinput要素を渡す際は
    必ず半角スペースを他のキャラクターで置き換えて下さい
    (ファイル中のJavaScriptは「Radio Station Name」に入力された文字列内の" "を"_"に置き換えするものです)。
    これは現状のWebインターフェース(ympd)ではブラウザのフォーム値をラズパイにパラメータとして渡す際の各パラメータ区切りとして半角スペースを使用しているためです。
    (パラメータ内部に半角スペースが存在するとrun.shが誤解してしまうため)
    どうしても半角スペースを含むパラメータをrun.shに渡したい場合は以下の2つの方法で実現出来ます。
     ①半角スペースを他のキャラクターに置き換えし、run.shの内部処理でそれを戻す
     ②各パラメータ間を別なキャラクターで予め接続した1つの文字列として渡し、run.shの
      内部処理でパラメータを分割する

  • @sunatomo さん

    プラグインの投稿、どうもありがとうございます。

    半角スペースの件、ご指摘ありがとうございます。
    個々のプラグインで対策していただくのは不便ですので、ympd本体側を修正したいと思います。

    v0.9.3からプラグイン作成ルールを刷新しましたが、作りやすさ・メンテナンスのしやすさなど、気付いた点があればおっしゃってください。

  • @パパリウス さま
    半角スペースの件、本体で対応頂くとのことで、お手数おかけします。
    (てっきりそういうポリシーかなぁとも考えていました。:relieved: )

    使い勝手に関してですが、2つほど提案があります。
    1.プラグインフォルダ名の取扱について
     今回から2ケタ数字-アルファベットで指定となりましたが、
     この2ケタ数字は何からのルールを制定する予定はありますか?
     (数字についてはプラグインの並び順と、グループ分けの両方の意味が
     あるように見受けられますが、如何でしょうか?)

    2.プラグイン製作のためのデザインポリシーについて
     プラグインはsymponic-mpdの外観上で唯一ユーザが自由に操作できる部分になりますが、
     パパリウスさまが考えるデザインポリシー(思想)について提示してもよいかと思います。
     私なりに私案(たたき台)作ってみました。

    -------- ここから -------
     プラグインを自作し、公開する際はデザインの統一感を持たせるため以下のルールを守って下さい。
     (個人的に利用する分については特に制限はありません。)
     なお、公式イメージにフォーラムなどでご提供頂いたプラグインを採用した際には、
     デザインや機能の修正を行うことがあることについてご了承下さい。

     ・各入力項目のタイトルにはlabelタグを、class属性でcontrol-labelを使用して下さい。
     ・inputタグにはclass属性でrunもしくはconfigを指定して下さい。
     ・各入力項目の解説文が必要な場合は英文で可能な限り簡潔(1行)に記載して下さい。

     なお、プラグイン開発に必要なWebUIの技術的なバックグラウンドは以下のとおりです。
     ・スタイルシートとしてbootstrap(v.3.1)を使用しています。
     ・JavaScriptのライブラリとしてjquery(v.1.10.2)を使用しています。
    -------- ここまで -------
    もしポリシーを記載するのはちょっと他の人の意欲が削がれるのではということでしたら、
    form.htmlのテンプレートがあるだけでも良いかもしれません。

  • @sunatomo さん

    ご意見ありがとうございます。

    プラグイン作成者からすると、プラグインフォルダ名をどうするか、ちょっと迷いますよね。

    原則は、

    • プラグインフォルダ名は、プラグイン作成者が決める
    • シンボリックリンク名は、利用者が決める

    というルールにしたいと思います。

    SDイメージに同梱しているプラグインは先頭に2ケタの数字をつけていますが、これに拘る必要はありません。
    プラグイン作成者が、自分の好きなルールで名称を決定してくださって結構です。

    メニューの並び順は、シンボリックリンク名を変えることで自分の好きなように並べ替えることができます。
    インストール後、利用者自身で好きなようにリネームして並べ替えしていただければと思います。


    デザインポリシーを決める代わりに、お手本となるようなプラグインを作っていければいいかなと思います。

    新規にプラグインを作る時、既存のプラグインをフォルダごとまるっとコピーして、それを改変していくと楽です。

    作りやデザインが優れたプラグインが改変のベースとして使われ、より洗練されていく、、、というのが望ましいかなと思います。


    プラグインの検索・インストールを行うプラグインを作りたいなと思っています。

    プラグイン配布ページをスクレイピングしてプラグインをリストアップし、ダウンロードとインストールができるような
    機能です。

    (プラグイン作成者は、プラグインフォルダを圧縮してフォーラムにアップします)

  • SOUND CARD設定用のプラグインをもう少しだけ頑張ってみる
     ここの過去ログ見るとお分かりでしょうが、v.0.9.3では私がお手伝いしたサウンドカード設定のプラグインを公式で拡張して採用頂いております。
     ただ、サポートで動作確認の素晴らしい表があるのだから、これを使って選択できるようにしたい(そんなに頻繁に変更するものではないですが)。
    という訳で、私なりの方法で実装したものです。
    01-soundcard.zip
    01-soundcard.png
    /home/pi/plugins/01-soundcardを改変するため、元のファイルはバックアップしておいて下さい。

    cd /home/pi/plugins/01-soundcard
    cp form.html form.html.org
    

    sndcard.json

    [
    {"d":"Audiophonics ES9018 DAC","c":"ES9018K2M","k":"i-sabre-k2m"},
    {"d":"Allo Boss DAC","c":"Burr Brown PCM5122","k":"allo-boss-dac-pcm512x-audio"},
    {"d":"Allo DigiOne","c":"Cirrus Logic WM8805","k":"allo-digione"},
    {"d":"Allo MiniBoss DAC","c":"Burr Brown PCM5122","k":"allo-boss-dac-pcm512x-audio"},
    {"d":"Allo Piano 2.1 Hi-Fi DAC","c":"Burr Brown PCM5142","k":"allo-piano-dac-plus-pcm512x-audio"},
    {"d":"Allo Piano Hi-Fi DAC","c":"Burr Brown PCM5122","k":"allo-piano-dac-pcm512x-audio"},
    {"d":"Audiophonics ES9023 DAC","c":"ESS Sabre ES9023","k":"hifiberry-dac"},
    {"d":"Audiophonics ES9023 DAC LTE","c":"ESS Sabre ES9023","k":"hifiberry-dac"},
    {"d":"Audiophonics ES9023 DAC TXCO","c":"ESS Sabre ES9023","k":"hifiberry-dac"},
    {"d":"Audiophonics ES9028 DAC","c":"ESS Sabre ES9028Q2M","k":"rpi-dac"},
    {"d":"Audiophonics PCM5102 DAC","c":"Burr Brown PCM5102A","k":"hifiberry-dac"},
    {"d":"Audiophonics PCM5122 DAC","c":"Burr Brown PCM5122","k":"hifiberry-dacplus"},
    {"d":"Audiophonics TDA1387 DAC","c":"Philips TDA1387","k":"hifiberry-dac"},
    {"d":"Buffalo I","c":"ESS Sabre ES9008","k":"rpi-dac"},
    {"d":"Buffalo II/IIIse","c":"ESS Sabre ES9018","k":"rpi-dac"},
    {"d":"DDDAC1794 NOS","c":"Burr Brown PCM1794","k":"rpi-dac"},
    {"d":"DIAL-DAC","c":"Burr Brown PCM1793","k":"rpi-dac"},
    {"d":"DIYINHK ES9023 DAC","c":"ESS Sabre ES9023","k":"hifiberry-dac"},
    {"d":"Denafrips Pontus R2R DAC (I2S)","c":"Altera MAX II CPLD","k":"rpi-dac"},
    {"d":"Dion Audio LOCO","c":"PCM5242 DAC","k":"dionaudio-loco"},
    {"d":"Durio Sound PRO","c":"Burr Brown PCM5102A","k":"hifiberry-dac"},
    {"d":"G2 Labs BerryNOS","c":"Philips TDA1543","k":"hifiberry-dac"},
    {"d":"G2 Labs BerryNOS","c":" RedPhilips TDA1543","k":"hifiberry-dac"},
    {"d":"HIFI DAC","c":"Burr Brown PCM5102A","k":"hifiberry-dac"},
    {"d":"HIFI DAC+","c":"Burr Brown PCM5122","k":"hifiberry-dacplus"},
    {"d":"HIFI Digi","c":"Wolfson WM8804G","k":"hifiberry-digi"},
    {"d":"HIFI Digi+","c":"Wolfson WM8804G","k":"hifiberry-digi"},
    {"d":"HiFiBerry Amp(Amp+)","c":"Burr Brown TAS5713","k":"hifiberry-amp"},
    {"d":"HiFiBerry DAC","c":"Burr Brown PCM5102A","k":"hifiberry-dac"},
    {"d":"HiFiBerry DAC+","c":"Burr Brown PCM5122","k":"hifiberry-dacplus"},
    {"d":"HiFiBerry DAC+ Light","c":"ESS Sabre ES9023","k":"hifiberry-dac"},
    {"d":"HiFiBerry DAC+ Pro","c":"Burr Brown PCM5122","k":"hifiberry-dacplus"},
    {"d":"HiFiBerry Digi(Digi+)","c":"Cirrus Logic WM8804","k":"hifiberry-digi"},
    {"d":"HiFiBerry Digi+ Pro","c":"Cirrus Logic WM8804","k":"hifiberry-digi-pro"},
    {"d":"Hifimediy ES9023","c":"ESS Sabre ES9023","k":"hifiberry-dac"},
    {"d":"IQaudIO Pi-AMP+","c":"Burr Brown TPA3118","k":"iqaudio-dacplus"},
    {"d":"IQaudIO Pi-DAC","c":"Burr Brown PCM5122","k":"iqaudio-dac"},
    {"d":"IQaudIO Pi-DAC PRO","c":"Burr Brown PCM5242","k":"iqaudio-dacplus"},
    {"d":"IQaudIO Pi-DAC+","c":"Burr Brown PCM5122","k":"iqaudio-dacplus"},
    {"d":"IQaudIO Pi-DACZero","c":"Burr Brown PCM5122","k":"iqaudio-dacplus"},
    {"d":"IQaudIO Pi-Digi+","c":"Wolfson WM8804","k":"iqaudio-digi-wm8804-audio"},
    {"d":"IQaudIO Pi-DigiAMP+","c":"Burr Brown TAS5756","k":"iqaudio-dacplus"},
    {"d":"IanFIFO II","c":"Altera Max II CPLD","k":"hifiberry-dac"},
    {"d":"JustBoom AMP HAT(Zero)","c":"Burr Brown TAS5756","k":"justboom-dac"},
    {"d":"JustBoom DAC HAT(Zero)","c":"Burr Brown PCM5122 (PCM5121)","k":"justboom-dac"},
    {"d":"JustBoom Digi HAT(Zero)","c":"Wolfson WM8804G","k":"justboom-digi"},
    {"d":"Lucid Labs Raspberry Pi DAC","c":"Burr Brown PCM5102A","k":"hifiberry-dac"},
    {"d":"Mamboberry HiFi DAC+","c":"ESS Sabre ES9032","k":"hifiberry-dac"},
    {"d":"Mamboberry LS DAC+","c":"ESS Sabre ES9023p","k":"hifiberry-dac"},
    {"d":"Pi2Design 503HTA Hybrid Tube Amp","c":"Burr Brown PCM5102A","k":"hifiberry-dac"},
    {"d":"Pimoroni pHAT DAC","c":"Burr Brown PCM5102A","k":"hifiberry-dac"},
    {"d":"PlainAMP","c":"Burr Brown TAS5756","k":"iqaudio-dacplus"},
    {"d":"PlainDAC","c":"Burr Brown PCM5100","k":"hifiberry-dac"},
    {"d":"PlainDAC+","c":"Burr Brown PCM5121","k":"hifiberry-dacplus"},
    {"d":"PlainDSP","c":"Burr Brown PCM5121","k":"hifiberry-dacplus"},
    {"d":"RPi-DAC","c":"Burr Brown PCM1794A","k":"rpi-dac"},
    {"d":"RaspyPlay4","c":"Burr Brown PCM5122","k":"iqaudio-dac"},
    {"d":"Red Rocks Audio DigiDAC1","c":"Wolfson WM8742 (DAC) WM8804 (S/PDIF)","k":"rra-digidac1-wm8741-audio"},
    {"d":"Sabreberry32","c":"ES9018Q2C","k":"sabreberry32"},
    {"d":"SB32+PRO DoP","c":"ESS Sabre ES9218P","k":"hifiberry-dacplus"},
    {"d":"Soekris DAM1021/1121 (I2S)","c":"FPGA based","k":"rpi-dac"},
    {"d":"Suptronics x400","c":"Burr Brown PCM5122","k":"iqaudio-dacplus"},
    {"d":"Terra-BerryDAC 2","c":"AK4490EQ","k":"hifiberry-dac"}
    ]
    

    対応表をJSON化したものです。dはサウンドカード名、kはdtoverlayを示します(未使用ですがcにサウンドチップを格納しています。)。
    将来的に新しいデバイスが増えた、対応カードが見つかった場合はこのファイルを拡張すれば良いわけです。

    form.html

    <script>
    $(function() {
      var i2sc;
      $.getJSON('/plugins/01-soundcard/sndcard.json' , function(data) {
        i2sc = data;
        init1();
      });
      $('input[name="sel"]').change(function() {
        if ($(this).val() === "1") {
          init1();
        } else {
          init2();
        }
      });
      function removeArrayDuplicates(ary) {
        var ext = {}, res = [];
        for (var i = 0, l = ary.length; i < l; i++) {
          var tmp = ary[i];
          if (!ext[tmp]) {
            ext[tmp] = true;
            res.push(tmp);
          }
        }
        return res;
      }
      function init1() {
        $("#d").val("");
        $("#scard option").remove();
        $("#device option").remove();
        var ary1 = [], ary2 = [];
        for (var i = 0, l = i2sc.length; i < l; i++) {
          ary1.push(i2sc[i].k);
        }
        ary2 = removeArrayDuplicates(ary1);
        ary2.sort();
        ary1 = null;
        for (var i = 0, l = ary2.length; i < l; i++) {
          $("#scard").append($("<option>").val(ary2[i]));
        }
        $("#k").attr("list", "scard");
        change();
        $("#sep").text("->");
        $("#dl").text("(Compat. Card)");
        $("#d").keyup(function() {
          change();
        });
        $("#d").focus(function() {
          change();
        });
        $("#k").off("keyup");
        $("#k").off("focus");
      }
      function init2() {
        $("#k").val("");
        $("#scard option").remove();
        $("#device option").remove();
        for (var i = 0, l = i2sc.length; i < l; i++) {
          $("#device").append($("<option>").val(i2sc[i].d));
        }
        $("#sep").text("<-");
        $("#dl").text("SoundCard");
        $("#d").off("keyup");
        $("#d").off("focus");
        $("#k").keyup(function() {
          change2();
        });
        $("#k").focus(function() {
          change2();
        });
      }
      function change() {
        $("#device option").remove();
        var spl = $("#k").val().split(",");
        for (var i = 0, l = i2sc.length; i < l; i++) {
          if (spl[0] === i2sc[i].k || $("#k").val === "") {
            $("#device").append($("<option>").val(i2sc[i].d));
          }
        }
        $("#d").attr("list", "device");
      }
      function change2() {
        $("#scard option").remove();
        for (var i = 0, l = i2sc.length; i < l; i++) {
          if ($("#d").val() === i2sc[i].d) {
            $("#scard").append($("<option>").val(i2sc[i].k));
            $("#k").val(i2sc[i].k);
            break;
          }
        }
        $("#k").attr("list", "scard");
      }
    });
    </script>
    <datalist id="scard">
    </datalist>
    
    <datalist id="device">
    </datalist>
    
    <datalist id="format_list">
        <option value="S16">
        <option value="S32">
    </datalist>
    
    <div style="padding:0px 20px 10px 20px;">
      <h3>config.txt</h3>
      <input type="radio" name="sel" value="1" checked>dtoverlay -> SoundCard (Check)<br/>
      <input type="radio" name="sel" value="2">dtoverlay <- Soundard
      <table style="width:100%;"><tr><td style="width:48%;">
      <label class="control-label">dtoverlay</label>
      <input type="text" id="k" class="config" uri="/boot/config.txt" key="dtoverlay" list="scard" />
      </td><td id="sep" style="width:4%;text-align:center;vertical-alighn:middle;"><label class="control-label">-></label></td><td style="width:48%;">
      <label id="dl" class="control-label">(Compat. Card)</label>
      <input type="text" id="d" class="config" list="device">
      </td></tr></table>
      <h3>environment</h3>
      <label class="control-label "><small>DEFAULT_SAMPLE_FORMAT</small></label>
      <input type="text" class="config" uri="/etc/environment" key="DEFAULT_SAMPLE_FORMAT" list="format_list" />
      <label class="control-label"><small>GPIO_DRIVE_STRENGTH (2~16)</small></label>
      <input type="text" class="config" uri="/etc/environment" key="GPIO_DRIVE_STRENGTH" />
      <br />
      <p>Restart is required after changing the setting.</p>
    </div>
    

    使い方
     dtoverlayの記載部分のテキストボックスが左右2個あります。
    左がdtoverlayをそのまま記載する場所(従来通りここの値が/boot/config.txtに保存されます)、
    右が当該dtoverlayが対応するサウンドカード名が表示されるようになっています。

    ラジオボタンで機能を切り替えできるように設計しました。
    ・dtoverlay -> SoundCard (Check)(デフォルトでON)
     現在指定されているdtoverlayで対応するサウンドカード名が右のテキストボックスに表示されます。設定があっているかの確認用として使用してみて下さい。
    ・dtoverlay <- Soundard
     このチェックボックスを選択すると、dtoverlayの文字列が消され、右のテキストボックスから
    サウンドカード名を選択すると左のテキストボックスに対応するdtoverlayドライバ文字列が表示されます(一回クリックして表示させて下さい)
    ↑
    ちょっとわかりにくいですが、触ってみれば何をしているかお分かりになるかと思います。

    なお、「こんな構成ならもっと分かりやすいのでは?」というご提案ありましたら、お教え下さい。