プログラム」カテゴリーアーカイブ

DirectShow Extend Filter Library 0.16公開

ある意味大変な間違いをしていたためにlibvpxのコンパイルが通らなかったことがわかったので改めてビルドし直しました…。

 

x86用のプロジェクトを作製した後のmake cleanを忘れるとこうなるのか…

というわけで真相がこれ。x86用の環境とx86-64用の環境はほぼ同一で作るようにしていたのでconfigureをx86用で通してmakeしたものをコピーしてlibvpxのライブラリを作成してそのままconfigureでx86-64用の設定をしてmakeをして…と思っていたのですが、どうもこれがまずかったようです。

x86用の設定が残ったままとなり、x86-64用の各種定義やらアセンブラのコンパイル環境がうまく設定されなかった結果、x86-64用のライブラリの作成に失敗していた、が真相だったようです。ちなみにmakeでその手のファイルも作り直されるのを失念していたのでただの間抜けですね。vcprojをコピーしただけではその辺の設定が正しく通らないので注意しましょう。

 

x86用のプロジェクトとx86-64用のプロジェクトを「ディレクトリ単位で」分けることで解決

ちょっとデータ容量がもったいないですが、ビルドできないよりましかな、という結論です。そのデータ量を惜しむならばハードリンクでもすればいいのですが、さすがにそちらの方が作業の手間なのでこういう結論になりました。こんなことで悩む人は多くないと思いますが、気をつけるべき点ですね。

 

Vectorのライブラリも更新

こっちはこっちで一体何年ぶりなのでしょうかね。毎月通知だけは受け取っていたのですが。しばらくたったら正式公開されると思いますのでそちらからダウンロードしたい人はちょっと待っていてくださいね。

 

DirectShow Extend Filter Library 0.15公開(ただしx86版のみ)

ただし書きが悲しいですよね…。x86版の方は形になりましたのでここまででいったん公開です。

 

放置しすぎたためにGUIDが違うわライブラリがビルドできないわ…

発端は「使ったときにWMVやWebMがうまく再生できない」というメールでした。少しだけ時間の余裕ができたので調べてみようと思いビルド環境を組み上げ…ることがなんと至難なことか。

まあ、わかりやすく言うとさすがに10年ほど前にビルドしたものなので環境が違いすぎること。特に

  • VisualStudioのバージョンを2010から2017への変更
  • WebM系のライブラリをできる限り最新環境へとアップデート

の2点を行ったのですが、特に後者がかなり難しかったというのが大変だった理由で、今回x64版がビルドできなかった理由だったりします。

 

webmdshow(WebMをDirectShow経由で再生するライブラリ)が2015年以降ほぼ更新されていない!

そう、今回の最大の問題点がこれだったけです。つまりVisualStudio2017(やそれよりも新しいVisualStudio)を前提にしていないコードのままになっていた、というのが問題だったわけです。特に

  • DirectShowの基本ライブラリ(BaseClasses)と同じ名前を使っているために名前空間の分離が必要(これは前から)
  • オーディオの読み取り部分でVorbisを読み込むパターンしかなく、Opusを読み込むパターンが用意されていない
  • 付属のlibvpxが古いため最新のlibvpxをビルドする必要がある

の3点が問題になりました。1点目は根性で相変わらずカバーです。2点目については今回Opusに関しては元から変換フィルタだけは用意されていたのでwebmdshow側でOpusが来たときにフォーマットを認識するコードを追加することでこれはなんとか回避しました。ところが3点目についてlibvpxはx86版はビルドできたのですが、x64版はアセンブラがコンパイルできないためにライブラリの生成に失敗する、という現象でストップしてしまいました。ソリューションの作成はLinux側で作ることで回避できるのですが、アセンブラがコンパイルできない問題はさすがに予定外です。何が悪いのか今現在はさっぱりわからないのでこちらは保留状態になっています。

 

Visual Studio 2017に対応していないライブラリ群は除外することに

一部のライブラリが古すぎてコンパイラのコード生成に失敗したりライブラリのリンクに失敗するという問題がありましたので0.15の段階でサポートを外すことにしました。もし使いたい場合は一応0.14版も残しておきますのでそちらを利用してみてください。何のサポートがなくなったはソフトウェアのページで確認してみてください。

 

micro:bitのタスクシステムを考察してみた

というわけで、なんとなく気になったので書いてみたくなったネタです。電子工作系と教育系を兼ね備えるものといえばmicro:bitな訳ですが、そのタスクシステムにちょっとした疑問があるので考察して+調べてみよう、というわけです。

 

MakeCode(Scratch)でmicro:bitのプログラムを作った時を前提とする

micro:bitで動くプログラムを作ることができるツールはいくつかあるわけですが、今回はMicrosoftのMakeCodeを前提としたいと思います。MuやらPython Editor for micro:bitやらあるのですが、小学校や中学校でも使えるレベルで、となると大半がMakeCode経由のような気がしますので、これで話をしたいと思います。

 

「ずっと(forever)」を何個も使うと一体どんな実行のされ方をするのか?

まずはこれを見てください。

 

MakeCodeである3つのブロックを使おうとしたときの状態です。見てわかるとおり「最初だけ」のように複数あると意味がわからなくなるものや「ボタン○○を押したとき」のように、入力の割り込みによって動くのものは1つしか有効にならないようになっています。これはわかります。

ところが、「ずっと(forever)」に当たるブロックを作ろうとすると上の図にあるように2個作ってもどちらも有効です。なお、基本的には何個でも有効になります。つまり、「すべて動作させることができる」という(プログラムをやったことがない人から見ると)不思議な現象が発生します。だとすると「Aをずっと繰り返す」「Bをずっと繰り返す」「Cをずっと繰り返す」を同時にしたいときに「A、B、Cの順にしてそれを繰り返す」のように無理に直列化して書かなくても個別に書いてよい、ということになるのでしょうか。これをちょっと見てみたいと思います。

 

次のように書くとどう実行されるのか?

というわけで、こういうプログラムを作りました。

「ずっと」ブロック×3と「ボタンAが押されたとき」の動作です。ちなみにこれはちょっとしたトリックがあって、「ずっと」のブロックの上下が0の出力と256の出力だと256の出力が下になるように配置しています。

で、これを(あくまでシミュレータ上ですが)実行するとこういう動きになります。

「0を出力」→「256を出力」→「512を出力」→「0を出力」→「256を出力」→「512を出力」→「0を出力」→…

つまり、「ずっと」のブロックを上から3つを順番に回しながらに実行しているだけ、となりました。ちなみにボタンAによる割り込みをかけてみたのですが、「ずっと」による実行順番は変わらず、という結果になっています。あくまでシミュレータ上ですのでオシロスコープなどで実機計測すると微妙に違うかもしれません。

これについてはある程度推測ができて、

  • 「ずっと」ブロックを使うとそれぞれがタスクとして独立に実行待ちキューに入る
  • 実行時間になると実行待ちキューの先頭にあるタスクが実行状態となり実行される
  • ブロックの実行が終了すると再度実行待ちキューの最後に入り待機状態となる
  • 割り込みは特別なタスク扱いとなり、「ずっと」のタスクが実行されていないときにチェックされて状態が確認されればタスクとして実行される

という動きになっているのではないか、というものです。で、これをチェックするために「このプログラムをPython(もどき)で表したもの」とタスク実行に関する説明書(のようなもの)を見て確認してみました。

 

このプログラムをPythonで表すと…

MakeCodeのPythonで表す機能を使ってプログラムを変換するとこうなりました。

def on_button_pressed_a():
    pins.analog_write_pin(AnalogPin.P0, 768)
input.on_button_pressed(Button.A, on_button_pressed_a)

def on_forever():
    pins.analog_write_pin(AnalogPin.P0, 0)
basic.forever(on_forever)

def on_forever2():
    pins.analog_write_pin(AnalogPin.P0, 256)
basic.forever(on_forever2)

def on_forever3():
    pins.analog_write_pin(AnalogPin.P0, 512)
basic.forever(on_forever3)

どうでしょうか。「ずっと」の3つのブロックがon_forever関数、on_forever2関数、on_forever3関数の3つとして定義され、basic.forever関数を呼び出して渡されています。このコードとシミュレータの動きから推測するとbasic.foreverの動きは「渡された関数を(無限実行をする)実行待ちキューに登録する」ものだと考えられます。リファレンスのbasic.foreverの説明ではforeverのループとeventのループについて少し書いてありましたが、この動作については明確には改訂ないような気がします。

 

タスク実行に関する説明から考察してみる

で、このforeverの動きや「バックグラウンドで実行する」とはどういうことか?を説明しているのが(直リンクは張りませんが)「The micro:bit – a reactive system」というところです。micro:bitのタスク実行について実行間隔やポーリング、タスクを並行(Concurrent)で実行する方法について、ボタンを押す、などのイベントがあったときにどう動くのか?といったことについて詳しく書いてありますので見てみるとよいと思います。プログラム、特に組み込み処理に関して詳しい人ならば読めると思いますが、今回の処理に必要な部分を読んでみると、

  • サブルーチン(この場合はforeverとして登録されるタスク)を登録するときには優先度がないタスクとして実行待ちキューに入る
  • 一時停止(Pause処理)がタスク上で発生したときに一時停止キューで時間待ちを行う
  • システムによりタスクが実行可能となったときは実行待ちキューの先頭にあるタスクを削除し実行状態に戻す
  • 実行終了するか一時停止時間が経過したサブルーチン(foreverタスク)は実行待ちキューの最後に戻す

と書いてあることから上の考察の大半は合っているのではないか、と思われます。

 

「ずっと」ブロック内の時間待ちについて

micro:bitの時間待ちのうち「一時停止」よる時間待ちは上の説明から「一時停止キューにタスクを移す」ことにより待ちを行っていますので一度実行状態から抜けることになります。そのため、別のforever処理や入力割り込みによる処理などがあればそれを実行する時間がとれることになります。しかし「whiteなどによる無駄ループを使った時間待ち」は上の説明からmicro:bitのタスクとして待ち状態や実行待ちには移らず実行状態のままになりますのでタスク切り替えがうまくできません。そのため、入力の検知などを行う時間で割り込みそのものは検知できるのですが、割り込み後に動かすルーチンは実行待ちキューに移されるだけとなり実行されない、ということになるかと思います。

これは特にforever関数で長い処理を実行するタイプのタスク+ある程度の反応速度が求められる処理だとちょっと厳しいことになるかと思いますのでロボット操作をやるときやある程度速い周期で処理する必要があるルーチンでは気をつける必要があるかと思います。そもそもタスクの切り替え周期もどれだけ出せるのか微妙なところですか。

 

単に教育用として簡単なものを作るだけなら知る必要はないが…

例えば自由研究などで複雑なプログラムを作り実行させるとうまく動かない、というときにこういうことが絡んでいる可能性はあるかな~という例でした。MicroPythonを入れる例だとこういう風に動くのかどうかはまた別の検証が必要そうなので今はしません。ADVゲームシステムなどで本体内に別のスクリプトシステム(Luaなど)を使うタイプだと似たような現象が発生するのでちょっと調べてみた、というところにしておいてください。はい。

 

 

CentOS7でPHP7.2からPHP7.4にバージョンアップ。ただ簡単すぎた。

ただいま仕事がないのでサーバ系やフリーソフトのバージョンアップをしながらメンテナンスをしている状況です。で、今回はPHPのバージョンアップ。今までPHP7.2系を使っていましたがセキュリティメンテナンスの期限も過ぎてしまったのでさすがにまずいということでPHP7.4系にバージョンアップすることにしました。この手のバージョンアップは状態によっては手順がかなり面倒だったりするのですが…。

 

Remi経由でPHP7.2をインストール済みの環境から

今回の前提条件がこれ。CentOS8のように元からPHP7.2が入っている環境ではなくRemi経由でPHPのバージョンが7.2系にバージョンアップ+設定がちゃんとなされている状態から始まっています。これのおかげでこの後の作業がとんでもなく楽な作業になってしまいました。

 

Remi経由でPHP7.2が入っているならリポジトリを微妙に変更してアップデートを行うだけであっさり終わり

そう。単にアップデートを行うだけで終わりだったわけです。PHP7.2系のリポジトリはremi-php72なので、remi-php74を指定するとPHP7.4系のリポジトリに切り替わります。そのため、とりあえず最新の状態まで更新が完了すれば一発

$ sudo yum update --disablerepo=base,updates --enablerepo=remi,remi-php74

これだけで終わりです。簡単でしょ?まあ、アップデートするときに一時的にPHPに関するサーバを止めてしまったもよかったのかもしれませんが…。あとは更新対象になったものをすべて更新すれば完了です。設定もそこまで違うことはないので使い回しできそうですし、更新の途中でPHP Warningが大量に出てきますがこれもそれほど気にする必要はないと思います。

 

後は運用しながら様子見

とりあえずblogも問題なく動いているようですし、あとは不具合が見つかれば設定などを見直していく、という感じになるかと思います。WordPressのプラグインもそうですが、この手の更新についてもちゃんと確認していかないとセキュリティメンテナンスがされていないものを使っているとどこからアタックが仕掛けられるかわからないですからね。ちゃんとやっていきましょう。

久しぶりにBlog(WordPress)の広告系設定を見直してみた

いろいろと忙しかったのでその手の設定を放置していたのですよ…。ちょうどGoogleの広告に関する状態を見に行ったときにいろいろと警告も出ていたのでいくつか修正してみることにしました。

 

AMPを導入

この場合のAMPはAccelerated Mobile Pagesの方です。モバイル系でアクセスされたときに速度を向上させるための技術ですね。出た当初はWordPressへ導入するのがかなり大変だったことと、とりあえずWPTouchでモバイルページ側をどうにかしていたので放置しておいたのですが、今回プラグインの導入とともにWPTouchを破棄することにしてみました。メニューとかがなくなって見づらくなっていると思いますが、モバイル版の方は後でテーマを変更して調整する予定です。プラグインは一応2種類あるようですが、公式に近いと思われる方を導入しています。もう片方の方は有料モードがあるのでちょっと怪しいということで今回は使いません。

 

Google広告のプラグインも変更

AMPを導入することで問題になるのが広告ユニットの問題。AMPではJavaScriptが使えない影響でそのままでは広告ユニットが表示できない、という問題があります。…まあ、なんとなくですがここ数年はWPTouch側でも広告を出す処理を設定にしていないような気がしているのでそれはそれでいいのかもしれませんが…。とりあえずAMP対応かつ有料にならないものを探す、ということで今回はAd Inserterを導入してみました。解説ページなどから設定をしてとりあえず動く状態には持って行っています。ヘッダ部への設定およびAMPのページでのみ動作する広告と通常ページで動作する広告を混ぜるのがちょっと大変でした。また特に設定箇所を表示する機能が地味に使えるのがうれしいところで、挿入箇所が予定していたポイントでなかったときにデバッグ的に使うことができました。なお、設定を少し代えてトップページの広告だけ第一記事と第二記事に表示するように設定しています。

 

そのほか詳しいことは別のサイトに譲ります

今回は説明サイトに従って設定してみたただの記録なのでこれで終わりです。WordPressでAMPを導入してかつGoogleなどの広告を表示させるのであればWordPressのプラグインであるAMPとAd Inserterの組み合わせがそれなりにいいのでは?という個人的感想を書いて終わりにします。