高見知英の技術ログ

技術関係のログをQiitaから移行してきました。プログラミングのほか、使っているアプリの細かい仕様についてなど書いていきます。

Element.requestFullscreen() APIはほかのウィンドウには使えない(っぽい)

きっかけはこの辺から。

github.com

ブラウザ上の任意の要素を画面いっぱいに表示するには、Element.requestFullscreen()というAPIを使います。

developer.mozilla.org

このAPIですが、どうもwindow.open()によって開かれたウィンドウから、元のウィンドウを操作することはできないようです。

というのも該当のAPIをウィンドウから開くとエラーが返るので。

document.body.requestFullscreen()
// Promise {<pending>}[[Prototype]]: Promise[[PromiseState]]: "fulfilled"[[PromiseResult]]: undefined (ウィンドウが最大化される)
window.opener.document.body.requestFullscreen()
// Promise {<rejected>: TypeError: fullscreen error
//    at <anonymous>:1:29}[[Prototype]]: Promise[[PromiseState]]: "rejected"[[PromiseResult]]: TypeError: fullscreen error
//    at <anonymous>:1:29(画面はなにも変わらない)

Chromewebkitプレフィックスをつけてもメソッドが呼び出せるらしいので使ってみるも、そちらもうまくいかず。

window.opener.document.body.webkitRequestFullscreen(); // -> undefined (なにもおこらない)

undefinedじゃあないんだよ・・・(まあこちらはdocument.body.webkitRequestFullscreen()を呼んでもなにもundefinedが返るのでそもそもそういうものっぽい)。

ちなみに「F11(ウィンドウの全画面化)」をエミュレーションすればなんとかなるのか?と思いましたが、それもダメっぽいです。

document.dispatchEvent( new KeyboardEvent( "keydown", { keyCode: 122 }) ); // -> trueが返って来るも、なにもおこらない

まあここは素直にユーザーに全画面表示の操作を提示するのが筋 というところでしょうか。

YouTubeの動画をプレイリストに自動登録するツールを作った

YouTubeには、以前プレイリストに動画を自動追加する機能がありました。ただ、いつの間にかこの機能は削除されてしまいました。

アップロードした動画の場合はアップロード中の設定画面でプレイリストを選択できるのでそんなに登録し忘れることはないのですが、ライブ配信の場合、プレイリストに動画を登録するタイミングがないので忘れてしまいがちです*1

そんなことで動画を自動的にプレイリストを自動登録するツールをGASで作りました。

gist.github.com

使い方

使い方はこのスクリプトをGASの新規プロジェクトに貼り付けるだけ。トリガーを設定して定期的に実行するように設定すればすぐ使えます。

以下の条件をすべて満たす動画が直近にアップロードされた50件の動画にあったときに、その動画をプレイリストに登録します。

  • 動画のタイトルの先頭が「プレイリストの名前:動画のタイトル」になっている(:は全角でも半角でも構いません)
  • その名前のプレイリストが存在する
  • そのプレイリストに該当の動画が登録されていない

プレイリストの自動作成などは(想定外のプレイリストが作られないように)行っていませんので、比較的安心して動かせるツールかと思います。

やってること

やってることは単純で、次のような処理を行っています。コメントにも一応書いてありますが。

  1. まず自チャンネルの情報と自チャンネルのプレイリスト一覧、最新50個の動画一覧を取得する。
  2. ビデオをForeachでまわして「プレイリストの名前:動画のタイトル」になっている動画を探す。
  3. プレイリストの名前が実在するプレイリストであるかどうか確認する(そうでなければcontinue)。
  4. 3で見つけたプレイリストに、探した動画が既に登録されているかどうか確認する(もうあればcontinue)。
  5. プレイリストに動画を登録する。

YoutubeAPIはOAuthを使うなど事前準備が多くて面倒ですが、Google Apps Scriptであれば簡単に使うことができますので便利です。レコードの構造が複雑だったりしてやや使いづらいのは変わり無しですが・・・。

注意点

Google Apps ScriptのYouTube APIには、YouTube.newPlaylistItemSnippet()などのメソッドがあり、おそらくAPIの動作に有用なレコードを生成することができます。

ただし、例えば階層構造があるレコードなどそのままメソッドを呼んだだけでは動作しないものがあるため、これらは使わずGoogle Apps Scriptのリファレンスにかかれているレコードを自分で作ったほうがよさそうです。

参照情報

*1:とくにStreamYardやRECentralなどを使って動画枠を作成し配信する場合、YouTubeを表示するタイミング自体が全くありませんので

PowerShellでパスワードを生成する(.NET Coreな環境でも動くバージョン)

表題の通りですがPowerShellでパスワードを生成する方法です。

PowerShellでパスワードを生成するというと、多くのサイトでSystem.Web.Security.Membership#GeneratePassword()メソッドを使う方法が紹介されていますが、.NET Coreのみが入っているような環境だと、このメソッドが存在しないため、パスワードの生成ができません。

ということで、上記メソッドを使わずにパスワードを生成するメソッドを作ってみました。

gist.github.com

やっていること

引数より英字、数字、記号の三種の要素をパスワードに含めるか、文字数は何文字かを指定し、含める文字種を変数に格納、その後、その中からランダムに文字を出力するというコードとなります。

同じ文字は2度と使わないような仕様になっているため、指定した文字種に存在する文字以上の長さの文字数を指定しても、文字種の文字数以上の値は出力されません。

便利な使い方

いちおう上記コードのコメントにも書きましたが・・・

  • 関数をのあとに| clipというコマンドを付け加える→そのままクリップボードにコピーする
  • Microsoft.PowerShell_profile.ps1(WindowsPowerShellまたはPowerShellフォルダ)に書き加えると、どこでも使えるようになる

そんなに使わないサービスだけどとりあえずパスワードはそこそこに強固なものを使っておきたい という場合に使ってみると便利かもしれません。

参照内容

結局今Lazarusを使う理由とは

このブログはLazarus(FreePascal)アドベントカレンダー25日目の記事です。

qiita.com

大オチ。

で、結局今Lazarusを使う理由とはなんなのか。

一言で言うと、そんなものはないに尽きます(権利関係とか分からないので画像略)。

ただでさえ言語自体がマイナーで、開発環境もマイナーで、(Delphiの)VCLとの互換性もあるようでないような環境。基本的に半分以上過去のDelphiの思い出で使うくらいのことしかないのかな と思います。

とくにプログラミングにおいて「検索ができない」というのは結構致命的。

もちろん自分が複数言語を使えれば他の言語で書かれたノウハウ記事をPascal訳して使う などというようなこともできますのである程度検索できる範囲も広がりますが、結局それでも「じゃあそれPascal(やLazarus)でどうやるのよ」になってしまうことも少なくなく。

少なくともはじめての言語や、ビジネスシーンで使うような言語にはお勧めできません。

じゃあなんで今回Lazarusを使ったのよ

じゃあなんで今回Lazarusを使ったのかというと、唯一Lazarusくらいしか候補が残らないシーンがあると思っていて・・・。

  • デスクトップ用の実行バイナリが作れる(スクリプト言語でない)環境が欲しい
  • GUIが表示したい
  • でもGUI構築にそんな時間はかけたくない(IDEにデザイナーが欲しい)
  • 開発に関われるタイミングが決して多くないのですぐ使える環境が欲しい

たとえば個人や小規模開発であればVisual Studio Communityなども使えますが、インストールサイズが結構大きい上に、アップデートが頻繁にあるので、「さあ久しぶりにアプリでも作るか」というときにアップデートで1時間近く時間が潰れる とかいうことになったりする(実際あった)。

そういうときにとりあえず気が向いたときに起動してもすぐ使えるLazarusは、割とこういうときにはいい選択肢になり得るのではないかな?と思います。いちおうChocolateywingetでもインストールできるし、アップデートもそちらに管理させることもできるので、アップデートなどの運用負荷もそれほどないし。

ホビーアプリ開発には、Lazarus?

なので、結局休日だけササッとアプリを作る、ちょっとした不便を解消したいので終業後の時間を少し使う とかいう開発の選択肢には、Lazarusは入ってくるのかな?と思います。

「今更デスクトップアプリ開発?」という声もありそうですが、半ば定番化している付箋紙アプリやランチャーアプリなども、10年やそこらくらい昔に作られ、メンテナンスが止まっているものも少なくない。

そんな今、「デスクトップ環境をあらためて見直す」ということが必要になる場合だってある。

そんなときにアプリを作る環境の選択肢として、Lazarusというのは、まあ、なくもない 気がします*1

現状のLazarus

ただ、現状のLazarusは、クロスプラットフォーム開発も可能ではありますが、基本的には機械語環境を意識しなければいけないシーンも少なくない。

ちょっとしたタイミングでふと起動するアセンブラビュー、ポインタの概念を意識せざるをえないデータ型、元々教育向け言語であったということから、一見分かりやすくはあるもののカッチリしすぎててパッと使いづらい言語仕様など、今じゃあLazarusを Pascalを使うかというと、どうだろう?と思うこともあるのかなあ と。

だからこそもしLazarusが今後も生き残るのであれば、普及するのであれば、せめて機械語環境を意識しなくても使える環境はもっと一般的になって欲しいなあ と、思ったりはします。

まとめ

ということで、ここ一ヶ月Lazarusについていろいろ記事を書いてきましたが、とりあえず現状のLazarusは「無理に使う必要はない」環境。

ただあまり頻繁にプログラミングに関われないなど「それくらいしか候補が残らない」という状況はなくもないかな という感じです。

であれば、もう少し情報が豊富に、久しぶりにまたPascal言語を使うときに困ることがないような環境に、なって欲しいなあ なんて思い、今回は25日まで連続で記事を書く なんていう暴挙に出てみました。

*1:まあよほどキビキビ動くことを要求しないのであればふつうにPythontkinterあたりを使って作っても良いんじゃない?という気もしますが。うちもtksugarなんてモジュール作ってるわけですし

標準ライブラリのソースコード読解のススメ

このブログはLazarus(FreePascal)アドベントカレンダー24日目の記事です。

qiita.com

24日は標準ライブラリのソースコードについて。

Pascalはやはりマイナーな言語です。とくにDelphiではなくあえてFree Pascalを使う という人は更に少ない。

あえてLazarusを使うのが検索に余計なものが引っかからない(というより読める情報が何も引っかからない)というくらいとにかく情報が少ない。

そんな中なのでとりあえず動作しているということが確約されているという標準ライブラリのソースコードは非常に貴重な情報源です。

ググって見つかる情報もあるけれど・・・

もちろん、基本的な情報であれば、Delphiの情報がそのまま流用できたりしますし、Lazarusを使って何か作っている方も少なからずいるので検索して見つかる情報もなくはない。

でもそのコードが今のFree Pascalのバージョンで動くかどうか というと、確証がなかったりしますし、動作イメージもパッと分かりにくかったりします。

そのため、普段使っていてなんとなく「どういう動作をするか」が分かっていて、現状のFree Pascalバージョンでも動くことが確約されている標準ライブラリのソースコードは非常に貴重です。

ソースコードを読むには?

Lazarusから標準ライブラリのソースコードを読むには、キーワードをマウスオーバーして出てくるヒントからファイルの名前をクリックするか、Ctrlキーを押しながらキーワードをクリックします。

f:id:TakamiChie:20211218184428p:plain
ソースコードを読む

クラス名をクリックするとクラスの定義箇所に飛ぶことができるなど、地味に優秀です。こういうコードを読んで、「ああ、こういう書き方があるのか」とか「こういう機能があるのか」というのを知る というのも良いかなと。

Lazarus(というかPascal)のデータ型について

このブログはLazarus(FreePascal)アドベントカレンダー23日目の記事です。

qiita.com

今回の内容はPascalのデータ型について。

Pascalのデータ型はちょっと特徴的で(といっても、最近PythonJavaScriptなど明確に型のない言語しかつかってないのでどれだけ特殊なのかは分からないのですが)、いくつかの種類のデータ型があります。

  • クラス型
  • 構造体型
  • プリミティブ型
  • 配列型
  • ポインタ型
  • 関数型(関数のポインタ型)
  • メソッド型(メソッドのポインタ型)

特に注意が必要なデータ型いろいろ

プリミティブ型の扱い

プリミティブ型だけみても結構な種類があり、数値だけでもInteger、Cardinal型、DWord型、QWord型、UInt型などいろいろな型があります。

基本的にはOSのビット数などで定義が切り替わるInteger型かCardinal型あたりを使うのが安全 ということだったと思いますが(Delphiのときには)、型を指定してデータ型を要求してきたり、戻り値が指定されたりすることもあり、実質おなじデータ型でも型が違うと引数に指定できない場合があるので、そういうものだくらいは覚えておいた方がいいです。

LCLオブジェクトなどのCaptionプロパティの型であるTCaptionも、辿っていけばString型です。先日ちょっと触れたヘルパークラスメソッドも、使うことができます。

これらはLazarusのソースエディタ上でデータ型にカーソルを合わせるか、Ctrlキーを押しながらクリックすることで、大元となっているデータ型を知ることができます。正直この辺はぱっと見分かりづらいので気になったら調べておくと良さそう。

f:id:TakamiChie:20211215111713p:plain
データ型の情報表示

また、Windows APIやOLEオブジェクトにデータ型を引き渡すときはPCharやPWCharなどのデータ型を指定する必要があります。これはポインタ型ではありますが、文字列型をキャストすることで作成できます。

uses
  Windows…;


{中略}

procedure TForm1.FormCreate(Sender: TObject);
begin
  SetWindowText(Self.Handle, PChar('TEST'));
end;

クラス型

また、Pascalにはガベージコレクションがありませんので、クラス型の場合データの解放処理が必要となります(Object.Freeメソッド)。Pythonを使ってる身からすると「withでいいやん」くらいに思ってしまうのですが、そういう便利構文はないようです。

constructor TLocalizer.Create;
var
  r: TResourceStream;
begin
  FLanguage:='def';
  r := TResourceStream.Create(HINSTANCE, 'LANG', RT_RCDATA);
  try
    FLocalizeFile := TMemIniFile.Create(r, []);
  finally
    r.Free;
  end;
end;

なお、クラス型以外のデータはスコープから抜けた時点で解放されるのでメモリの解放処理は必要ありません。

配列型

Pascalでは関数が特定の型の配列を返すときなどは、配列型の定義が必要です。

type TIntArray= array of Integer;

function Test: TIntArray;
begin
  Result:=[1,2];
end;

begin
  WriteLn(Test[0]); // -> 1
  ReadLn;
end.

ただし、開発環境が結構よろしくガイドを表示してくれるので…。

しかしそこはさすが静的型付け言語。Lazarusが結構適切にデータ型の情報を表示してくれるので、それほどには迷わなかったりします。

PythonJavaScriptだとそうもいかないのでここは「さすがPascal…」と思ってしまいます(まあ他の言語でも静的型付け言語ならそんなもんだとは思いますが)。

とはいえ分かりづらい部分があるのに変わりはないので、マウスホバー時のヒントやCtrl+Spaceキーなどで表示されるインテリセンスなどを上手く活用したコーディングをしていきましょう。

Lazarusのユニットファイルの循環参照を避ける

このブログはLazarus(FreePascal)アドベントカレンダー22日目の記事です。

qiita.com

22日目はユニットファイルの循環参照について。

ほかの言語と同様、usesでお互いのユニットを参照したプログラムを作ると、循環参照が発生します。

f:id:TakamiChie:20211218182216p:plain
循環参照を示すメッセージ

お互いのユニットでお互いのユニットのメソッドを使うから、循環参照と言われてもなあ となることはたまにあるかと思います。

Pythonなどの場合、たとえばどちらかのimport文をファイルの先頭ではなく実際にクラスやメソッドを使う直前に書くことで循環参照を回避する なんてことも可能ですがPascalの場合uses句が書ける場所は限定されています。その場合どうするか。

implementation句に書く

その場合uses句をimplementation句に書くことで、循環参照を回避することができます。

Pascaluses句はinterface句に書かれていることが一般的なので一見してそちらにしか書けないかと思ってしまいがちですが、別にimplemnentation句に書いても良いようです。

なので、どちらかのユニットからの参照をそちらに移すことで、循環参照を回避できます。