NetBSD上のFirefoxで、KeePassXCと連携させてみる

この記事は、NetBSD Advent Calendar 2023の17日目の記事です。

KeePassXCとは

KeePassXCは、クロスプラットフォームなパスワード管理ソフトウェアです。 FreeBSD Workshopで、重村さんが紹介されていて、 それを聞いて詳しい機能を知ることができました。

パスワードをNetBSDデスクトップ環境で入力するのは、sudoやsuを使う時か、ウェブブラウザーでウェブサイトにログインする時が主だと思います。 sudoやsuで入力するパスワードの入力を補助してもらう必要はないので、入力補助が欲しいのはウェブブラウザー上のことになります。 KeePassXCは、Firefoxの拡張機能を経由して、KeePassXCアプリケーションと通信して、ユーザーIDやパスワードの情報を取得し、 ウェブフォームやBasic認証のポップアップに入力してくれる機能があります。

Firefoxにもパスワード管理機能はありますが、あくまでユーザーIDとパスワードの組み合わせを入力補助してくれる以上のことはできません。 3箇所以上に自動入力して欲しい時には、KeePassXCは役立ちそうです。

KeePassXCのインストール

NetBSDでは、pkgsrc/security/keepassxcとしてKeePassXCをインストールすることができます。 以下のように実行すれば良いでしょう。

# cd /usr/pkgsrc/security/keepassxc
# make install

pkgsrc/www/firefoxからインストールしてMozilla FirefoxでKeePassXC-Browser という拡張機能をインストールすれば、設定を開始する準備ができました。

KeePassXCの起動

KeePassXCの使い方は、KeePassXC: Getting Started Guideを読んでもらうのが一番です。 まずはパスワードデータベースを作成し、使う認証情報を登録してください。例えば下図のような感じです。

更に、設定画面からbrowser integrationを有効にし、Firefoxで使うように設定します。下図のような感じです。

KeePassXC-Browserの初期設定

まず、keepassxcコマンドでKeePassXCを起動させましょう。パスワードデータベースもロックを解除しておきます。 その上で、 ツールバーのジグソーパズルのピースのアイコンから、KeePassXC-Browserをクリックすると、最初にKeePassXCアプリケーションとの連携を設定する表示になります。 ここで、適当な識別子を入力して、Save and allow accessボタンを押してください。 これでKeePassXCアプリケーションとKeePassXC-Browser拡張機能がつながります。

KeePassXC-Browserを使ってみる

その上で、登録したウェブサイトを開くと、KeePassXCのアイコンが入力フォームに表示されます。同時に、どの情報を入力するかの選択のできるポップアップウィンドウが 表示されます。 ここで、利用したいものを選択すれば、自動的に認証情報が入力されます。

NetBSDで最新のMozcを使う 2

この記事は、NetBSD Advent Calendar 2023の20日目の記事です。

昨日に続き、Mozc 2.29.5268.102をNetBSD/amd64で使うまでの話を書きたいと思います。 ここで、NetBSD/amd64と書きました。 昨日は書き忘れてしまいましたが、Bazelは64ビットの環境でしかビルドできません。 ですので、NetBSD/i386に代表される32ビットの環境ではBazelが動かないので、 Mozc 2.29.5268.102をビルドすることはできません。残念です。

ちなみに、以前のMozcよりOSに依存するコードは格段に少なくなっているようです。 そういう部分はabseil-cppを利用することになったのかもしれません。 Bazelが良いためでないのは間違いありませんが…。

mozc-serverのビルド

Mozcのパッケージは、pkgsrc/inputmethod/mozc-serverからビルドしていくことになります。 実を言いますと、mozc-serverのビルドは難しくありませんでした。 潜在的なBazelの問題は、mozc-serverのビルドでは表面化しなかったのです。

ですが、以下のようにすれば、pkgsrc開発者的にはうれしいような気がします。

do-build:
        cd ${WRKSRC} && ${SETENV} ${MAKE_ENV} \
                ${PREFIX}/bin/bazel \
                        --output_user_root=${WRKDIR}/bazel \
                        --client_debug \
                        build \
                        server:mozc_server \
                        --host_action_env=CWRAPPERS_CONFIG_DIR=${CWRAPPERS_CONFIG_DIR} \
                        --action_env=CWRAPPERS_CONFIG_DIR=${CWRAPPERS_CONFIG_DIR} \
                        --host_action_env=PATH=${PATH} \
                        --action_env=PATH=${PATH} \
                        --sandbox_debug \
                        --verbose_failures \
                        --subcommands \
                        --config oss_linux --compilation_mode opt

ここで、--output_user_rootをWRKSRC以下に設定すれば、make cleanすることで ビルドの過程で生成されたものは全て削除することができます。 また、--subcommandsを指定することで、どのようなコマンドが実行されたのか表示されるようになります。 ここで、oss_linuxというconfigを指定しているのですが、特にLinuxに特化したものではなく、 Unix-like OS全般に適用できるものでしたので、このままで大丈夫です。 --host_action_envや--action_envでcwrapperの変数を渡していますが、これは本当は不要でしょう。 Bazelはサンドボックス機能を持っているので、明示的に渡さないと環境変数も暗黙の内には引き継がれません。

これで、WRKSRC/bazel/bazel-out/netbsd-opt/bin/server/mozc_serverが生成できました。

mozc-rendererのビルド

次にはpkgsrc/inputmethod/mozc-rendererをビルドします。 pkgsrc以外のパッケージ管理の仕組みでは、mozc-rendererを個別のパッケージにしていない 場合もあるようですが、pkgsrcでは分けています。 この方が依存関係を解決するには良いと思うのですが…。

現在のMozcのmozc-rendererはQt6を利用しています。 Bazelではソースファイル(.cや.cxxなど)に加えて、そこからインクルードされる ヘッダーファイルまでBazelファイル中で再帰的に依存関係として記載しておく必要があります。 個人的には、そんな必要があるような気がしないのですが…。 しかもBazelファイルを記述するドメイン固有言語であるStarlarkではdir/**という そのディレクトリー以下のファイルを再帰的に指定する方法も提供されていますので、 自己否定しているような気もしてしまいます…。

いずれにしても、Qt6のようにツリー外の依存関係を解決するのは、Bazelでは少し面倒ですし、 一級市民ではないようです。 pkg-configの結果から、依存関係を自動生成する仕組みがMozc用に用意されていました。 ですが、少なくともNetBSD/amd64上のpkgsrcにとっては、指定されたパッケージでは 不足していました。WORKSPACE.bazelで、Qt6OpenGLとglもpkg-configで情報を 取得する対象にする必要がありました。

ここまでは、よくあることなのですが、実際にビルドしてみると、Qt6のヘッダーファイルが 不正に利用されているとしてBazelがエラーを多量に発生させてしまいます。 どうやら、cc -MDで生成される.dファイルの内容と、Bazelのサンドボックス機能で作られた ヘッダーファイルのパスが一致しているかをチェックしているようです。 例えば、/usr/pkg/qt6/include/QtCore/QObjectが不正に利用されていると エラーが発生していました。

いろいろと試してみると、2つのことが分かりました。 1つ目は、そもそも/usr/pkg/qt6という絶対パスはBazelファイルでの依存関係として 指定されていないと言うこと、2つ目は依存関係に絶対パスを指定するとBazelは絶対パスの 指定を許さずエラーになると言うことです。

Bazelは、ヘッダーファイルのパスを指定するのに、-Iではなく-isystemを利用します。 そして、各ヘッダーファイルは、シンボリックリンクでWRKSRC/bazel以下にBazelが配置します。 NetBSD/amd64-currentのGCC 10.5.0は、-isystemで絶対パスを設定し、それがシンボリックリンク を含んでいる場合に、シンボリックリンクをたどった結果のパスを.dファイルに記載するような 挙動になっていました。clangはそうではありません。

ここまで、NetBSD baseのccを使ってビルドするようにbazelをブートストラップしていたのですが、 GCCの挙動ではBazelは気にいらないようです。 pkgsrc/lang/clangからインストールされるclang/clang++を使うようにすることにしました。 これで正常にビルドは完了するようになりました。

mozc-tool、fcits5-mozcのビルド

mozc-rendererがビルドできれば、mozc-toolもfcitx5-mozcも問題なくビルドすることが できました。

今後について

Mozc自体はibus用のモジュールをビルドするようになっています。 私がfcitx5を利用しているので、今のところibus-mozcまでたどりついていませんが、 commitするまでには、ibus-mozcも用意しておきたいと思います。

NetBSDで最新のMozcを使う 1

この記事は、NetBSD Advent Calendar 2023の19日目の記事です。

はじめに

私自身はSKKを常用しているので、連文節日本語かな漢字変換の世間の流れを良く知りませんが、 Google日本語入力のオープンソース版であるMozcが、NetBSDで利用できるなかで、 一番快適なのではないかと思っています。

ですが、最近のProtocol Bufferパッケージ(pkgsrc/deve/protobuf)のアップデートで、 pkgsrc/inputmethod以下にあるMozc関連のパッケージがビルドに失敗するようになって しまったようです。

ちょうどpkgsrcは4半期のフリーズの時期ですので、実際にはアップデートはできていませんが、 Mozcを最新のタグである2.29.5268.102というバージョンにアップデートする準備が だいたい整いましたので、アップデートのために実施したことを書いておきたいと思います。

最近のMozcのビルドの仕組み

最近のMozcは、Googleの提供しているBazelというビルド・オートメーション・システムを 利用するようになっています。 pkgsrcに現在含まれているMozc関連のパッケージは、GYPというビルド・オートメーション・ツール を使っていましたが、少なくともNetBSDで利用する際にベースとなるLinuxでのビルドには、 GYPはもう使えないようです。

と言うことで、Bazelのパッケージを先に作成する必要があります。

Bazelのパッケージを作る

Bazelをビルドするには、2つの方法があるようです。 Bazelを使ってBazelをビルドする方法と、Bazelを使わずBazelをビルドする方法です。 NetBSD用のBazelバイナリーは配布されていませんので、後者の方法(ブートストラップする方法)を使うしかありません。 ブートストラップする場合には、Javaの.jarファイルが実行でき、Python 3も使えれば良いようです。

Bazelのソースコードを確認する

NetBSDでBazelをブートストラップしようとすると、NetBSDという選択肢がないとjavaコマンドに 文句を言われてしまい、先に進めません。 ブートストラップ用の配布物に含まれる.jarファイルがNetBSDに対応していないために、 このようなエラーが発生しているようです。 Bazelファイル(WORKSPACE、BUILD、*.bzl)と.javaファイルをLinuxやOpenBSD、FreeBSDでgrepし、NetBSDも同様に 定義をしたり、条件節を追加したりしてやります。 具体的な内容は、pkgsrc/wip/bazel/patches以下を見ていただければと思います。 この時点で気付いた以上のものが含まれてはいますが…。

Bazelのブートストラップ・キットを作り直す

.jarファイルの生成自体は、うまくBazelファイルを編集し、pkgsrc/pkgtools/libkverを 使えばNetBSDでもビルドできましたが、Linux/x86_64環境でビルドしてしまうのが一番簡単です。 bazel-distfileターゲットを実行すれば、.zipアーカイブでブートストラップ・キットが できあがるはずと思うのですが、scripts/bootstrap以下のファイルが含まれていませんでした。 これも元のブートストラップ・キットからコピーして再度手動でアーカイブファイルを作成し直して、 これをNetBSD環境へ持って行きます。 LOCAL_PORTS/bazel-6.4.0-dist-netbsd.tar.gzから最終的なブートストラップ・キットは 入手できます。 これ以降、Bazelファイルの修正が不足していて修正する必要が出て来るのですが、Bazelファイル を直しても、Linuxでブートストラップ・キットを作り直す必要はありませんでした。 修正して再度アーカイブ・ファイルを作成するだけで大丈夫でした。

Bazelの隔離機能とpkgsrcの隔離機能が競合する

Bazelは、一貫性のあるビルドを実行するために、ビルド用のサンドボックスを提供しているようです。 pkgsrcも、buildlink3という仕組みで、サンドボックス的な環境を提供しています。 ですが、2つの機能は少し発想が異なるようで、両立させるのは私には無理でした。

この時点で認識できた競合した事項を記載しておきます。

  • C/C++コンパイラーやstripコマンド等が絶対パスで埋め込まれてしまいます。 これによって、pkgsrcのcwrqapperのccコマンドやc++コマンド等をビルド時に使用すると、 WRKSRC以下の絶対パスがBazelコマンドに埋め込まれてしまい、実質的に使えないバイナリーに なってしまいます。
  • できたbazelバイナリーを実行してみて、libjava.soが見付からないとエラーが出るため JAVA_HOMEの設定がおかしい、あるいはどこかで上書きされているのではないかと、 この時は考えていたのですが、これは勘違いでした。

Bazelのランタイムエラーを解析し、修正する

生成されたbazelコマンドを実行すると、

Error: could not find libjava.so
Error: Could not find Java SE Runtime Environment.

と表示されて、動きません。 検索すると、 Java error on AIX #6655 に同じ問題に悩んでいるAIXへ移植しようとしている人がいたのですが、 解決することなくissueはクローズされてしまっています。

何もヒントがウェブ上にはないようなので、lang/openjdk11でこのエラーメッセージを 出している箇所を検索してみることにしました。

すると、 jdk11u-jdk-11.0.21-9-1/src/java.base/unix/native/libjli/java_md_common.c の中の、以下の関数のdladdr()が想定されるlibjli.soのパスではなく、bazel()という文字列を 返しているのが良くないと分かりました。

jboolean
GetApplicationHomeFromDll(char *buf, jint bufsize)
{
    /* try to find ourselves instead */
    Dl_info info;
    if (dladdr((void*)&GetApplicationHomeFromDll, &info) != 0) {
        char *path = realpath(info.dli_fname, buf);
        if (path == buf) {
            return TruncatePath(buf);
        }
    }
    return JNI_FALSE;
}

lang/oprnjdk11では、libjliは静的にリンクされています。 それがいけなさそうです。

jdk11u-jdk-11.0.21-9-1/make/launcher/LauncherCommon.gmk を見ると、AIXとBSDの場合は、libjliを静的にリンクするようになっています。 さきほどのissueでAIXの人が同じように悩んでいたのも納得できました。 https://mail-index.netbsd.org/pkgsrc-changes/2023/12/09/msg288356.html のように変更し、lang/openjdk11でlibjli.soを動的にリンクするようにしました。 実際には、 https://mail-index.netbsd.org/pkgsrc-changes/2023/12/12/msg288501.html の適用も必要でした。

このopenjdk11を使えば、bazelコマンドは正常に動作しているように見えるくらいにはなりました。

時間の関係で、更にbazelを直しつつ、Mozcをビルドする話は次回に続きます。

NetBSD上のFirefoxで、text-to-speechを試す

この記事は、NetBSD Advent Calendar 2023の1日目の記事です。

はじめに

最近のMozilla Firefoxには、text-to-speech機能を利用するための仕組みが組み込まれています。 しかし、Firefox自体がテキストの内容を発音する訳ではなく、speech-dispatcher経由でFestivalというtext-to-speechエンジンを利用します。 NetBSDでも、pkgsrcを使ってFirefoxやspeech-dispatcher、Festivalをインストールし、設定することで、この機能を利用できます。 ですが、音声の品質は良くないようです。 今回は英語のみ発音させることを考えます。

Firefoxのインストール

現在のpkgsrc/www/firefoxのバージョンは120.0です。 既定値ではspeech-dispatcherを使うオプションは有効化されていません。 今回紹介する手順を実施しておかないと、text-to-speechが使えないという警告が頻繁に表示されることがあるので、speech-dispatcherを使うオプションはtext-to-speech機能を利用したい人だけが有効化するのが良いと思います。

以下のように/etc/mk.confに記載して、speech-dispatcherを利用できるFirefoxをビルドできるようにします。

# vi /etc/mk.con
PKG_OPTIONS.firefox=speechd

これを設定した上で、pkgsrc/www/firefoxをビルドし、インストールします。

# cd /usr/pkgsrc/www/firefox
# make install

speech-dispatcherは、pkgsrc/audio/speech-dispatcherにありますが、自動的にインストールされます。

Festivalのインストール

Festivalは本体であるpkgsrc/audio/festivalだけではなく、発音データは音声データも必要です。 pkgsrcでインストールする場合には、以下の4つのパッケージをインストールすれば、Festival本体も含め必要なものは全てインストールできます。

  • pkgsrc/audio/festvox-kal16
  • pkgsrc/audio/festvox-ked16
  • pkgsrc/audio/festvox-rab16
  • pkgsrc/audio/festival-freebsoft-utils

以下のように操作すれば良いでしょう。

# cd /usr/pkgsrc/audio/festvox-kal16
# make install
# cd /usr/pkgsrc/audio/festvox-ked16
# make install
# cd /usr/pkgsrc/audio/festvox-rab16
# make install
# cd /usr/pkgsrc/audio/festival-freebsoft-utils
# make install

これにより、3つの音声を選択することができるようになります。 いずれもあまり質は良くないのですが‥、

speech-dispatcherの設定

speech-dispatcherは、標準ではespeak-ngを使うような設定ファイルになっています。 今回はFestivalを使いますので、そのように指定して行きます。 /usr/pkg/etc/speech-dispatcher/speechd.confに、以下のようなパッチを適用すれば良いでしょう。

--- /usr/pkg/share/examples/speech-dispatcher/speechd.conf	2023-11-18 05:59:28.000000000 +0900
+++ /usr/pkg/etc/speech-dispatcher/speechd.conf	2023-12-01 12:33:15.988361377 +0900
@@ -114,6 +114,7 @@
 # configuration.
 
 # DefaultLanguage "en-US"
+DefaultLanguage "en-US"
 
 
 # ----- MESSAGE DISPATCHING CONTROL -----
@@ -255,7 +256,7 @@
 
 #AddModule "espeak"                   "sd_espeak"    "espeak.conf"
 #AddModule "espeak-ng"                "sd_espeak-ng" "espeak-ng.conf"
-#AddModule "festival"                 "sd_festival"  "festival.conf"
+AddModule "festival"                 "sd_festival"  "festival.conf"
 #AddModule "flite"                    "sd_flite"     "flite.conf"
 #AddModule "ivona"                    "sd_ivona"     "ivona.conf"
 #AddModule "pico"                     "sd_pico"      "pico.conf"
@@ -287,7 +288,8 @@
 # The DefaultModule selects which output module is the default.  You
 # must use one of the names of the modules loaded with AddModule.
 
-DefaultModule espeak-ng
+#DefaultModule espeak-ng
+DefaultModule festival
 
 # The LanguageDefaultModule selects which output modules are prefered
 # for specified languages.
@@ -295,6 +297,7 @@
 #LanguageDefaultModule "en"  "espeak"
 #LanguageDefaultModule "cs"  "festival"
 #LanguageDefaultModule "es"  "festival"
+LanguageDefaultModule "en"  "festival"
 
 # -----CLIENT SPECIFIC CONFIGURATION-----
 

起動させる

Firefoxを起動させる前に、Festivalサーバーを起動しておく必要があります。 Festivalサーバーは、/etc/rc.d以下のスクリプトで起動させるのではなく、自分で起動させる必要があります。

$ festival --server &

続いて、Firefoxも起動させます。

$ firefox &

テキストを読ませる

テキストを読ませるには、リーダービュー機能が利用できるウェブページである必要があります。 例えば、https://edition.cnn.com/の個別の記事であれば、リーダービューを有効にできます。 アドレス欄の右端に下図のようなアイコンが表示されていれば、リーダービューを利用できるウェブページです。 これをクリックすると、リーダービュー画面に移動することができます。

リーダービュー画面では左上に、下図のようなコンソールが表示されています。 ヘッドホンアイコンをクリックすると、音声や再生速度の選択、再生・停止の指示のできるポップアップもできます。

macOS環境なしで古いMacにmacOS High SierraをインストールするUSBスティックを作成する

iPhoneから写真を大量に取り出すためだけにMac mini mid2011 (Macmini5,1)を維持している。 当然最新のmacOSであるmacOS Sonomaが利用できる訳ではない。 サポートされているのは、macOS High Sierraが最後である。

トラブルがあってMac mini mid2011が起動しなくなってしまった。 そこでインターネットリカバリーでmacOS High Sierraをインストールしようとしたのだが、復元サーバーに接続できないとのことでインターネットリカバリーはできなかった。 出荷時にインストールされていたMac OS X Lionも同様にインストールできない。 おそらく、既にインターネットリカバリーでmacOS High Sierra以前をインストールすることはできなくなっているのだろう。 しかし、私はこのMac mini mid2011しかMacは持っていない。手元にある機材のみでmacOS High Sierraを再インストールすることができたので、書いておく。

macOS Sierraのインストーラーを入手する

macOS Sierraのインストーラーとは言っても、DVD-RやUSBスティックに書き込めるイメージファイルではない。 あくまでmacOS上で実行するためのアプリケーションである。これは.dmgファイルでダウンロードできる。 なぜmacOS Sierraなのかと言うと、.dmg形式でダウンロードできるもののうちインターネットリカバリーのターミナル上でインストーラーUSBスティックを作れる最新のものだからである。

ダウンロードは、AppleのウェブページmacOS をダウンロードしてインストールする方法 (HT211683)からダウンロードできる。 「Web ブラウザを使う」の部分の、「Sierra 10.12」からInstallOS.dmgをダウンロードすれば良い。

このInstallOS.dmgをWindowsの7-Zip 23.01で展開する。その中に、Install OSディレクトリーの中にあるInstallOS.pkgが目的としているインストーラーである。

macOS Sierraのインストーラーを展開する

私の持っているmacOSの環境というと、インターネットリカバリー画面から使えるターミナルだけなので、ここで作業できるように考える。 Windows上でUSBスティックをexFATでフォーマットし、そこにInstallOS.pkgファイルをコピーする。

Mac mini mid2011に接続したキーボードで、WindowsキーとAltキーとRキーを同時に押したまま電源を投入すると、インターネットリカバリーの画面になる。これは、macOS High Sierraのリカバリー画面であるはずである。 ここで、インストールする内蔵ストレージの設定と、インストール用のUSBスティックの作成を行う。

内蔵ストレージの設定として、HFS+のパーティションを作成する。macOS SierraはAPFSを扱えないので、macOS High Sierraのリカバリー画面でAPFS関係は全て消して、HFS+だけの環境にしておく必要がある。 ディスクユーティリティーで全て消して、HFS+のパーティションのみ作成すれば良い。

ここで、exFATでフォーマットし、InstallOS.pkgを格納したUSBスティックを接続する。 私の場合には、/Volumes/Untitledにマウントされた。 更にインストーラーにするUSBスティックも接続する。これは/Volumes/32GBにマウントされた。 インストーラーにするUSBスティックがマウントされない場合には、ディスクユーティリティーでApple partitioningのHFS+のパーティションを作っておけば間違いないだろう。 以下のように実行して、USBスティックからインストーラーを起動できるようにする。

# cd /Volumes/Untitled
# pkgutil --expand-full InstallOS.pkg OSInstaller
# cd OSInstaller/InstallOS.pkg
# mv InstallESD.dmg Payload/Install\ macOS\ Sierra.app/Contents/SharedSupport
# plutil -replace CFBundleShortVersionString -string "12.6.03" Payload/Install\ macOS\ Sierra.app/Contents/Info.plist
# cd Payload/Install\ macOS\ Sierra.app/Contents/Resources
# ./createinstallmedia --volume /Volumes/32GB --applicationpath /Volumes/Untitled/OSInstaller/InstallOS.pkg/Payload/Install\ macOS\ Sierra.app

ここで、2行目から4行目は、OpenCoreのLegacy macOS: Offline Methodのページを参照した。

ここで、5行目は、qiitaの「macOS Sierraのインストール 用 USBメモリ作成方法の落とし穴」のページを参照した。

macOS Sierraをインストールする

Altキーを押しながらMac mini mid2011を起動させると、起動するデバイスやパーティションを選択できる。そこで「Install macOS Sierra」を選択する。 念のためターミナルで以下のように実行して時刻を合わせておいた上でインストールを継続する。

# ntpdate time.apple.com

今回作成したインストーラーUSBスティックでは、GUIでインストールしようとすると、整合性に問題があると言われてインストールをすることができない。 コマンドラインでインストールすればそのようなエラーにはならないので、以下のように実行してインストールする。 内蔵ストレージが/Volumes/macOSにマウントされている。

# installer -pkg /Volumes/Mac\ OS\ X\ Install\ DVD/Packages/OSInstall.mpkg -target /Volumes/macOS

これで、macOS Sierraをインストールできる。その後に、macOS Sierra上でmacOS High SierraのインストーラーUSBスティックを作成し、それを使ってクリーンインストールすれば良い。

2023年10月10日まで有効なWindows 11 development environmentで、ファイルシステムとしてReFSが使えるようになっていた

Windows 11 development environmentというのがあって、各種ハイパーバイザー用に仮想マシンがインポートできるようなファイルが配布されている。 私はVirtualBox用のものを利用しているが、Hyper-V (V2)の方が良いのかもしれない。

ここで利用できるWindowsは約3カ月しかライセンスがないのだが、実態としてはWindows 11 Enterprise Evaluation64ビット版22H2だった。 そもそもWindows 11 Enterprise Evaluation自体が3カ月間利用できるので、実機にインストールしても、Windows 11を利用するという視点では 変わらないかもしれない。 各種開発環境がインストール済みであるのは、宣伝文句の通り利点かもしれない。 ちなみに、ディスクの空き容量は最低でも70GB必要と記載されているが、VirtualBoxの場合には、実際には40GB程度空いていれば利用開始することはできる。

この環境はWindows 11 Enterpriseであるということは、ファイルシステムとしてReFSを利用できるのではないかと考えて試してみると、 確かにReFSが利用できた。

第7世代Amazon Kindleと第10世代Amazon Kindle Fire HD 8で、EPUB3な電子書籍を読む

少なくとも2023年8月1日の時点では、Amazon Kindle (einkな画面のタブレット)や、FireタブレットでEPUB3な電子書籍を読むことができる。

私の持っているEPUB3のファイルの容量は大きいので、電子メールで送って読めるようにするのは難しい。 調べてみると、Send to Kindleというウェブページからアップロードできるようになっていた。 最大200MBまでアップロードできるそうだ。

アップロードしても、クラウドリーダーでは読むことはできなかった。

Amazon FireOS用のMicrosoft OneNoteアプリで、言語ファイルがダウンロードできるようになっていた

しばらく前に、第10世代のAmazon Kindle Fire HD 8というタブレットを購入していた。 電子書籍を読むのに使っている訳だが、Amazonアプリストアというものも用意されていて、 Androidアプリをインストールできる。 まあ、十分なものはないので、F-Droidでもインストールしないと困ってしまうような気がする。

しかし、Microsoft OfficeとOneNoteのアプリはマイクロソフトから提供されていて、 OneNoteを少し大きな画面のタブレットで使うとどうなるのかは気になっていた。 しかし、インストールすると厳密には覚えていないが、言語ファイルがダウンロードできないと言う エラーが起きていた。それでも、日本語のユーザーインターフェイスにはなっていたように思うが。

先週くらいに試したら、無事に言語ファイルがダウンロードでき、日本語フォントもダウンロードしたようだった。 OneNoteはあまり私のニーズには合わなかったように思うが、正常に使えるようになったのは良かった。

TOPPERSでメーリングリストが廃止されていた

users@toppers.jpというメーリングリストを購読していたのだが、 2023年7月7日に廃止されていた。 移行先はGitHub Discussionsになるそうだ。 電子メールが流行っていないのは確かな気がするが、電子メールほどオープンな規格もない訳で、簡単には同じ決断はできない気がする。

ヘッドホンJVC STEREO HEADPHONES HA-RZ710のイヤークッションを交換する

JVC HA-RZ710というヘッドホンは 比較的安価で使いやすいものなのだが、それなりの期間使って来てイヤークッションがボロボロになってしまった。

大きさを測ってみると、2個入り イヤーパッド イヤークッション 交換用耳パッド 105 MM 対応が合いそうで、 実際に購入してみると、ちょうど良いサイズだった。

WindowsでPDFファイルのページ単位での加除をするソフトウェアを選ぶ

PDFファイルを編集したいという場合には、何でもできるAdobe Acrobat DCを使えば良いと個人的には思うのだが、誰もが費用を負担できないし、 確かにAdobe Acrobatはおおげさ過ぎる用途というのもあると思う。

PDFSam Basicは知っていて、便利であるとは思うのだが、Javaベースであることが 唯一Windowsユーザーにお勧めできない理由になっていた。

pdf_asが.NET Framework 4.6で動くものであり、Windows 10の環境では 導入しやすく便利だった。 itextsharp.dllを利用しているとのことだった。

WhatAppのcompanion機能

WhatAppでは基本的には電話番号をベースにアカウントが作成されていると思うのだが、徐々に複数の端末で同時にログインできるようになって来た。 最初は、元となるスマートフォンがオンラインであれば、web.whatsapp.comをデスクトップ版のウェブブラウザーで 開くとメッセージを参照・投稿できるようになった。 次には、そもそもSIMカードの入らないタブレット端末のWhatsAppアプリもweb.whatsapp.com同様に利用できるようになったり、 元となるスマートフォンがオンラインである必要がなくE2E暗号化して利用できるようになり、 現在は、1つの電話番号ベースのアカウントに対して、web.whatsapp.com、タブレット端末のWhatsAppアプリ、スマートフォン端末のWhatsAppアプリの中から 合計4端末が紐付けできるようになっている。 特に、複数台のスマートフォンで同時に共有して利用できるようになっている。

iPhoneのMessageアプリで、電話番号が+81から始まる表示になってしまい、連絡先アプリに登録されている電話番号と合致しなくなってしまった場合

iPhoneを乗り換えた際に、Messageアプリでやりとりしているメッセージ(おそらくSMS)のやりとしている相手が+81で始まる電話番号になってしまい、 連絡先アプリに登録されている090-xxxx-xxxxのような電話番号と合致しなくなってしまい、困っているという話を聞いた。 遠方の方なので直接見る術はなかったのだが、とりあえず直せたので書いておく。

参考にしたのは、 [iPhone]メッセージで携帯電話番号が「+81」からの表示になっています。何か設定が変わったのでしょうか?という ソフトバンクのFAQの記事である。 ここには、「iOSアップデート(ソフトウェア更新)する。」という対処方法が記載されている。 本当にこんな方法で解消するのかと疑っていたのだが、ソフトウェア更新が残っていたので実施してもらったところ、問題は解消されたとのことだった。

安価なメカニカルキーボードを購入した

何年かFILCO Majestouchの青軸キーボードを使って来たのだが、これはどこかおかしく、DIPスイッチで設定を変更できない。 また、USB接続してから使えるようになるのに時間がかかるというのもあって不便だった。 Bluetooth接続機能もあるのだが、ついに一度も使ってみることはなかった。 今回それが故障してしまったので、安価なメカニカルキーボードを探していた。

Merdia メカニカル式ゲーミングキーボード 全104キーボード US配列 USB有線キーボード LEDバックライト付き (青軸-ブラック) を購入してみたら、 打鍵感は良かった。私には英語キーボード配列が望ましいので、そういう面でも問題ない。 1つ難点があるとすれば、キートップに表示された文字のフォントが見慣れない感じなので、若干違和感がある。 デフォルトでは相当派手にLEDが光るのだが、輝度を下げて行くと接続時以外は一切光らないようにできるので、おとなしい感じで利用できる。

郵便はがきに連名で宛先を印刷する

郵便はがきに宛先を印刷したかったのだが、必要な条件として、連名が綺麗に印刷できるというのがあった。 姓の部分は重複せず、名の部分を揃えて印刷したい。 TeXとかでやれば良いのだろうが、そこまで手を掛けるほどの枚数でもない。

Windows環境でも良いと思って探すと、はがき作家16 Freeの、「はがき作家 あてな」が望みの印刷ができた。 無料版でははがきの宛名面に自分の住所を印刷できないようだが、今回は裏面に印刷するので不要だった。

Amazon.co.jpでuxcellの金属製支持金具(ダボ)を購入した

とある棚で棚板を支えるのに使われている直径6mm、長さ19mmの金属製のサポートピンを探していたのだが、 全く見付からない。 Amazon.co.jpで探してみると、uxcell シェルフブラケットペグ ニッケルメッキ ホルダー サポート ピン キャビネット 6x19 mm 20個入り というのが見付かった。だが、日本国外から発送されて来るらしい。

説明によると、日本国外からの発送には10日から14日かかるとのことだった。結果としては、2023年5月25日に注文して6月9日に届いた。 これはYanwenと言う運送業者が取り扱っていることになっているのだが、 公式ウェブサイトのトラッキングは全く役に立たなかった。5月30日に運送業者に引き渡した時点で情報は更新されなくなってしまった。

到着してみると、中国本土からの発送かと思い込んでいたのだが、クルグスのビシュケクからの発送になっていた。 これまでクルグスからの発送の経験はなかったが、それでも15日で届くのだからおもしろい。

Amazon Kindle Fire HD 8 第10世代でBluetooth audioのabsolute volumeを無効にする

Bluetooth接続のヘッドセットBose Noise Cancelling Headphones 700を使っているのだが、 Amazon Kindle Fire HD 8 第10世代では、標準ではBluetooth audioのabsolute volume機能が有効になっている。 absolute audio機能が有効になっていると、Kindle Fire HD 8の音量が、Bose Noise Cancelling Headphones 700の音量調整をすることで変更される。 私は、Kindle Fire HD 8の音量とBose Noise Cancelling Headphones 700の音量は別に調整したいので、absolute volume機能は無効にしたい。 そのためには、Kindle Fire HD 8でdeveloper optionsを有効にしないといけない。

developer optionsは、Androidでは通常は表示されていない。 Amazon.comのConnect to Fire Tablet through ADB (Fire Tablets)のページによると、 developer optionsを有効にするには、serial numberを何回かタップすれば良い。 設定アプリより、「端末オプション」を選び、さらに「Fireタブレットのバージョン情報」を選択し、「シリアル番号」を何回かタップすれば、「「端末オプション」のメニューに「開発者オプション」が追加される。 その中に「絶対音量を無効にする」というオプションがあり、それが既定値では無効になっているので、有効にすることでBluetooth audioのabsolute volumeを無効化できる。

ToodledoのiOS appのBeta版を利用している

ToodledoというTo Do管理のウェブサービスを長年利用している。一時期は全くメンテナンスしている雰囲気はなかったのだが、 オーナーが変わってから、iOSとAndroidのアプリも更新しようとしている。 現在はベータ版も利用でき、ベータ版は結構便利で良くできている。

少し前まで、iPhone 8 Plusを利用していただのが、iOS用のベータ版は非常に動きが緩慢で苦痛だった。データを保存する時に、動作が止まってしまっていた。 これを、iPhone 11やiPhone 12で利用すると、動作が止まってしまうことはなく、快適に利用できた。

ファミリー共有されたApple IDでiTunesカードの残高を使う

Appleへの支払いを一元化したいのもあって、Apple IDでファミリー共有を有効にし、支払いも共有している。 だが、共有された側のApple IDでiTunesカードのを購入してredeemしてしまうと、分かりにくい状況になってしまった。

状況としては、私がファミリー共有の管理者になっていて、私のクレジットカードを共有された支払い元に設定している。 その上で、ファミリー共有に追加されている家族のiPhoneで、iTunesカードの残高を追加した。 すると、iTunesカードから追加した残高を使うことができなかった。

問題は、私のクレジットカードの情報が、家族のApple IDかiPhoneかで確認済の状態になっていなかったために起きた。 家族のApple IDかiPhoneかで私のクレジットカードを確認済の状態にしないと、もう一つの支払方法であるiTunesカードからの残高も利用できないのである。 家族のApple IDかiPhoneかで私のクレジットカードを確認済の状態にするには、私のクレジットカードのCVV (3桁のセキュリティーコード)を 家族のiPhoneで入力しないといけなかった。 それにより私のクレジットカードは家族のiPhoneでも利用できるようになり、その家族のApple IDにあるiTunesカードからの残高も支払方法として 利用できるようになった。

Synology NASへFirefoxでログインできない場合

Synology DS920+というNASでDSM 7を利用しているものを管理しているのだが、Firefoxで管理画面にログインできない場合がある。 移設する場合くらいしかそういうことは発生しないのだが、いつもなぜだか覚えておらず困ってしまうので、書いておく。 Google Chromeでは、そういう場合でもログインできる。 ログイン画面でF12を押してconsoleを表示させると、cookieが無効だと言われているのが見えるはずである。

Cookie “_SSID” has been rejected because it is already expired.

それが問題なのだが、無効になるのは、DS920+のRTCが正しくないためである。2000年の日付になっていて、 そのためにcookieが無効になってしまっている。

そういう場合には、Google Chromeでログインし、強制的にNTPで時刻を同期してやるか、手動でほぼ正しい時刻を設定してやれば良い。 こういうことが起きるのは、私の管理するもので、NTPサーバーが利用できるより前にDS920+を起動しておく必要があるからだと思われる。 なので、通常は起きないことなのかもしれない。

HP Envy 13-ay1052AU x360のBIOSをWindowsを起動させずに更新する

HP Envy 13-ay1052AU x360では、他のWindowsが起動しているPCでUSB stickにBIOSイメージを書き込み、HP Envy-ay1052AU x360でWindowsを起動させることなく BIOSをアップデートできる。 具体的には、 HP Communityの記事にあるように、USB stickを接続した状態で、WindowsキーとBキーを押しながら電源ボタンを押して起動させ3秒間電源ボタンを押したままにし、電源ボタンを離して更にWindowsキーとBキーを3秒間押したままにして、 その後に全てのキーを離してやると、USB stickにあるBIOSアップデートイメージを書き込んでくれる。 ただし、BIOSの設定項目は全て初期化されてしまうので、再度設定し直す必要がある。

Bose Noise Cancelling Headphones 700 UCを購入した

Jabra Move WirelessというBluetoothヘッドセットを使っていたのだが、電池の持ちが著しく悪くなって来たし、 音質もSBCしかサポートしていないようで、良いような気はしない。 しかし、ヘッドセットとしては、HD Voiceに対応していて、最低限の性能は持っている。

一度、ノイズキャンセリング機能を体験してみたかったので、 Bose Noise Cancelling Headphones 700 UCを購入してみた。 ここで、UCというのは、Creative BT-W3のようなBluetoothオーディオアダプターが付属しているということを示している。

Bluetoothと独自の2.4GHz通信の両方をサポートしているヘッドセットを探していたのだが、Bose Noise Cancelling Headphones 700 UCはそれに近いかもしれない。 だが、Creative BT-W3と比較して特にHands-free profileでの通話の場合にどうなのか分かっていない。 Bluetooth接続の場合、HD Voiceには対応しているようだ。

ノイズキャンセリングは非常に有用で、既にこれなしで音を聞くのはないような気がしている。ちなみに、Android相手のA2DPの場合にはAACが利用されるようだ。 NetBSD/amd64 10.99.2でも付属のBluetoothオーディオアダプターは正常に利用できる。

pkgsrc/multimedia/mplayerで、/dev/audio以外で音を再生する

NetBSDで、pkgsrc/multimedia/mplayerで音を再生するのに、複数あるデバイスから1つを指定したい。 オーディオバックエンドはOSSとする。OSSはLinuxでは既に廃れているようなので、ウェブ上ではほぼ例は見つからない。 以下のようにすると/dev/audio2で音を再生できた。

$ mplayer -ao oss:/dev/audio2 test.mkv

ちなみに、sunバックエンドもNetBSDで利用できる。この場合の設定はOSS同様で以下のようにすれば良かった。

$ mplayer -ao sun:/dev/audio2 test.mkv

pdftocairoで、PDFファイルをJPEGやPNGファイルに変換する

PDFファイルをJPEGファイルにするには、GhostScriptを利用するというのが古くからの方法だと思うのだが、 分かりにくかった記憶があるし、満足した結果が得られたこともなかったような気がする。 GhostScriptをちゃんと理解していないからだろう。 だが、PDFファイルの1ページを1つのJPEGファイルやPDFファイルにしたい場合は存在する。 Popplerはcairoを使っていて、 その一部であるpdftocairoコマンドを使うと、簡単に満足できる品質のJPEGファイルやPNGファイルを得ることができた。 pkgsrcだと、print/poppler-utilsパッケージに含まれている。

HP Envy 13-ay1052AU x360のブート時のメニュー選択

ほぼMaintenance and Service Guideに書かれているのだが、 すぐに分からなくなってしまうので、書き留めておく。

F2
Startup CHeckということで、診断メニューを表示する。HP PC Diagnostics UEFIがHP_TOOLSというディスクラベルのドライブに用意してあれば、リッチな診断を実施できる。
F9
Change Boot Orderということで、一時的に起動デバイス等を選択する画面を表示する。
F10
BIOS Setup Optionsということで、BIOS設定画面を表示する。
F12
Network Bootということで、PXE bootができるようだ。試していない。

ESCキーを押せば、メニューが表示されるので、細かく覚えておく必要はないかもしれない。

Asterisk 16で、内線端末間で番号通知をする

ここまでで、複数のソフトフォンで発着信できるようになっているのだが、内線番号を相互に通知することはできていなかった。 どういう方法が一番適切であるか良く分からないのだが、pjsip.confiax.confで指定すれば 内線番号を相互に通知することはできた。

pjsip.confの場合には、以下のようにした。endpointの設定でcalleridを追加している。

; 内線: baresip+
[fire8]
type = aor
max_contacts = 1
qualify_frequency = 60
remove_existing = yes

[fire8]
type = auth
auth_type = userpass
username = fire8
password = password

[fire8]
type = endpoint
transport = transport-udp
context = default
disallow = all
allow = ilbc,ulaw,alaw,gsm,g729,g723
aors = fire8
auth = fire8
;outbound_auth = fire8
dtmf_mode = rfc4733
force_rport = yes
ice_support = no
rtp_symmetric = yes
direct_media = no
rewrite_contact = yes
device_state_busy_at = 1
callerid="104" <104>

iax.confも似たような設定で、calleridを追加した。

[general]
match_auth_username=yes
iaxcompact=yes
allow=all

; 電話機との接続
[user1] ; Android smartphone
type=friend
username=user1
secret=password1
context=default
canreinvite=no
host=dynamic
qualify=no
callerid="101" <101>

[ryoonwinpc] ; Zoiper for Windows
type=friend
username=user2
secret=password2
context=default
canreinvite=no
host=dynamic
qualify=no
callerid="103" <103>

Asterisk 16に収容したFusion IP-Phone SMARTの2回線への接続に、PJSIPを利用する

Asteriskとソフトフォンの間の通信をchan_sipからPJSIPに変更したのだが、 AsteriskとFusion IP-Phone SMART 2回線分の通信はchan_sipのままだった。 これもPJSIPにして問題ないはずなので、変更してみた。

まずは、sip.confに相当する内容をpjsip.confに移植する。 現在のsip.confの内容は以下のようになっている。

[general]
match_auth_username=yes ; 同じsmart.0038.netに複数のアカウントを持っているので。
; 外線着信のため
register => 5XXXXXXX:password1@fusion1/5XXXXXXX
register => 5YYYYYYY:password2@fusion2/5YYYYYYY

; 外線
[fusion1]
type=friend
username=5XXXXXXX
fromuser=5XXXXXXX
secret=password1
host=smart.0038.net
fromdomain=smart.0038.net
context=default
insecure=port,invite
canreinvite=no
dtmfmode=inband
qualify=yes
allow=!all,ilbc,g729,gsm,g723,ulaw,alaw
allowguest=no
host=dynamic

[fusion2]
type=friend
username=5YYYYYYY
fromuser=5YYYYYYY
secret=password2
host=smart.0038.net
fromdomain=smart.0038.net
context=default
insecure=port,invite
canreinvite=no
dtmfmode=inband
qualify=yes
allow=!all,ilbc,g729,gsm,g723,ulaw,alaw
allowguest=no
host=dynamic

これをpjsip.confに移植して行く。 まずは変更点を示す。

@@ -1,8 +1,16 @@
+[general]
+match_auth_username = yes
+
+[system]
+type = system
+disable_rport = yes
+
 [transport-udp]
 type = transport
 protocol = udp
-bind = 0.0.0.0:5070 ; 5060 portはchan_sipと競合する。
+bind = 0.0.0.0

+; 外線: ひかり電話
 [hikari-denwa]
 type = registration
 transport = transport-udp
@@ -19,7 +27,7 @@ password = 0003_password

 [hikari-trunk]
 type = aor
-contact = sip:10.81.0.1
+contact = sip:3@10.81.0.1

 [hikari-trunk]
 type = endpoint

@@ -38,3 +46,81 @@ dtmf_mode = inband
 type = identify
 endpoint = hikari-trunk
 match = 10.81.0.1
+
+
+
+; 外線: Fusion SMART IP 1
+[fusion1]
+type = registration
+transport = transport-udp
+outbound_auth = fusion1
+server_uri = sip:smart.0038.net
+client_uri = sip:5XXXXXXX@smart.0038.net
+retry_interval = 0
+auth_rejection_permanent = no
+
+[fusion1]
+type = auth
+auth_type = userpass
+username = 5XXXXXXX
+password = password1
+
+[fusion1]
+type = aor
+contact = sip:5XXXXXXX@smart.0038.net
+qualify_frequency = 5
+
+[fusion1]
+type = endpoint
+transport = transport-udp
+context = default
+from_user = 5XXXXXXX
+from_domain = smart.0038.net
+outbound_auth = fusion1
+disallow = all
+allow = ilbc,g729,gsm,g723,ulaw,alaw
+aors = fusion1
+
+[fusion1]
+type = identify
+match = 61.213.230.153 ; IPアドレス
+endpoint = fusion1
+
+
+
+; 外線: Fusion SMART IP 2
+[fusion2]
+type = registration
+transport = transport-udp
+outbound_auth = fusion2
+server_uri = sip:smart.0038.net
+client_uri = sip:5YYYYYYY@smart.0038.net
+retry_interval = 0
+auth_rejection_permanent = no
+
+[fusion2]
+type = auth
+auth_type = userpass
+username = 5YYYYYYY
+password = password2
+
+[fusion2]
+type = aor
+contact = sip:5YYYYYYY@smart.0038.net
+qualify_frequency = 5
+
+[fusion2]
+type = endpoint
+transport = transport-udp
+context = default
+from_user = 5YYYYYYY
+from_domain = smart.0038.net
+outbound_auth = fusion2
+disallow = all
+allow = ilbc,g729,gsm,g723,ulaw,alaw
+aors = fusion2
+
+[fusion2]
+type = identify
+match = 61.213.230.153 ; IPアドレス
+endpoint = fusion2

全体としては、以下のようになる。

[general]
match_auth_username = yes

[system]
type = system
disable_rport = yes

[transport-udp]
type = transport
protocol = udp
bind = 0.0.0.0

; 外線: ひかり電話
[hikari-denwa]
type = registration
transport = transport-udp
outbound_auth = hikari-trunk
server_uri = sip:10.81.0.1
client_uri = sip:3@10.81.0.1
retry_interval = 60

[hikari-trunk]
type = auth
auth_type = userpass
username = 0003
password = 0003_password

[hikari-trunk]
type = aor
contact = sip:3@10.81.0.1

[hikari-trunk]
type = endpoint
transport = transport-udp
context = default
disallow = all
allow = ulaw
outbound_auth = hikari-trunk
aors = hikari-trunk
direct_media = no
from_user = 3
from_domain = 10.81.0.1
dtmf_mode = inband

[hikari-trunk]
type = identify
endpoint = hikari-trunk
match = 10.81.0.1



; 外線: Fusion SMART IP 1
[fusion1]
type = registration
transport = transport-udp
outbound_auth = fusion1
server_uri = sip:smart.0038.net
client_uri = sip:5XXXXXXX@smart.0038.net
retry_interval = 0
auth_rejection_permanent = no

[fusion1]
type = auth
auth_type = userpass
username = 5XXXXXXX
password = password1

[fusion1]
type = aor
contact = sip:5XXXXXXX@smart.0038.net
qualify_frequency = 5

[fusion1]
type = endpoint
transport = transport-udp
context = default
from_user = 5XXXXXXX
from_domain = smart.0038.net
outbound_auth = fusion1
disallow = all
allow = ilbc,g729,gsm,g723,ulaw,alaw
aors = fusion1

[fusion1]
type = identify
match = 61.213.230.153 ; IPアドレス
endpoint = fusion1



; 外線: Fusion SMART IP 2
[fusion2]
type = registration
transport = transport-udp
outbound_auth = fusion2
server_uri = sip:smart.0038.net
client_uri = sip:5YYYYYYY@smart.0038.net
retry_interval = 0
auth_rejection_permanent = no

[fusion2]
type = auth
auth_type = userpass
username = 5YYYYYYY
password = password2

[fusion2]
type = aor
contact = sip:5YYYYYYY@smart.0038.net
qualify_frequency = 5

[fusion2]
type = endpoint
transport = transport-udp
context = default
from_user = 5YYYYYYY
from_domain = smart.0038.net
outbound_auth = fusion2
disallow = all
allow = ilbc,g729,gsm,g723,ulaw,alaw
aors = fusion2

[fusion2]
type = identify
match = 61.213.230.153 ; IPアドレス
endpoint = fusion2

extensions.confでは、以下の抜粋のように変更すれば良い。 ここではログも出力するようにしている。

 ; 発信
 ;; Fusion SMARTalk 1の場合には9で発信する。
-exten => _9.,1,Set(CALLERID(num)=${MYNUMBER})
+exten => _9.,1,NoOp(Fusion1で発信9)
+exten => _9.,n,Set(CALLERID(num)=${MYNUMBER})
 exten => _9.,n,Set(CALLERID(name)=${MYNUMBER})
-exten => _9.,n,Dial(SIP/${EXTEN:1}@fusion1,120,T)
+exten => _9.,n,Dial(PJSIP/${EXTEN:1}@fusion1,120,T)
+exten => _9.,n,Hangup()

 ;; Fusion SMARTalk 2の場合には8で発信する。
-exten => _8.,1,Set(CALLERID(num)=${MYNUMBER})
+exten => _8.,1,NoOp(Fusion2で発信8)
+exten => _8.,n,Set(CALLERID(num)=${MYNUMBER})
 exten => _8.,n,Set(CALLERID(name)=${MYNUMBER})
-exten => _8.,n,Dial(SIP/${EXTEN:1}@fusion2,120,T)
+exten => _8.,n,Dial(PJSIP/${EXTEN:1}@fusion2,120,T)
+exten => _9.,n,Hangup()

 ;; ひかり電話の場合には7で発信する。
-exten => _7.,1,Set(CALLERID(num)=${MYNUMBER})
+exten => _7.,1,NoOp(ひかり電話で発信7)
+exten => _7.,n,Set(CALLERID(num)=${MYNUMBER})
 exten => _7.,n,Set(CALLERID(name)=${MYNUMBER})
 exten => _7.,n,Dial(PJSIP/${EXTEN:1}@hikari-trunk)
+exten => _7.,n,Hangup()

Asterisk 16で、ソフトフォンとの間をPJSIPによる通信に変更する

Asteriskに接続している一部のクライアントはIAX2で通信するようにしたのだが、 もう1台はZoiPerではなくbaresip+を使っているので、 IAX2にすることはできない。 そこで、この端末についてもchan_sipではなくPJSIPに乗り換えることにした。

PJSIP自体は、既にひかり電話のホームゲートウェイに接続するのに利用しているので、それも合わせて、以下のように設定すれば良い。

PJSIPでAsteriskにregisterするには、Asterisk 16はデータベースを使えるようになっている必要がある。 pkgsrc/comms/asterisk16の場合には、標準ではSQLite3が利用され、/var/db/asterisk/astdb.sqlite3にデータベースファイル が置かれている。 今回は、なぜかこのデータベースファイルの所有者が別ユーザーになっており、SQL errorが起きていたのを無視していたため、 端末がAsteriskにregisterできなかった。ユーザーIDとパスワードの認証までは通過できるのだが、着信できない状態になってしまった。

pjsip.confは、以下のようにした。

[general]
match_auth_username = yes

[system]
type = system
disable_rport = yes

[transport-udp]
type = transport
protocol = udp
bind = 0.0.0.0

; 外線: ひかり電話
[hikari-denwa]
type = registration
transport = transport-udp
outbound_auth = hikari-trunk
server_uri = sip:10.81.0.1
client_uri = sip:3@10.81.0.1
retry_interval = 60

[hikari-trunk]
type = auth
auth_type = userpass
username = 0003
password = 0003_password

[hikari-trunk]
type = aor
contact = sip:3@10.81.0.1

[hikari-trunk]
type = endpoint
transport = transport-udp
context = default
disallow = all
allow = ulaw
outbound_auth = hikari-trunk
aors = hikari-trunk
direct_media = no
from_user = 3
from_domain = 10.81.0.1
dtmf_mode = inband

[hikari-trunk]
type = identify
endpoint = hikari-trunk
match = 10.81.0.1


; 内線: baresip+ on Amazon Kindle Fire HD 8 gen10
[fire8]
type = aor
max_contacts = 1
qualify_frequency = 60
remove_existing = yes

[fire8]
type = auth
auth_type = userpass
username = fire8
password = user3_password

[fire8]
type = endpoint
transport = transport-udp
context = default
disallow = all
allow = ilbc,ulaw,alaw,gsm,g729,g723
aors = fire8
auth = fire8
;outbound_auth = fire8
dtmf_mode = rfc4733
force_rport = yes
ice_support = no
rtp_symmetric = yes
direct_media = no
rewrite_contact = yes
device_state_busy_at = 1

これに合わせて、extensions.confも変更し、発信・着信できるようにする。

[default]
;include => stdexten

; 着信
;; 内線
;;; 自動応答
exten => 1290,1,Playback(demo-congrats) ; 動作チェック用
;;; 各端末
exten => 101,1,Dial(IAX2/user1,20,rt)
exten => 103,1,Dial(IAX2/user2,20,rt)
exten => 104,1,Dial(PJSIP/fire8,20,rt)

;; 外線
exten => 55863768,1,Dial(IAX2/user1&IAX2/user2&PJSIP/fire8,20,rt)
exten => 53077771,1,Dial(IAX2/user1&lIAX2/user2&PJSIP/fire8,20,rt)
exten => s,1,Dial(IAX2/user1&IAX2/user2&PJSIP/fire8)


; 発信
;; Fusion SMARTalkの場合には9で発信する。
exten => _9.,1,NoOp(Fusion発信9)
exten => _9.,n,Set(CALLERID(num)=${MYNUMBER})
exten => _9.,n,Set(CALLERID(name)=${MYNUMBER})
exten => _9.,n,Dial(PJSIP/${EXTEN:1}@fusion1,120,T)
exten => _9.,n,Hangup()

;; Fusion SMARTalkの場合には8で発信する。
exten => _8.,1,NoOp(Fusion発信8)
exten => _8.,n,Set(CALLERID(num)=${MYNUMBER})
exten => _8.,n,Set(CALLERID(name)=${MYNUMBER})
exten => _8.,n,Dial(PJSIP/${EXTEN:1}@fusion2,120,T)
exten => _9.,n,Hangup()

;; ひかり電話の場合には7で発信する。
exten => _7.,1,NoOp(ひかり電話で発信7)
exten => _7.,n,Set(CALLERID(num)=${MYNUMBER})
exten => _7.,n,Set(CALLERID(name)=${MYNUMBER})
exten => _7.,n,Dial(PJSIP/${EXTEN:1}@hikari-trunk)
exten => _7.,n,Hangup()

Asterisk 16で、ソフトフォンとの間をIAX2プロトコルによる通信に変更する

これまで、NetBSD/amd64 9上で動かしているpkgsrc/comms/asterisk16では、SIPソフトフォンとの間については、chan_sipによるSIPを利用していた。 しかし、既にchan_sipの利用は推奨されていないようだ。 後継となるPJSIPについては、既にひかり電話のためにNTT東日本から借りているホームゲートウェイに接続するのに利用していた。 3台のソフトフォンのうち、2台はZoiPerなので、IAX2を利用できる。 この分はIAX2にしてしまおう。

IAX2の設定は、iax.confに記載すれば良い。 chan_sipと似た感じで記入でき、簡単である。

[general]
match_auth_username=yes
iaxcompact=yes
allow=all

; 電話機との接続
[user1] ; Android smartphone
type=friend
username=user1
secret=user1_password1
context=default
canreinvite=no
host=dynamic
qualify=no

[user2] ; Zoiper for Windows
type=friend
username=user2
secret=user2_password2
context=default
canreinvite=no
host=dynamic
qualify=no

extensions.confでも、IAX2を使って着信させるための通信をするのを指定する。

[default]
;include => stdexten

; 着信
;; 内線
exten => 1290,1,Playback(demo-congrats) ; 動作チェック用
exten => 101,1,Dial(IAX2/user1,20,rt)
exten => 103,1,Dial(IAX2/user2,20,rt)

;; 外線
exten => 55863768,1,Dial(IAX2/user1&IAX2/user1,20,rt)
exten => 53077771,1,Dial(IAX2/user1&IAX2/user2,20,rt)
exten => s,1,Dial(IAX2/user1)


; 発信
;; 1回線目のFusion SMARTalkの場合には9で発信する。
exten => _9.,1,NoOp(Fusion発信9)
exten => _9.,n,Set(CALLERID(num)=${MYNUMBER})
exten => _9.,n,Set(CALLERID(name)=${MYNUMBER})
exten => _9.,n,Dial(PJSIP/${EXTEN:1}@fusion1,120,T)
exten => _9.,n,Hangup()

;; 2回線目のFusion SMARTalkの場合には8で発信する。
exten => _8.,1,NoOp(Fusion発信8)
exten => _8.,n,Set(CALLERID(num)=${MYNUMBER})
exten => _8.,n,Set(CALLERID(name)=${MYNUMBER})
exten => _8.,n,Dial(PJSIP/${EXTEN:1}@fusion2,120,T)
exten => _9.,n,Hangup()

;; ひかり電話の場合には7で発信する。
exten => _7.,1,NoOp(ひかり電話で発信7)
exten => _7.,n,Set(CALLERID(num)=${MYNUMBER})
exten => _7.,n,Set(CALLERID(name)=${MYNUMBER})
exten => _7.,n,Dial(PJSIP/${EXTEN:1}@hikari-trunk)
exten => _7.,n,Hangup()

sip.confpjsip.confの内容は、前回と大差はない。

無料のVMware ESXi 8.0のライセンスを取得する

VMwareのウェブサイトを見たら、VMware ESXi 8.0がリリースされていた。 しかし、無料で入手できるような表示にはなっていないように見える。

VMware ESXiの無料での提供は止めてしまったのかと思ったのだが、そうでもないようだ。Free ESXi 8.0 - How to Download and get License Keysによると、 Evaluationを申し込むと、これまで提供されて来たような無料のライセンスが提供されるらしい。

実際に、Customer Connectにログインして、Product Evaluation Center for VMware vSphere Hypervisor 8のページへ行き、License&Downloadのタブへ移動して、 Registerの青色のボタンをクリックして自分についての情報を入力し(基本的にはアカウントの情報が既に入力済みだったが、必須項目で抜けているものもあった)、 評価版の申し込みを完了すると、VMware vSphere Hypervisor 8 Licenseという表示に、無期限のESXi 8.0のライセンスが表示されるようになる。 同様に、インストールのためのISOイメージファイルもダウンロードできるようになる。

ライセンスを割り当てた後の表示は以下のようになる。期限は定められていないことが分かる。「Up to 8-way virtual SMP」という機能の制限は これまでと変わっていないはずである。

MSI製Z79-S01というマザーボードで、NVMe SSDから起動できる条件

Z79-S01というのは、OEM製品のようで、BIOSアップデーターも提供されない。残念な気がする。 MeltdownとかSpectreとかも無視なのかと悲しい気持ちにもなる。

とは言っても、安定しているのかもしれないし、設定項目は結構たくさんある。 NVMe SSDを挿せるM.2端子が1つのみあるのだが、Fast BootオプションをOffにすると、 NVMe SSDからは一切起動できなくなる。

普通のマシンでのFast Bootであれば何も関係ないような気がするが、実際Z79-S01については そういう状態だった。

オフライン状態で、ローカルグループにActive Directoryユーザーを追加する

Windows 10 ProでActive Directoryでセットアップされているマシンで、 ドメインコントローラーにアクセスできない状態、つまり、オフラインの 状態で、ローカルグループ(手元のPCのグループ)のAdministratorsに Active Directoryのユーザーを追加したいと思った。

特に工夫もなく、以下のようにコマンドラインで実行すれば良い。

> net localgroup LOCALGROUP DOMAINUSERID /add
これで、ローカルのLOCALGROUPグループに、DOMAIN\DOMAINUSERIDユーザーを 追加できる。

iPhoneから、MTP経由で写真をコピーする際に、「MACまたはPCに転送」の「元のフォーマットのまま」と「自動」が切り替わるタイミング

pkgsrc/graphics/libheifで利用できるlibheif-1.13.0ではうまく扱えないiPhone XRのiOS 15で撮影した.HEIC画像がある。 とりあえずやりたいことはJPEG形式に変換することなので、いつもは「元のフォーマットのまま(Keep Originals)」に設定している写真アプリの 「MACまたはPCに転送」の設定を「自動(Automatic)」にしてみることにした。 これは、「設定アプリ→写真→MACまたはPCに転送」あるいは「Settings app→Photos→TRANSFER TO MAC OR PC」のようにたどると設定できる。

これUSB to Lightningケーブルをつないている状態でも設定変更できるが、実際にJPEGファイルがMTP経由でPCから見えるようになるのは、 USB to Lightningケーブルをつなぎ直した後からだった。

IA16なGCCのint、long、ポインターのサイズを確認する

GCCはIA16 (8086で始まる16ビットのIntelアーキテクチャー)をサポートするようになっているが、int型、long型、ポインター型のサイズがどうなっているのか理解していなかった。 GCCのオンラインマニュアルでのx86の-m16オプションの説明を読むと、 -m16でも-m32と同様にint型、long型、ポインター型は全て32ビットであるらしい。 それを確認するには、以下のようにすれば良さそうだ。

まず、以下のようなC言語のソースコードsizeof.cを作成する。

$ cat sizeof.c
int
main(void)
{
        int int_size = sizeof(int);
        int long_size = sizeof(long);
        int pointer_size = sizeof(void *);

        return 0;
}

これをコンパイルして、オブジェクトファイルsizeof.oを生成する。

$ gcc -m16 -c sizeof.c

これをディスアセンブルする。すると、$0x4というのが代入される部分が3箇所あることが分かる。 つまり、4バイト=32ビットがint型、long型、ポインター型のサイズであることが分かる。

$ objdump -d sizeof.o

sizeof.o:     file format elf32-i386


Disassembly of section .text:

00000000 <main≶:
   0:   66 55                   push   %bp
   2:   66 89 e5                mov    %sp,%bp
   5:   66 83 ec 10             sub    $0x10,%sp
   9:   67 66 c7 45 fc 04 00    movw   $0x4,-0x4(%di)
  10:   00 00                   add    %al,(%eax)
  12:   67 66 c7 45 f8 04 00    movw   $0x4,-0x8(%di)
  19:   00 00                   add    %al,(%eax)
  1b:   67 66 c7 45 f4 04 00    movw   $0x4,-0xc(%di)
  22:   00 00                   add    %al,(%eax)
  24:   66 b8 00 00             mov    $0x0,%ax
  28:   00 00                   add    %al,(%eax)
  2a:   66 89 ec                mov    %bp,%sp
  2d:   66 5d                   pop    %bp
  2f:   66 c3                   retw

Amazon Fire HD 8 (第10世代)にMozilla Firefox for Androidをインストールする

Amazon Fire HD 8 (第10世代)を利用しているのだが、 デフォルトでAmazon Silkというウェブブラウザーにはあまり慣れられない。 これはGoogle Chrome for Androidを別名でリリースしているものだと思うのだが、そもそもGoogle Chromeも使い慣れていないので、使いにくい。

いつも利用しているMozilla Firefox for Androidは、Amazon Appstoreでは提供されていないようだ。 Mozilla Firefox for Androidは、Fenixという名前で、GitHubで.apkファイルが公開されている。 Amazon Fire HD 8 (第10世代)のFireOS 7.3.2.6は、32ビットARMなAndroidをベースにしているようで、64ビットARM (arm64-v8a)な.apkファイルはインストールできなかった。 armeabi-v7aな.apkファイル をインストールすると、少なくとも私の利用している機能は、自動アップデートを除き、正常に利用できた。 Mozilla Firefox for Androidを利用しているAndroidスマートフォンがあるので、アップデートには気付けそうなので、手作業でアップデートすれば良いのかもしれない。

これで相当にAmazon Fire HD 8 (第10世代)を使う機会が増えそうだ。

Amazon Fire HD 8 (第10世代)でPDFファイルを閲覧する

Amazon Fire HD 8 (第10世代)を利用しているのだが、 PDFファイルを閲覧するアプリがAmazon Appstoreいないように見えた。 実際にPDFファイルを閲覧しようとして提案されるのは、デフォルトでインストールされているKindleアプリだった。 Kindleアプリで十分に閲覧可能なので、有用なPDFファイルビューアーアプリは存在しないのかもしれない。

Amazon Fire HD 8 (第10世代)で、Microsoft OneNoteアプリを利用する

Amazon Fire HD 8 (第10世代)で、Microsoft Officeアプリを利用する話を 書いたが、手書きノートをとるのを試そうと、Microsoft OneNoteアプリもインストールすることにした。 結果としては、静電容量式のスタイラスペンでの書き込みは、反応速度はそこまで悪くはないものの、あまり使いやすいようなイメージを持てなかった。

Microsoft OneNoteアプリは、初回起動時にMicrosoft Officeアプリ同様に言語ファイルをダウンロードしようとするのだが、これが毎回失敗する。 Amazon Appstoreの日本語のレビューでは、あるバージョンでは言語ファイルのダウンロードには失敗しなくなったようなのだが、 少なくとも2023年1月1日現在では、毎回失敗し、日本語のユーザーインターフェイスは利用できない。英語のユーザーインターフェイスを利用することとなる。

plgarc/wip/llama.cppでpkgsrcのBLASサポートを探る

この記事は、 NetBSD Advent Calendar 2024 の13日目の記事です。 llama.cppを使ってみる 以前に、 NetBSD/amd64でllama.cppを使ってみる という記事で llama.cpp を使ってみていました。 あれか...