Watchface作成、続けま〜す。

初めて、経鼻孔内視鏡を体験してきました。とても感動したので、ちょっとだけ感想。
経口内視鏡の場合、私は挿入時の咽頭反射が苦手で、筋肉弛緩剤やら鎮静剤など、使用可能なあらゆる手段を使って検査してもらいました。しかし、経鼻孔内視鏡は、キシロカインゼリーで鼻から喉を麻痺させるだけでOK。鎮静剤も使わず、口も塞がれていないので、医師と会話しながら、自分の中身を観ることができました。頭では理解していても、いざ体験してみると、負担の少なさに驚かされます。最新の電子スコープの細径化もさることながら、画像の良さにもビックリしました。解像度があがっているし、明るさも発色も超絶進化してます。う〜む、、OLYMPUSさん、素晴らしいです! 低侵襲医療機器の開発、これからもよろしくです。

さて、前回に続けて、Watchfaceの作成です。
 
 

Princess-SUWA
つづけるのじゃ!

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のロジックからの出力は、ここまでの作業で終了とします。
背景画像の設定や外部フォントの使用に関する情報は、またこんど。
 
 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください