初めて、経鼻孔内視鏡を体験してきました。とても感動したので、ちょっとだけ感想。
経口内視鏡の場合、私は挿入時の咽頭反射が苦手で、筋肉弛緩剤やら鎮静剤など、使用可能なあらゆる手段を使って検査してもらいました。しかし、経鼻孔内視鏡は、キシロカインゼリーで鼻から喉を麻痺させるだけでOK。鎮静剤も使わず、口も塞がれていないので、医師と会話しながら、自分の中身を観ることができました。頭では理解していても、いざ体験してみると、負担の少なさに驚かされます。最新の電子スコープの細径化もさることながら、画像の良さにもビックリしました。解像度があがっているし、明るさも発色も超絶進化してます。う〜む、、OLYMPUSさん、素晴らしいです! 低侵襲医療機器の開発、これからもよろしくです。
さて、前回に続けて、Watchfaceの作成です。
waf configure は、無事に終わったでしょうか?
Setting top to : /Users/zieya/pebbledev/pebble-prj/[プロジェクト名]
Setting out to : /Users/zieya/pebbledev/pebble-prj/[プロジェクト名]/build
Checking for program gcc,cc : arm-none-eabi-gcc
Checking for program ar : arm-none-eabi-ar
‘configure’ finished successfully
こんな表示が出たらOKです。
では、出力された雛型ソースをみてみましょう。
作成したプロジェクトのフォルダ配下に、src フォルダが出来ているので、この中をチェック。
“beats-jp”というプロジェクトであれば、”beats-jp.c”、”test”というプロジェクトであれば、”test.c”というファイルが出力されています。
#include “pebble_os.h”
#include “pebble_app.h”
#include “pebble_fonts.h”
#define MY_UUID { << uuidgen -hdrした値 >> }
PBL_APP_INFO(
MY_UUID, “Template App”, “Your Company”, 1, 0, /* App version */
DEFAULT_MENU_ICON,
APP_INFO_STANDARD_APP);
Window window;
void handle_init(AppContextRef ctx) {
(void)ctx;window_init(&window, “Window Name”);
window_stack_push(&window, true /* Animated */);
}
void pbl_main(void *params) {
PebbleAppHandlers handlers = {
.init_handler = &handle_init
};
app_event_loop(params, &handlers);
}
[Generated by Pebble sdk]
たったこれだけなのですが、コイツが Pebble で作成できるアプリの基本骨格です。
こいつを少し見てみましょう。
#include “pebble_os.h”
#include “pebble_app.h”
#include “pebble_fonts.h”
include部分、実は個人的にちょっと戸惑った部分でした。あれ? stdlib や stdio は?
標準関数の include 文は、すべて pebble_os.h で定義済みでした。
定義済みの標準ライブラリは以下のとおりです。
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <time.h>
#include <string.h>
[Quote from pebble_os.h]
次に PBL_APP_INFO.
PBL_APP_INFO(
MY_UUID, ・・・ 普通にUUIDです。アプリの個別識別子
”Template App”,”Your Company”,1, 0, ・・・ アプリ名、会社名、バージョン、リビジョン
DEFAULT_MENU_ICON, ・・・ アイコンリソースかな?
APP_INFO_STANDARD_APP); ・・・ アプリの種類だと思う
これは、WindowsやMacでいうところの、アプリのプロパティといった感じ。
アプリの種類については、pebble_app.hに定義を発見
typedef enum {
APP_INFO_STANDARD_APP = 0,
APP_INFO_WATCH_FACE = 1 << 0,
APP_INFO_VISIBILITY_HIDDEN = 1 << 1,
APP_INFO_VISIBILITY_SHOWN_ON_COMMUNICATION = 1 << 2,
} PebbleAppFlags;
[Quote from pebble_app.h]
今回、Watchface を作ろうと思っていますので、APP_INFO_WATCH_FACE に変更しておきます。
では、いよいよアプリの入り口、pbl_main()、いわゆるmain()関数です。
void pbl_main(void *params) {
PebbleAppHandlers handlers = {
.init_handler = &handle_init
};
app_event_loop(params, &handlers);
}
pbl_main()上のスタックに Pebble の割り込みイベントハンドラを定義して、app_event_loop()のコールバックに代入しているようですね。
インベントハンドラの定義をチェック。
typedef struct
{
PebbleAppInitEventHandler init_handler;
PebbleAppDeinitEventHandler deinit_handler;
PebbleAppRenderEventHandler render_handler;
PebbleAppInputHandlers input_handlers;
PebbleAppTickInfo tick_info;
PebbleAppTimerHandler timer_handler;
PebbleAppMessagingInfo messaging_info;
} PebbleAppHandlers;
[Quote from pebble_os.h]
ふむ、initは初期化、deinit?これは何でしょう?後回し。render?画面更新かな? inputはきっとボタン押下ですね。
tickは、時計のチクタク割り込み、Timerは文字通りタイマーかな? messagingはきっと、母艦からの通知でしょう。
つまり、pbl_main()ですべきことは、大きく2つです。
・フックするイベントと、Callする関数のポインタを紐付ける。
・アプリケーションのイベントループをグルグルまわす。
Pebble SDK をインストールした時にBuildした、超シンプルな時計のソースをみてみます。
void pbl_main(void *params) {
PebbleAppHandlers handlers = {
.init_handler = &handle_init,
.tick_info = {
.tick_handler = &handle_tick,
.tick_units = SECOND_UNIT
}
};
app_event_loop(params, &handlers);
}
[Quote from PebbleKit、example_src.c]
これをみると、initハンドラーに handle_init() 関数へのポインタ、チクタクハンドラーに handle_tick() 関数へのポインタを紐付けています。
また、チクタクイベントに SECOND_UNIT って指定しているので、1秒ごとにイベント発生するようにしているのかな?
ワタクシの beats-jp も病刻みで時間を表示したかったので、この pbl_main は、丸パクリで良さそうです。
そんな訳で完成したのが、GitHub にアップしたソースです。
背景画像や特殊なフォントは使っていないので、リソースファイルは生成されたままになっています。
ローカルにでもコピーして、./waf build としていただければ、beat-jp.pbw が出来上がります。うまくビルドできるでしょうか?
最後に2点、beat-jp.pbw を作成して気づいたことをメモしておきます。
1)GMTが取得できませんでした。
これは多分、Pebble SDK の制約?gmttime()関数がリンクできませんでした。
本当は、Localtimeを意識しなくてもGMTを正確に取得したかったのですが、それは叶わず。
しかたが無いので、beat-jp.pbw では、Localtimeから9時間減算しました。
9時間の手動オフセットを余儀なくされたので、beats”-jp”としました。
2)恨み節なのですが、標準関数が少ない?
Swatch beat time を出力する時の事です。
sprintf( buffer, "-%03.02F", double_val );
と書けば、一発で終了なのですが、これもリンクできませんでした。更に、、、
sprintf系の関数は、まぁ、何となくそんな予感もしていましたが、itoa()もNGでした。
とりあえず、beat-jpのロジックからの出力は、ここまでの作業で終了とします。
背景画像の設定や外部フォントの使用に関する情報は、またこんど。