Commit 1d70a7c4 authored by Douglas6's avatar Douglas6

initial load

parent 3605001f
{
"appKeys": {
"MSG_KEY_ARTIST": 102,
"MSG_KEY_BUTTON_CODE": 0,
"MSG_KEY_BUTTON_DATA": 1,
"MSG_KEY_MUTED": 104,
"MSG_KEY_PLAY_STATE": 103,
"MSG_KEY_TITLE": 101,
"MSG_KEY_VOLUME": 100
},
"capabilities": [
""
],
"companyName": "douglasotwell@gmail.com",
"longName": "Rockodi",
"projectType": "native",
"resources": {
"media": [
{
"file": "images/pics.png",
"name": "ICON_PICS",
"type": "png"
},
{
"file": "images/info.png",
"name": "ICON_INFO",
"type": "png"
},
{
"file": "images/weather.png",
"name": "ICON_WEATHER",
"type": "png"
},
{
"file": "images/video.png",
"name": "ICON_VIDEO",
"type": "png"
},
{
"file": "images/home.png",
"name": "ICON_HOME",
"type": "png"
},
{
"file": "images/full.png",
"name": "ICON_FULL",
"type": "png"
},
{
"file": "images/goto.png",
"name": "ICON_GOTO",
"type": "png"
},
{
"file": "images/list.png",
"name": "ICON_LIST",
"type": "png"
},
{
"file": "images/button.png",
"name": "ICON_BUTTON",
"type": "png"
},
{
"file": "images/vol_up.png",
"name": "ICON_VOL_UP",
"type": "png"
},
{
"file": "images/vol_dn.png",
"name": "ICON_VOL_DN",
"type": "png"
},
{
"file": "images/power.png",
"name": "ICON_POWER",
"type": "png"
},
{
"file": "images/player.png",
"name": "ICON_PLAYER",
"type": "png"
},
{
"file": "images/remote.png",
"name": "ICON_REMOTE",
"type": "png"
},
{
"file": "images/addons.png",
"name": "ICON_ADDONS",
"type": "png"
},
{
"file": "images/speaker.png",
"name": "ICON_SPEAKER",
"type": "png"
},
{
"file": "images/pause.png",
"name": "ICON_PAUSE",
"type": "png"
},
{
"file": "images/cursor_up.png",
"name": "ICON_CURSOR_UP",
"type": "png"
},
{
"file": "images/cursor_down.png",
"name": "ICON_CURSOR_DOWN",
"type": "png"
},
{
"file": "images/check.png",
"name": "ICON_CHECK",
"type": "png"
},
{
"file": "images/up.png",
"name": "ICON_UP",
"type": "png"
},
{
"file": "images/down.png",
"name": "ICON_DOWN",
"type": "png"
},
{
"file": "images/play.png",
"name": "ICON_PLAY",
"type": "png"
},
{
"file": "images/rockodi.png",
"menuIcon": true,
"name": "ICON_ROCKODI",
"type": "png"
},
{
"file": "images/rev.png",
"name": "ICON_REV",
"type": "png"
},
{
"file": "images/ff.png",
"name": "ICON_FF",
"type": "png"
}
]
},
"sdkVersion": "2",
"shortName": "Rockodi",
"uuid": "77495959-66fe-4db1-ab4b-368369babb00",
"versionCode": 1,
"versionLabel": "0.1",
"watchapp": {
"watchface": false
}
}
// Copyright (c) 2015 Douglas Otwell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#include <pebble.h>
#include "addons.h"
#include "common.h"
#include "basic_menu_layer.h"
#include "player.h"
static Window *s_window;
static MenuLayer *s_menu;
static Layer *s_lyr_loading;
static BasicMenuModel *s_model;
static GFont s_res_gothic_24_bold;
#define ITEMS_BUFFER_SIZE 1024
static uint8_t items_buffer[ITEMS_BUFFER_SIZE];
static DictionaryIterator items_iter;
static void lyr_loading_update_proc(Layer *layer, GContext *ctx) {
GRect bounds = layer_get_bounds(layer);
graphics_fill_rect(ctx, bounds, 0, GCornerNone);
graphics_draw_text(ctx, "Loading...", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD),
GRect(0, 10, bounds.size.w, 28), GTextOverflowModeTrailingEllipsis, GTextAlignmentCenter, NULL);
}
static void load_menu(void) {
Tuple *t = dict_read_first(&items_iter);
while(t != NULL) {
char* id = (char*) t->value->cstring;
char* name = split_id_name_pair(id);
basic_menu_model_add_item(s_model, name, NULL, id);
t = dict_read_next(&items_iter);
}
menu_layer_reload_data(s_menu);
layer_set_hidden(s_lyr_loading, true);
}
static void inbox_received_callback(DictionaryIterator *iterator, void *context) {
dict_write_begin(&items_iter, items_buffer, ITEMS_BUFFER_SIZE);
Tuple *t = dict_read_first(iterator);
while(t != NULL) {
dict_write_cstring(&items_iter, (int) t->key, (char*) t->value->cstring);
t = dict_read_next(iterator);
}
int items_size = dict_write_end(&items_iter);
DEBUG("Size of the written buffer is %d bytes.", items_size);
load_menu();
}
static void inbox_dropped_callback(AppMessageResult reason, void *context) {
ERROR("Message dropped! %s", translate_app_message_result(reason));
}
static void menu_select_cb(MenuLayer *menu_layer, MenuIndex *cell_index, BasicMenuItem *item) {
char* value = item->value;
outbox_send_with_data("EXE_ADDON", value);
window_stack_pop(true);
}
static void initialize_ui(void) {
s_window = window_create();
window_set_fullscreen(s_window, false);
window_set_background_color(s_window, GColorBlack);
Layer *window_layer = window_get_root_layer(s_window);
GRect bounds = layer_get_frame(window_layer);
s_res_gothic_24_bold = fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD);
s_model = basic_menu_model_create();
// s_menu
s_menu = basic_menu_layer_create(bounds, s_model);
basic_menu_model_set_select_callback(s_model, menu_select_cb);
menu_layer_set_click_config_onto_window(s_menu, s_window);
layer_add_child(window_layer, menu_layer_get_layer(s_menu));
// s_lyr_loading
s_lyr_loading = layer_create(bounds);
layer_set_update_proc(s_lyr_loading, lyr_loading_update_proc);
layer_add_child(window_layer, (Layer *) s_lyr_loading);
app_message_register_inbox_received(inbox_received_callback);
app_message_register_inbox_dropped(inbox_dropped_callback);
}
static void destroy_ui() {
window_destroy(s_window);
layer_destroy(s_lyr_loading);
basic_menu_layer_destroy(s_menu);
basic_menu_model_destroy(s_model);
}
static void handle_window_unload(Window* window) {
destroy_ui();
}
void show_addons(void) {
initialize_ui();
window_set_window_handlers(s_window, (WindowHandlers) {
.unload = handle_window_unload,
});
window_stack_push(s_window, true);
outbox_send("GET_ADDONS");
}
void hide_addons(void) {
window_stack_remove(s_window, true);
}
// Copyright (c) 2015 Douglas Otwell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#pragma once
void show_addons(void);
void hide_addons(void);
// Copyright (c) 2015 Douglas Otwell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#include <pebble.h>
#include "basic_menu_layer.h"
#include "common.h"
BasicMenuModel *basic_menu_model_create(void) {
BasicMenuModel *model = malloc(sizeof *model);
model->item_count = 0;
return model;
}
void basic_menu_model_destroy(BasicMenuModel *model) {
for (int i=0; i<model->item_count; i++) {
free(model->items[i]);
}
free(model);
}
void basic_menu_model_add_item(BasicMenuModel *model, char *label, GBitmap *icon, void *value) {
BasicMenuItem *item = malloc(sizeof *item);
item->label = label;
item->icon = icon;
item->value = value;
model->items[model->item_count++] = item;
}
void basic_menu_model_set_select_callback(BasicMenuModel *model, BasicMenuSelectCallback cb) {
model->callback = cb;
}
// menu handlers
static uint16_t menu_get_num_sections_cb(MenuLayer *menu_layer, void *data) {
return 1;
}
static uint16_t menu_get_num_rows_cb(MenuLayer *menu_layer, uint16_t section_index, void *data) {
BasicMenuModel *model = (BasicMenuModel*) data;
switch (section_index) {
case 0:
return model->item_count;
default:
return 0;
}
}
static void menu_draw_header_cb(GContext* ctx, const Layer *cell_layer, uint16_t section_index, void *data) {
}
static int16_t menu_get_header_height_cb(MenuLayer *menu_layer, uint16_t section_index, void *data) {
return 0;
}
static void menu_draw_row_cb(GContext* ctx, const Layer *cell_layer, MenuIndex *cell_index, void *data) {
// graphics_context_set_fill_color(ctx, GColorBlack);
BasicMenuModel *model = (BasicMenuModel*) data;
GRect bounds = layer_get_frame(cell_layer);
GBitmap *icon = model->items[cell_index->row]->icon;
int offset = 4;
if (icon != NULL) {
offset = 44;
graphics_draw_bitmap_in_rect(ctx, model->items[cell_index->row]->icon, GRect(4, 8, 28, 28));
}
graphics_draw_text(ctx, model->items[cell_index->row]->label, fonts_get_system_font(FONT_KEY_GOTHIC_24),
GRect(offset, 4, bounds.size.w - offset, 16), GTextOverflowModeTrailingEllipsis, GTextAlignmentLeft, NULL);
}
static void menu_select_cb(MenuLayer *menu_layer, MenuIndex *cell_index, void *data) {
BasicMenuModel *model = (BasicMenuModel*) data;
BasicMenuItem *item = model->items[cell_index->row];
model->callback(menu_layer, cell_index, item);
}
BasicMenuLayer* basic_menu_layer_create(GRect rect, BasicMenuModel* model) {
BasicMenuLayer* layer = (BasicMenuLayer*) menu_layer_create(rect);
menu_layer_set_callbacks(layer, model, (MenuLayerCallbacks){
.get_num_sections = menu_get_num_sections_cb,
.get_num_rows = menu_get_num_rows_cb,
.get_header_height = menu_get_header_height_cb,
.draw_header = menu_draw_header_cb,
.draw_row = menu_draw_row_cb,
.select_click = menu_select_cb,
});
return layer;
}
void basic_menu_layer_destroy(BasicMenuLayer *layer) {
menu_layer_destroy((MenuLayer*) layer);
}
\ No newline at end of file
// Copyright (c) 2015 Douglas Otwell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#pragma once
typedef struct {
char *label;
void *value;
GBitmap *icon;
} BasicMenuItem;
typedef void (*BasicMenuSelectCallback)(MenuLayer *menu_layer, MenuIndex *cell_index, BasicMenuItem *item);
typedef struct basic_menu_model {
int item_count;
BasicMenuItem* items[32];
BasicMenuSelectCallback callback;
} BasicMenuModel;
typedef MenuLayer BasicMenuLayer;
BasicMenuModel* basic_menu_model_create(void);
void basic_menu_model_destroy(BasicMenuModel *model);
void basic_menu_model_add_item(BasicMenuModel *model, char *label, GBitmap *icon, void* value);
void basic_menu_model_set_select_callback(BasicMenuModel *model, BasicMenuSelectCallback cb);
BasicMenuLayer* basic_menu_layer_create(GRect rect, BasicMenuModel* model);
void basic_menu_layer_destroy(BasicMenuLayer *layer);
\ No newline at end of file
// Copyright (c) 2015 Douglas Otwell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#include <pebble.h>
#include "buttons_window.h"
#include "common.h"
static ButtonsWindow *window;
static ButtonsWindowData buttonsWindowData;
static Layer *s_lyr_background;
static void lyr_background_update_proc(Layer *layer, GContext *ctx) {
GRect layer_bounds = layer_get_bounds(layer);
window = layer_get_window(layer);
ButtonsWindowData* data = (ButtonsWindowData*) window_get_user_data(window);
graphics_context_set_fill_color(ctx, GColorWhite);
graphics_fill_rect(ctx, GRect(0, 2, layer_bounds.size.w, 50), 12, GCornersLeft);
graphics_fill_rect(ctx, GRect(0, 51, layer_bounds.size.w, 50), 12, GCornersLeft);
graphics_fill_rect(ctx, GRect(0, 100, layer_bounds.size.w, 50), 12, GCornersLeft);
graphics_context_set_fill_color(ctx, GColorBlack);
graphics_fill_rect(ctx, GRect(1, 3, layer_bounds.size.w, 48), 12, GCornersLeft);
graphics_fill_rect(ctx, GRect(1, 52, layer_bounds.size.w, 48), 12, GCornersLeft);
graphics_fill_rect(ctx, GRect(1, 101, layer_bounds.size.w, 48), 12, GCornersLeft);
graphics_context_set_fill_color(ctx, GColorWhite);
graphics_fill_rect(ctx, GRect(layer_bounds.size.w - 21,2, 21,layer_bounds.size.h - 4), 4, GCornersLeft);
graphics_draw_text(ctx, data->buttons[0].label, fonts_get_system_font(FONT_KEY_GOTHIC_24),
GRect(0, 10, layer_bounds.size.w - 28, 16), GTextOverflowModeTrailingEllipsis, GTextAlignmentRight, NULL);
graphics_draw_text(ctx, data->buttons[1].label, fonts_get_system_font(FONT_KEY_GOTHIC_24),
GRect(0, 59, layer_bounds.size.w - 28, 16), GTextOverflowModeTrailingEllipsis, GTextAlignmentRight, NULL);
graphics_draw_text(ctx, data->buttons[2].label, fonts_get_system_font(FONT_KEY_GOTHIC_24),
GRect(0, 108, layer_bounds.size.w - 28, 16), GTextOverflowModeTrailingEllipsis, GTextAlignmentRight, NULL);
}
ButtonsWindow* buttons_window_create() {
static struct ButtonsWindowButton button_1;
button_1.label = "Button 1";
static struct ButtonsWindowButton button_2;
button_2.label = "Button 2";
static struct ButtonsWindowButton button_3;
button_3.label = "Button 3";
buttonsWindowData.buttons[0] = button_1;
buttonsWindowData.buttons[1] = button_2;
buttonsWindowData.buttons[2] = button_3;
window = window_create();
window_set_background_color(window, GColorBlack);
window_set_user_data(window, &buttonsWindowData);
Layer *window_layer = window_get_root_layer(window);
GRect bounds = layer_get_frame(window_layer);
s_lyr_background = layer_create(bounds);
layer_set_update_proc(s_lyr_background, lyr_background_update_proc);
layer_add_child(window_layer, (Layer *) s_lyr_background);
return window;
}
void buttons_window_destroy(ButtonsWindow* window) {
window_destroy(window);
layer_destroy(s_lyr_background);
}
void buttons_window_set_label(int id, char* label) {
ButtonsWindowData* data = (ButtonsWindowData*) window_get_user_data(window);
if (id >= 1 && id <= 3) {
data->buttons[id - 1].label = label;
}
}
// Copyright (c) 2015 Douglas Otwell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#pragma once
#include <pebble.h>
typedef Window ButtonsWindow;
struct ButtonsWindowButton {
char *label;
GBitmap *icon;
};
typedef struct {
ActionBarLayer* action_bar_layer;
struct ButtonsWindowButton buttons[3];
} ButtonsWindowData;
ButtonsWindow* buttons_window_create();
void buttons_window_destroy(ButtonsWindow* window);
void buttons_window_set_label(int id, char* label);
// Copyright (c) 2015 Douglas Otwell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#include <pebble.h>
#include "common.h"
// AppMessage handlers
void outbox_send(char* send_cmd){
DictionaryIterator *iter;
app_message_outbox_begin(&iter);
Tuplet value = TupletCString(MSG_KEY_BUTTON_CODE, send_cmd);
dict_write_tuplet(iter, &value);
dict_write_end(iter);
app_message_outbox_send();
}
void outbox_send_with_data(char* send_cmd, char* send_data){
DictionaryIterator *iter;
app_message_outbox_begin(&iter);
Tuplet code = TupletCString(MSG_KEY_BUTTON_CODE, send_cmd);
dict_write_tuplet(iter, &code);
Tuplet data = TupletCString(MSG_KEY_BUTTON_DATA, send_data);
dict_write_tuplet(iter, &data);
dict_write_end(iter);
app_message_outbox_send();
}
char* translate_app_message_result(AppMessageResult app_message_error) {
char *msg = "";
switch(app_message_error) {
case APP_MSG_OK:
msg = "All good, operation was successful.";
break;
case APP_MSG_SEND_TIMEOUT:
msg = "The other end did not confirm receiving the sent data with an (n)ack in time.";
break;
case APP_MSG_SEND_REJECTED:
msg = "The other end rejected the sent data, with a 'nack' reply.";
break;
case APP_MSG_NOT_CONNECTED:
msg = "The other end was not connected.";
break;
case APP_MSG_APP_NOT_RUNNING:
msg = "The local application was not running.";
break;
case APP_MSG_INVALID_ARGS:
msg = "The function was called with invalid arguments.";
break;
case APP_MSG_BUSY:
msg = "There are pending (in or outbound) messages that need to be processed first.";
break;
case APP_MSG_BUFFER_OVERFLOW:
msg = "The buffer was too small to contain the incoming message.";
break;
case APP_MSG_ALREADY_RELEASED:
msg = "The resource had already been released.";
break;
case APP_MSG_CALLBACK_ALREADY_REGISTERED:
msg = "The callback node was already registered, or its ListNode has not been initialized.";
break;
case APP_MSG_CALLBACK_NOT_REGISTERED:
msg = "The callback could not be deregistered, because it had not been registered before.";
break;
case APP_MSG_OUT_OF_MEMORY:
msg = "The support library did not have sufficient application memory.";
break;
case APP_MSG_CLOSED:
msg = "App message was closed.";
break;
case APP_MSG_INTERNAL_ERROR:
msg = "An internal OS error prevented APP_MSG from completing an operation";
break;
}
return msg;
}
char* split_id_name_pair(char *pair) {
char* pipe_pos = strchr(pair, '|');
if (pipe_pos != NULL) {
(*pipe_pos) = '\0';
}
return pipe_pos + 1;
}
void strip_ext(char *str) {
char* dot_pos = strchr(str, '.');
if (dot_pos != NULL) {
(*dot_pos) = '\0';
}
}
// Copyright (c) 2015 Douglas Otwell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#pragma once
#define MSG_KEY_BUTTON_CODE 0
#define MSG_KEY_BUTTON_DATA 1
#define MSG_KEY_VOLUME 100
#define MSG_KEY_TITLE 101
#define MSG_KEY_ARTIST 102
#define MSG_KEY_PLAY_STATE 103
// convenient macros courtesy of Matthew Tole: github.com/smallstoneapps/pebble-assist
#define DEBUG(...) app_log(APP_LOG_LEVEL_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
#define INFO(...) app_log(APP_LOG_LEVEL_INFO, __FILE__, __LINE__, __VA_ARGS__)
#define WARN(...) app_log(APP_LOG_LEVEL_WARNING, __FILE__, __LINE__, __VA_ARGS__)
#define ERROR(...) app_log(APP_LOG_LEVEL_ERROR, __FILE__, __LINE__, __VA_ARGS__)
void outbox_send(char* button_code);
void outbox_send_with_data(char* send_code, char* send_data);
char* translate_app_message_result(AppMessageResult app_message_error);
char* split_id_name_pair(char *pair);
void strip_ext(char *str);
\ No newline at end of file
// Copyright (c) 2015 Douglas Otwell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#include <pebble.h>
#include "goto.h"
#include "common.h"
#include "basic_menu_layer.h"
static Window *s_window;
static MenuLayer *s_menu;
static GBitmap *s_icon_full;
static GBitmap *s_icon_info;
static GBitmap *s_icon_home;
static GBitmap *s_icon_music;
static GBitmap *s_icon_video;
static GBitmap *s_icon_pics;
static GBitmap *s_icon_weather;
static BasicMenuModel *s_model;
static void menu_select_cb(MenuLayer *menu_layer, MenuIndex *cell_index, BasicMenuItem *item) {
char *value = item->value;
outbox_send(value);
window_stack_pop(true);
}
static void initialize_ui(void) {
s_icon_full = gbitmap_create_with_resource(RESOURCE_ID_ICON_FULL);
s_icon_info = gbitmap_create_with_resource(RESOURCE_ID_ICON_INFO);
s_icon_home = gbitmap_create_with_resource(RESOURCE_ID_ICON_HOME);
s_icon_music = gbitmap_create_with_resource(RESOURCE_ID_ICON_PLAYER);
s_icon_video = gbitmap_create_with_resource(RESOURCE_ID_ICON_VIDEO);
s_icon_pics = gbitmap_create_with_resource(RESOURCE_ID_ICON_PICS);
s_icon_weather = gbitmap_create_with_resource(RESOURCE_ID_ICON_WEATHER);
s_window = window_create();
window_set_fullscreen(s_window, false);
window_set_background_color(s_window, GColorBlack);
Layer *window_layer = window_get_root_layer(s_window);
GRect bounds = layer_get_frame(window_layer);
s_model = basic_menu_model_create();
basic_menu_model_add_item(s_model, "Fullscreen", s_icon_full, "GO_FULL");
basic_menu_model_add_item(s_model, "Info", s_icon_info, "GO_INFO");
basic_menu_model_add_item(s_model, "Home", s_icon_home, "GO_HOME");
basic_menu_model_add_item(s_model, "Music", s_icon_music, "GO_MUSIC");
basic_menu_model_add_item(s_model, "Video", s_icon_video, "GO_VIDEO");
basic_menu_model_add_item(s_model, "Pictures", s_icon_pics, "GO_PICS");
basic_menu_model_add_item(s_model, "Weather", s_icon_weather, "GO_WEATHER");
s_menu = basic_menu_layer_create(bounds, s_model);
basic_menu_model_set_select_callback(s_model, menu_select_cb);
menu_layer_set_click_config_onto_window(s_menu, s_window);
layer_add_child(window_layer, menu_layer_get_layer(s_menu));
}
static void destroy_ui() {
window_destroy(s_window);
basic_menu_layer_destroy(s_menu);
basic_menu_model_destroy(s_model);
gbitmap_destroy(s_icon_full);
gbitmap_destroy(s_icon_info);
gbitmap_destroy(s_icon_home);
gbitmap_destroy(s_icon_music);
gbitmap_destroy(s_icon_video);
gbitmap_destroy(s_icon_pics);
gbitmap_destroy(s_icon_weather);
}
static void handle_window_unload(Window* window) {
destroy_ui();
}
void show_goto(void) {
initialize_ui();
window_set_window_handlers(s_window, (WindowHandlers) {
.unload = handle_window_unload,
});
window_stack_push(s_window, true);
}
void hide_goto(void) {
window_stack_remove(s_window, true);
}
\ No newline at end of file
// Copyright (c) 2015 Douglas Otwell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#pragma once
void show_goto(void);
void hide_goto(void);
// Copyright (c) 2015 Douglas Otwell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#include <pebble.h>
#include "main_menu.h"
static void init() {
app_message_open(app_message_inbox_size_maximum(), app_message_outbox_size_maximum());
show_main_menu();
}
static void deinit() {
}
int main(void) {
init();
app_event_loop();
deinit();
}
\ No newline at end of file
// Copyright (c) 2015 Douglas Otwell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#include <pebble.h>
#include "main_menu.h"
#include "common.h"
#include "basic_menu_layer.h"
#include "player.h"
#include "remote.h"
#include "goto.h"
#include "playlists.h"
#include "addons.h"
#include "power.h"
static Window *s_window;
static MenuLayer *s_menu;
static GBitmap *s_icon_player;
static GBitmap *s_icon_remote;
static GBitmap *s_icon_goto;
static GBitmap *s_icon_list;
static GBitmap *s_icon_addons;
static GBitmap *s_icon_power;
static BasicMenuModel *s_model;
static void menu_select_cb(MenuLayer *menu_layer, MenuIndex *cell_index, BasicMenuItem *item) {
void (*callback)(void) = item->value;
callback();
}
static void initialize_ui(void) {
s_icon_player = gbitmap_create_with_resource(RESOURCE_ID_ICON_PLAYER);
s_icon_remote = gbitmap_create_with_resource(RESOURCE_ID_ICON_REMOTE);
s_icon_goto = gbitmap_create_with_resource(RESOURCE_ID_ICON_GOTO);
s_icon_list = gbitmap_create_with_resource(RESOURCE_ID_ICON_LIST);
s_icon_addons = gbitmap_create_with_resource(RESOURCE_ID_ICON_ADDONS);
s_icon_power = gbitmap_create_with_resource(RESOURCE_ID_ICON_POWER);
s_window = window_create();
window_set_fullscreen(s_window, false);
window_set_background_color(s_window, GColorBlack);
Layer *window_layer = window_get_root_layer(s_window);
GRect bounds = layer_get_frame(window_layer);
s_model = basic_menu_model_create();
basic_menu_model_add_item(s_model, "Player", s_icon_player, show_player);
basic_menu_model_add_item(s_model, "Remote", s_icon_remote, show_remote);
basic_menu_model_add_item(s_model, "Go to", s_icon_goto, show_goto);
basic_menu_model_add_item(s_model, "Playlists", s_icon_list, show_playlists);
basic_menu_model_add_item(s_model, "Addons", s_icon_addons, show_addons);
basic_menu_model_add_item(s_model, "Power", s_icon_power, show_power);
s_menu = basic_menu_layer_create(bounds, s_model);
basic_menu_model_set_select_callback(s_model, menu_select_cb);
menu_layer_set_click_config_onto_window(s_menu, s_window);
layer_add_child(window_layer, menu_layer_get_layer(s_menu));
}
static void destroy_ui() {
window_destroy(s_window);
gbitmap_destroy(s_icon_player);
gbitmap_destroy(s_icon_remote);
gbitmap_destroy(s_icon_goto);
gbitmap_destroy(s_icon_list);
gbitmap_destroy(s_icon_addons);
gbitmap_destroy(s_icon_power);
basic_menu_layer_destroy(s_menu);
basic_menu_model_destroy(s_model);
}
static void handle_window_unload(Window* window) {
destroy_ui();
}
void show_main_menu(void) {
initialize_ui();
window_set_window_handlers(s_window, (WindowHandlers) {
.unload = handle_window_unload,
});
window_stack_push(s_window, true);
}
void hide_main_menu(void) {
window_stack_remove(s_window, true);
}
\ No newline at end of file
// Copyright (c) 2015 Douglas Otwell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#pragma once
void show_main_menu(void);
void hide_main_menu(void);
// Copyright (c) 2015 Douglas Otwell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// MessageQueue implementation is copyright (c) 2014 by Matthew Tole, https://github.com/smallstoneapps/js-message-queue
// Distributed under the MIT license, see above. Many thanks Matthew!
//
var MessageQueue=function(){var RETRY_MAX=5;var queue=[];var sending=false;var timer=null;return{reset:reset,sendAppMessage:sendAppMessage,size:size};function reset(){queue=[];sending=false}function sendAppMessage(message,ack,nack){if(!isValidMessage(message)){return false}queue.push({message:message,ack:ack||null,nack:nack||null,attempts:0});setTimeout(function(){sendNextMessage()},1);return true}function size(){return queue.length}function isValidMessage(message){if(message!==Object(message)){return false}var keys=Object.keys(message);if(!keys.length){return false}for(var k=0;k<keys.length;k+=1){var validKey=/^[0-9a-zA-Z-_]*$/.test(keys[k]);if(!validKey){return false}var value=message[keys[k]];if(!validValue(value)){return false}}return true;function validValue(value){switch(typeof value){case"string":return true;case"number":return true;case"object":if(toString.call(value)=="[object Array]"){return true}}return false}}function sendNextMessage(){if(sending){return}var message=queue.shift();if(!message){return}message.attempts+=1;sending=true;Pebble.sendAppMessage(message.message,ack,nack);timer=setTimeout(function(){timeout()},1e3);function ack(){clearTimeout(timer);setTimeout(function(){sending=false;sendNextMessage()},200);if(message.ack){message.ack.apply(null,arguments)}}function nack(){clearTimeout(timer);if(message.attempts<RETRY_MAX){queue.unshift(message);setTimeout(function(){sending=false;sendNextMessage()},200*message.attempts)}else{if(message.nack){message.nack.apply(null,arguments)}}}function timeout(){setTimeout(function(){sending=false;sendNextMessage()},1e3);if(message.ack){message.ack.apply(null,arguments)}}}}();
// global variables
var ISDEBUG = true;
var g_server_url = "http://192.168.1.76";
var g_user;
var g_password;
var g_player_id;
var g_player_type;
var g_volume;
var g_muted;
var g_play_state;
var JsonRpcRequest = function (method, params) {
this.jsonrpc = "2.0";
this.id = 1;
this.method = method;
this.params = params;
};
function sendJsonRequest(requests, callback) {
var response = null;
var req = new XMLHttpRequest();
req.onload = function(e) {
if (req.readyState == 4 && req.status == 200) {
if (ISDEBUG) console.log("Response text: "+req.responseText);
response = JSON.parse(req.responseText);
if (response.result == null) {
handleJsonRpcError(response);
} else {
if (callback != null) {
callback(response.result);
}
}
}
};
req.onerror = function(e) {
console.log("Error connecting to Kodi");
};
var url_string = g_server_url+"/jsonrpc?request=";
req.open('GET', url_string+encodeURI(JSON.stringify(requests)), true);
req.timeout = 2000;
req.send(null);
if (ISDEBUG) console.log("Sent request: "+url_string);
}
function handleJsonRpcError(response) {
var err_msg = "Unknown error";
if (response.constructor === Array) {
for (var i=0;i<response.length;i++) {
if (response[i].result == null) {
if (response[i].error!= null) {err_msg = response[i].error.message;}
console.log("Kodi responded with an error: "+err_msg);
}
}
} else {
if (response.result == null) {
if (response.error!= null) {err_msg = response.error.message;}
console.log("Kodi responded with an error: "+err_msg);
}
}
}
// player methods
function getStatus() {
g_player_id = -1;
sendJsonRequest(new JsonRpcRequest("Application.GetProperties", {"properties":["volume", "muted"]}), getAppPropertiesCb);
sendJsonRequest(new JsonRpcRequest("Player.GetActivePlayers", {}), getActivePlayersCb);
}
function getAppPropertiesCb(result) {
g_volume = result.volume;
g_muted = (result.muted) ? 1 : 0;
MessageQueue.sendAppMessage({"MSG_KEY_VOLUME": g_volume, "MSG_KEY_MUTED": g_muted});
}
function getActivePlayersCb(result) {
g_player_id = -1;
for (var i=0; i<result.length; i++) {
var player = result[i];
g_player_type = player.type;
if (g_player_type == "audio" || g_player_type == "video") {
g_player_id = player.playerid;
break;
}
}
if (g_player_id >= 0) {
sendJsonRequest(new JsonRpcRequest("Player.GetProperties", {"playerid": g_player_id, "properties": ["speed"]}), getPlayerPropertiesCb);
sendJsonRequest(new JsonRpcRequest("Player.GetItem", {"playerid": g_player_id, "properties": ["title","album","artist","director","duration"]}), getItemCb);
} else {
MessageQueue.sendAppMessage({"MSG_KEY_TITLE": "No player available", "MSG_KEY_ARTIST": ""});
}
}
function getPlayerPropertiesCb(result) {
g_play_state = (result.speed > 0) ? 1 : 0;
MessageQueue.sendAppMessage({"MSG_KEY_PLAY_STATE": g_play_state});
}
function getItemCb(result) {
var title = (result.item.title === "") ? result.item.label : result.item.title;
var artist = "";
if (result.item.type == "movie") {
artist = (result.item.director.length < 1) ? "" : result.item.director[0];
} else {
artist = (result.item.artist.length < 1) ? "" : result.item.artist[0];
}
console.log("Artist:"+artist);
MessageQueue.sendAppMessage({"MSG_KEY_TITLE":title,"MSG_KEY_ARTIST":artist});
}
function playPause() {
if (g_player_id >= 0) {
sendJsonRequest(new JsonRpcRequest("Player.PlayPause", {"playerid": g_player_id}), playPauseCb);
}
}
function playPauseCb(result) {
g_play_state = result.speed;
MessageQueue.sendAppMessage({"MSG_KEY_PLAY_STATE": g_play_state});
}
function raiseVolume() {
g_volume = (g_volume > 95) ? 100 : g_volume + 5;
sendJsonRequest(new JsonRpcRequest("Application.SetVolume", {"volume": g_volume}), setVolumeCb);
}
function lowerVolume() {
g_volume = (g_volume < 5) ? 0 : g_volume - 5;
sendJsonRequest(new JsonRpcRequest("Application.SetVolume", {"volume": g_volume}), setVolumeCb);
}
function setVolumeCb (result) {
g_volume = result;
MessageQueue.sendAppMessage({"MSG_KEY_VOLUME": g_volume});
}
function previous() {
if (g_player_id >= 0) {
sendJsonRequest(new JsonRpcRequest("Player.GoTo", {"playerid": g_player_id, "to": "previous"}), changeTransportCb);
}
}
function next() {
if (g_player_id >= 0) {
sendJsonRequest(new JsonRpcRequest("Player.GoTo", {"playerid": g_player_id, "to": "next"}), changeTransportCb);
}
}
function stop() {
if (g_player_id >= 0) {
sendJsonRequest(new JsonRpcRequest("Player.Stop", {"playerid": g_player_id}), changeTransportCb);
}
}
function changeTransportCb(result) {
getStatus();
}
// Remote methods
function sendKey(input_key) {
switch(input_key) {
case "KEY_UP":
sendJsonRequest(new JsonRpcRequest("Input.Up"));
break;
case "KEY_DOWN":
sendJsonRequest(new JsonRpcRequest("Input.Down"));
break;
case "KEY_SELECT":
sendJsonRequest(new JsonRpcRequest("Input.Select"));
break;
case "KEY_BACK":
sendJsonRequest(new JsonRpcRequest("Input.Back"));
break;
case "KEY_LEFT":
sendJsonRequest(new JsonRpcRequest("Input.Left"));
break;
case "KEY_RIGHT":
sendJsonRequest(new JsonRpcRequest("Input.Right"));
break;
}
}
// Goto methods
function gotoFullscreen() {
sendJsonRequest(new JsonRpcRequest("GUI.setFullScreen",{"fullscreen":true}));
}
function gotoInfo() {
sendJsonRequest(new JsonRpcRequest("Input.Info"));
}
function gotoHome() {
sendJsonRequest(new JsonRpcRequest("GUI.ActivateWindow",{"window":"home"}));
}
function gotoMusic() {
sendJsonRequest(new JsonRpcRequest("GUI.ActivateWindow",{"window":"music"}));
}
function gotoVideo() {
sendJsonRequest(new JsonRpcRequest("GUI.ActivateWindow",{"window":"video"}));
}
function gotoPictures() {
sendJsonRequest(new JsonRpcRequest("GUI.ActivateWindow",{"window":"pictures"}));
}
function gotoWeather() {
sendJsonRequest(new JsonRpcRequest("GUI.ActivateWindow",{"window":"weather"}));
}
// Playlist methods
function getMusicPlaylists() {
sendJsonRequest(new JsonRpcRequest("Files.GetDirectory", {"directory":"special://musicplaylists","media":"files","properties":["title"],"limits":{"start":0,"end":10}}), getMusicPlaylistsCb);
}
function getMusicPlaylistsCb(result) {
var dict = {};
var key = 0;
var files = result.files;
for (var i=0;i<files.length;i++) {
var filename = files[i].file;
var label = files[i].label;
dict[key++] = filename + "|" + label;
}
MessageQueue.sendAppMessage(dict);
}
function playMusicPlaylist(payload) {
var filename = payload.MSG_KEY_BUTTON_DATA;
var requests = [];
requests.push(new JsonRpcRequest("PlayList.Clear", {"playlistid": 0}));
requests.push(new JsonRpcRequest("PlayList.Add", {"playlistid":0, "item":{"directory":filename,"recursive":true}}));
requests.push(new JsonRpcRequest("Player.Open", {"item":{"playlistid":0,"position":0}}));
sendJsonRequest(requests);
}
// Addon methods
function getAddons() {
sendJsonRequest(new JsonRpcRequest("Addons.GetAddons", {"type": "xbmc.python.script", "properties": ["name"],"limits":{"start":0,"end":10}}), getAddonsCb);
}
function getAddonsCb(result) {
var dict = {};
var key = 0;
var addons = result.addons;
for (var i=0;i<addons.length;i++) {
var id = addons[i].addonid;
var name = addons[i].name;
dict[key++] = id + "|" + name;
}
MessageQueue.sendAppMessage(dict);
}
function executeAddon(payload) {
var addonid = payload.MSG_KEY_BUTTON_DATA;
sendJsonRequest(new JsonRpcRequest("Addons.ExecuteAddon", {"addonid": addonid}));
}
// Power methods
function systemShutdown() {
sendJsonRequest(new JsonRpcRequest("System.Shutdown"));
}
function systemReboot() {
sendJsonRequest(new JsonRpcRequest("System.Reboot"));
}
function systemHibernate() {
sendJsonRequest(new JsonRpcRequest("System.Hibernate"));
}
function systemSuspend() {
sendJsonRequest(new JsonRpcRequest("System.Suspend"));
}
// Event listeners
Pebble.addEventListener('ready',
function(e) {
console.log('Rockodi copyright (c) 2015, Douglas Otwell');
}
);
Pebble.addEventListener("appmessage",
function(e) {
var cmd = e.payload.MSG_KEY_BUTTON_CODE;
switch(cmd) {
// Player messages
case "GET_STATUS": getStatus(); break;
case "PLAY_PAUSE": playPause(); break;
case "VOLUME_UP": raiseVolume(); break;
case "VOLUME_DOWN": lowerVolume(); break;
case "NEXT": next(); break;
case "STOP": stop(); break;
case "PREVIOUS": previous(); break;
// Remote messages
case "KEY_SELECT": sendKey(cmd); break;
case "KEY_UP": sendKey(cmd); break;
case "KEY_DOWN": sendKey(cmd); break;
case "KEY_BACK": sendKey(cmd); break;
case "KEY_LEFT": sendKey(cmd); break;
case "KEY_RIGHT": sendKey(cmd); break;
// Goto messages
case "GO_FULL": gotoFullscreen(); break;
case "GO_INFO": gotoInfo(); break;
case "GO_HOME": gotoHome(); break;
case "GO_MUSIC": gotoMusic(); break;
case "GO_VIDEO": gotoVideo(); break;
case "GO_PICS": gotoPictures(); break;
case "GO_WEATHER": gotoWeather(); break;
// Playlist messages
case "GET_MUSIC_PLAYLISTS": getMusicPlaylists(); break;
case "PLAY_MUSIC_PLAYLIST": playMusicPlaylist(e.payload); break;
// Addons messages
case "GET_ADDONS": getAddons(); break;
case "EXE_ADDON": executeAddon(e.payload); break;
// Power messages
case "PWR_SHUTDOWN": systemShutdown(); break;
case "PWR_REBOOT": systemReboot(); break;
case "PWR_SUSPEND": systemSuspend(); break;
case "PWR_HIBERNATE": systemHibernate(); break;
default: console.log("Command is not defined: "+cmd+"; payload: "+e.payload);
}
}
);
\ No newline at end of file
// Copyright (c) 2015 Douglas Otwell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#include <pebble.h>
#include "player.h"
#include "common.h"
static Window *s_window;
static GBitmap *s_icon_vol_up;
static GBitmap *s_icon_pause;
static GBitmap *s_icon_play;
static GBitmap *s_icon_vol_dn;
static GBitmap *s_icon_speaker;
static GFont s_res_gothic_18;
static GFont s_res_gothic_24_bold;
static ActionBarLayer *s_action_bar;
static TextLayer *s_txt_title;
static TextLayer *s_txt_artist;
static BitmapLayer *s_bmp_speaker;
static Layer *s_lyr_volume;
static Layer *s_lyr_background;
// player data
static char s_title[64];
static char s_artist[64];
static void up_click_cb(ClickRecognizerRef recognizer, void *context) {outbox_send("VOLUME_UP");}
static void down_click_cb(ClickRecognizerRef recognizer, void *context) {outbox_send("VOLUME_DOWN");}
static void select_click_cb(ClickRecognizerRef recognizer, void *context) {outbox_send("PLAY_PAUSE");}
static void previous_click_cb(ClickRecognizerRef recognizer, void *context) {outbox_send("PREVIOUS");}
static void stop_click_cb(ClickRecognizerRef recognizer, void *context) {outbox_send("STOP");}
static void next_click_cb(ClickRecognizerRef recognizer, void *context) {outbox_send("NEXT");}
static void click_provider(void *context)
{
window_single_click_subscribe(BUTTON_ID_UP, up_click_cb);
window_single_click_subscribe(BUTTON_ID_SELECT, select_click_cb);
window_single_click_subscribe(BUTTON_ID_DOWN, down_click_cb);
window_long_click_subscribe(BUTTON_ID_UP, 500, previous_click_cb, NULL);
window_long_click_subscribe(BUTTON_ID_SELECT, 500, stop_click_cb, NULL);
window_long_click_subscribe(BUTTON_ID_DOWN, 500, next_click_cb, NULL);
}
static void lyr_background_update_proc(Layer *layer, GContext *ctx) {
GRect bounds = layer_get_bounds(layer);
graphics_context_set_fill_color(ctx, GColorWhite);
graphics_fill_rect(ctx, GRect(bounds.size.w - 21,2, 21,bounds.size.h - 4), 4, GCornersLeft);
}
static void lyr_volume_update_proc(Layer *layer, GContext *ctx) {
GRect bounds = layer_get_bounds(layer);
uint32_t *len = (uint32_t *) layer_get_data(s_lyr_volume);
graphics_context_set_fill_color(ctx, GColorWhite);
GRect rect = GRect(0, 1, *len, bounds.size.h - 2);
graphics_fill_rect(ctx, rect, 1, GCornersAll);
}
static void inbox_received_callback(DictionaryIterator *iterator, void *context) {
uint32_t *layer_data;
Tuple *t = dict_read_first(iterator);
while(t != NULL) {
switch(t->key) {
case MSG_KEY_TITLE:
DEBUG("Adjusting title: %s", t->value->cstring);
strncpy(s_title, t->value->cstring, sizeof(s_title));
text_layer_set_text(s_txt_title, s_title);
break;
case MSG_KEY_ARTIST:
DEBUG("Adjusting artist: %s", t->value->cstring);
strncpy(s_artist, t->value->cstring, sizeof(s_artist));
text_layer_set_text(s_txt_artist, s_artist);
break;
case MSG_KEY_VOLUME:
DEBUG("Adjusting volume: %d", (int) t->value->int32);
layer_data = (uint32_t *)layer_get_data(s_lyr_volume);
*layer_data = t->value->int32;
layer_mark_dirty(s_lyr_volume);
break;
case MSG_KEY_PLAY_STATE:
DEBUG("Adjusting play state: %d", (int) t->value->int32);
if (t->value->int32 > 0) {
action_bar_layer_set_icon(s_action_bar, BUTTON_ID_SELECT, s_icon_pause);
} else {
action_bar_layer_set_icon(s_action_bar, BUTTON_ID_SELECT, s_icon_play);
}
break;
}
t = dict_read_next(iterator);
}
}
static void inbox_dropped_callback(AppMessageResult reason, void *context) {
ERROR("Message dropped %s", translate_app_message_result(reason));
}
static void player_tap_cb(AccelAxisType axis, int32_t direction) {
outbox_send("GET_STATUS");
}
static void initialize_ui() {
s_window = window_create();
window_set_fullscreen(s_window, false);
window_set_background_color(s_window, GColorBlack);
Layer *window_layer = window_get_root_layer(s_window);
GRect bounds = layer_get_frame(window_layer);
s_icon_vol_up = gbitmap_create_with_resource(RESOURCE_ID_ICON_VOL_UP);
s_icon_pause = gbitmap_create_with_resource(RESOURCE_ID_ICON_PAUSE);
s_icon_play = gbitmap_create_with_resource(RESOURCE_ID_ICON_PLAY);
s_icon_vol_dn = gbitmap_create_with_resource(RESOURCE_ID_ICON_VOL_DN);
s_icon_speaker = gbitmap_create_with_resource(RESOURCE_ID_ICON_SPEAKER);
s_res_gothic_24_bold = fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD);
s_res_gothic_18 = fonts_get_system_font(FONT_KEY_GOTHIC_18);
// s_lyr_backround
s_lyr_background = layer_create(bounds);
layer_set_update_proc(s_lyr_background, lyr_background_update_proc);
layer_add_child(window_layer, (Layer *) s_lyr_background);
// s_player_bar
s_action_bar = action_bar_layer_create();
action_bar_layer_add_to_window(s_action_bar, s_window);
action_bar_layer_set_icon(s_action_bar, BUTTON_ID_UP, s_icon_vol_up);
action_bar_layer_set_icon(s_action_bar, BUTTON_ID_SELECT, s_icon_pause);
action_bar_layer_set_icon(s_action_bar, BUTTON_ID_DOWN, s_icon_vol_dn);
action_bar_layer_set_click_config_provider(s_action_bar, click_provider);
layer_add_child(window_layer, (Layer *) s_action_bar);
// s_txt_title
s_txt_title = text_layer_create(GRect(4, 0, 116, 76));
text_layer_set_background_color(s_txt_title, GColorClear);
text_layer_set_text_color(s_txt_title, GColorWhite);
text_layer_set_text_alignment(s_txt_title, GTextAlignmentCenter);
text_layer_set_font(s_txt_title, s_res_gothic_24_bold);
text_layer_set_text(s_txt_title, "Loading...");
layer_add_child(window_layer, (Layer *) s_txt_title);
// s_txt_artist
s_txt_artist = text_layer_create(GRect(4, 78, 116, 56));
text_layer_set_background_color(s_txt_artist, GColorClear);
text_layer_set_text_color(s_txt_artist, GColorWhite);
text_layer_set_text_alignment(s_txt_artist, GTextAlignmentCenter);
text_layer_set_font(s_txt_artist, s_res_gothic_18);
layer_add_child(window_layer, (Layer *) s_txt_artist);
// s_bmap_speaker
s_bmp_speaker = bitmap_layer_create(GRect(2, 134, 8, 12));
bitmap_layer_set_bitmap(s_bmp_speaker, s_icon_speaker);
layer_add_child(window_layer, (Layer *) s_bmp_speaker);
// s_lyr_volume
s_lyr_volume = layer_create_with_data(GRect(16, 136, 100, 8), sizeof(uint32_t));
layer_set_update_proc(s_lyr_volume, lyr_volume_update_proc);
uint32_t *len = (uint32_t *) layer_get_data(s_lyr_volume);
*len = 0;
layer_add_child(window_layer, (Layer *) s_lyr_volume);
app_message_register_inbox_received(inbox_received_callback);
app_message_register_inbox_dropped(inbox_dropped_callback);
outbox_send("GET_STATUS");
}
static void destroy_ui() {
window_destroy(s_window);
gbitmap_destroy(s_icon_vol_up);
gbitmap_destroy(s_icon_pause);
gbitmap_destroy(s_icon_play);
gbitmap_destroy(s_icon_vol_dn);
gbitmap_destroy(s_icon_speaker);
layer_destroy(s_lyr_background);
action_bar_layer_destroy(s_action_bar);
text_layer_destroy(s_txt_title);
text_layer_destroy(s_txt_artist);
bitmap_layer_destroy(s_bmp_speaker);
layer_destroy(s_lyr_volume);
}
static void handle_window_appear(Window* window) {
accel_tap_service_subscribe(player_tap_cb);
}
static void handle_window_disappear(Window* window) {
accel_tap_service_unsubscribe();
}
static void handle_window_unload(Window* window) {
destroy_ui();
}
void show_player(void) {
initialize_ui();
window_set_window_handlers(s_window, (WindowHandlers) {
.unload = handle_window_unload,
.appear = handle_window_appear,
.disappear = handle_window_disappear,
});
window_stack_push(s_window, true);
}
void hide_player(void) {
window_stack_remove(s_window, true);
}
// Copyright (c) 2015 Douglas Otwell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#pragma once
void show_player(void);
void hide_player(void);
// Copyright (c) 2015 Douglas Otwell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#include <pebble.h>
#include "player.h"
#include "common.h"
#include "basic_menu_layer.h"
static Window *s_window;
static MenuLayer *s_menu;
static Layer *s_lyr_loading;
static BasicMenuModel *s_model;
#define ITEMS_BUFFER_SIZE 1024
static uint8_t items_buffer[ITEMS_BUFFER_SIZE];
static DictionaryIterator items_iter;
static void lyr_loading_update_proc(Layer *layer, GContext *ctx) {
GRect bounds = layer_get_bounds(layer);
graphics_fill_rect(ctx, bounds, 0, GCornerNone);
graphics_draw_text(ctx, "Loading...", fonts_get_system_font(FONT_KEY_GOTHIC_24_BOLD),
GRect(0, 10, bounds.size.w, 28), GTextOverflowModeTrailingEllipsis, GTextAlignmentCenter, NULL);
}
static void load_menu(void) {
Tuple *t = dict_read_first(&items_iter);
while(t != NULL) {
char* id = (char*) t->value->cstring;
char* name = split_id_name_pair(id);
strip_ext(name);
basic_menu_model_add_item(s_model, name, NULL, id);
t = dict_read_next(&items_iter);
}
menu_layer_reload_data(s_menu);
layer_set_hidden(s_lyr_loading, true);
}
static void inbox_received_callback(DictionaryIterator *iterator, void *context) {
dict_write_begin(&items_iter, items_buffer, ITEMS_BUFFER_SIZE);
Tuple *t = dict_read_first(iterator);
while(t != NULL) {
dict_write_cstring(&items_iter, (int) t->key, (char*) t->value->cstring);
t = dict_read_next(iterator);
}
int items_size = dict_write_end(&items_iter);
DEBUG("Size of the written buffer is %d bytes.", items_size);
load_menu();
}
static void inbox_dropped_callback(AppMessageResult reason, void *context) {
ERROR("Message dropped: %s", translate_app_message_result(reason));
}
static void menu_select_cb(MenuLayer *menu_layer, MenuIndex *cell_index, BasicMenuItem *item) {
char* value = item->value;
outbox_send_with_data("PLAY_MUSIC_PLAYLIST", value);
window_stack_pop(true);
}
static void initialize_ui(void) {
s_window = window_create();
window_set_fullscreen(s_window, false);
window_set_background_color(s_window, GColorBlack);
Layer *window_layer = window_get_root_layer(s_window);
GRect bounds = layer_get_frame(window_layer);
s_model = basic_menu_model_create();
s_menu = basic_menu_layer_create(bounds, s_model);
basic_menu_model_set_select_callback(s_model, menu_select_cb);
menu_layer_set_click_config_onto_window(s_menu, s_window);
layer_add_child(window_layer, menu_layer_get_layer(s_menu));
// s_lyr_loading
s_lyr_loading = layer_create(bounds);
layer_set_update_proc(s_lyr_loading, lyr_loading_update_proc);
layer_add_child(window_layer, (Layer *) s_lyr_loading);
app_message_register_inbox_received(inbox_received_callback);
app_message_register_inbox_dropped(inbox_dropped_callback);
}
static void destroy_ui() {
window_destroy(s_window);
basic_menu_layer_destroy(s_menu);
basic_menu_model_destroy(s_model);
layer_destroy(s_lyr_loading);
}
static void handle_window_unload(Window* window) {
destroy_ui();
}
void show_playlists(void) {
initialize_ui();
window_set_window_handlers(s_window, (WindowHandlers) {
.unload = handle_window_unload,
});
window_stack_push(s_window, true);
outbox_send("GET_MUSIC_PLAYLISTS");
}
void hide_playlists(void) {
window_stack_remove(s_window, true);
}
// Copyright (c) 2015 Douglas Otwell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#pragma once
void show_playlists(void);
void hide_playlists(void);
// Copyright (c) 2015 Douglas Otwell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#include <pebble.h>
#include "power.h"
#include "common.h"
#include "basic_menu_layer.h"
static Window *s_window;
static MenuLayer *s_menu;
static BasicMenuModel *s_model;
static void menu_select_cb(MenuLayer *menu_layer, MenuIndex *cell_index, BasicMenuItem *item) {
char* value = item->value;
outbox_send(value);
}
static void initialize_ui(void) {
s_window = window_create();
window_set_fullscreen(s_window, false);
window_set_background_color(s_window, GColorBlack);
Layer *window_layer = window_get_root_layer(s_window);
GRect bounds = layer_get_frame(window_layer);
s_model = basic_menu_model_create();
basic_menu_model_add_item(s_model, "Shutdown", NULL, "PWR_SHUTDOWN");
basic_menu_model_add_item(s_model, "Reboot", NULL, "PWR_REBOOT");
basic_menu_model_add_item(s_model, "Suspend", NULL, "PWR_SUSPEND");
basic_menu_model_add_item(s_model, "Hibernate", NULL, "PWR_HIBERNATE");
s_menu = basic_menu_layer_create(bounds, s_model);
basic_menu_model_set_select_callback(s_model, menu_select_cb);
menu_layer_set_click_config_onto_window(s_menu, s_window);
layer_add_child(window_layer, menu_layer_get_layer(s_menu));
}
static void destroy_ui() {
window_destroy(s_window);
basic_menu_layer_destroy(s_menu);
basic_menu_model_destroy(s_model);
}
static void handle_window_unload(Window* window) {
destroy_ui();
}
void show_power(void) {
initialize_ui();
window_set_window_handlers(s_window, (WindowHandlers) {
.unload = handle_window_unload,
});
window_stack_push(s_window, true);
}
void hide_power(void) {
window_stack_remove(s_window, true);
}
// Copyright (c) 2015 Douglas Otwell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#pragma once
void show_power(void);
void hide_power(void);
// Copyright (c) 2015 Douglas Otwell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#include <pebble.h>
#include "remote.h"
#include "common.h"
#include "buttons_window.h"
static Window *s_window;
static GBitmap *s_icon_cursor_up;
static GBitmap *s_icon_check;
static GBitmap *s_icon_cursor_down;
static ActionBarLayer *s_action_bar;
static void up_click_cb(ClickRecognizerRef recognizer, void *context) {outbox_send("KEY_UP");}
static void down_click_cb(ClickRecognizerRef recognizer, void *context) {outbox_send("KEY_DOWN");}
static void select_click_cb(ClickRecognizerRef recognizer, void *context) {outbox_send("KEY_SELECT");}
static void left_click_cb(ClickRecognizerRef recognizer, void *context) {outbox_send("KEY_LEFT");}
static void right_click_cb(ClickRecognizerRef recognizer, void *context) {outbox_send("KEY_RIGHT");}
static void back_click_cb(ClickRecognizerRef recognizer, void *context) {outbox_send("KEY_BACK");}
static void click_provider(void *context)
{
window_single_click_subscribe(BUTTON_ID_UP, up_click_cb);
window_single_click_subscribe(BUTTON_ID_DOWN, down_click_cb);
window_single_click_subscribe(BUTTON_ID_SELECT, select_click_cb);
window_long_click_subscribe(BUTTON_ID_UP, 350, left_click_cb, NULL);
window_long_click_subscribe(BUTTON_ID_DOWN, 350, right_click_cb, NULL);
window_long_click_subscribe(BUTTON_ID_SELECT, 350, back_click_cb, NULL);
}
static void initialize_ui() {
s_window = buttons_window_create();
window_set_fullscreen(s_window, false);
Layer *window_layer = window_get_root_layer(s_window);
s_icon_cursor_up = gbitmap_create_with_resource(RESOURCE_ID_ICON_CURSOR_UP);
s_icon_check = gbitmap_create_with_resource(RESOURCE_ID_ICON_CHECK);
s_icon_cursor_down = gbitmap_create_with_resource(RESOURCE_ID_ICON_CURSOR_DOWN);
// s_bar_rmt
s_action_bar = action_bar_layer_create();
action_bar_layer_add_to_window(s_action_bar, s_window);
action_bar_layer_set_icon(s_action_bar, BUTTON_ID_UP, s_icon_cursor_up);
action_bar_layer_set_icon(s_action_bar, BUTTON_ID_SELECT, s_icon_check);
action_bar_layer_set_icon(s_action_bar, BUTTON_ID_DOWN, s_icon_cursor_down);
action_bar_layer_set_click_config_provider(s_action_bar, click_provider);
layer_add_child(window_layer, (Layer*) s_action_bar);
buttons_window_set_label(BUTTON_ID_UP, "Up / Left");
buttons_window_set_label(BUTTON_ID_SELECT, "Select / Back");
buttons_window_set_label(BUTTON_ID_DOWN, "Down / Right");
}
static void destroy_ui() {
buttons_window_destroy(s_window);
action_bar_layer_destroy(s_action_bar);
gbitmap_destroy(s_icon_cursor_up);
gbitmap_destroy(s_icon_check);
gbitmap_destroy(s_icon_cursor_down);
}
static void handle_window_unload(Window* window) {
destroy_ui();
}
void show_remote(void) {
initialize_ui();
window_set_window_handlers(s_window, (WindowHandlers) {
.unload = handle_window_unload,
});
window_stack_push(s_window, true);
}
void hide_remote(void) {
window_stack_remove(s_window, true);
}
// Copyright (c) 2015 Douglas Otwell
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#pragma once
void show_remote(void);
void hide_remote(void);
#
# This file is the default set of rules to compile a Pebble project.
#
# Feel free to customize this to your needs.
#
import os.path
try:
from sh import CommandNotFound, jshint, cat, ErrorReturnCode_2
hint = jshint
except (ImportError, CommandNotFound):
hint = None
top = '.'
out = 'build'
def options(ctx):
ctx.load('pebble_sdk')
def configure(ctx):
ctx.load('pebble_sdk')
global hint
if hint is not None:
hint = hint.bake(['--config', 'pebble-jshintrc'])
def build(ctx):
if False and hint is not None:
try:
hint([node.abspath() for node in ctx.path.ant_glob("src/**/*.js")], _tty_out=False) # no tty because there are none in the cloudpebble sandbox.
except ErrorReturnCode_2 as e:
ctx.fatal("\nJavaScript linting failed (you can disable this in Project Settings):\n" + e.stdout)
# Concatenate all our JS files (but not recursively), and only if any JS exists in the first place.
ctx.path.make_node('src/js/').mkdir()
js_paths = ctx.path.ant_glob(['src/*.js', 'src/**/*.js'])
if js_paths:
ctx(rule='cat ${SRC} > ${TGT}', source=js_paths, target='pebble-js-app.js')
has_js = True
else:
has_js = False
ctx.load('pebble_sdk')
ctx.pbl_program(source=ctx.path.ant_glob('src/**/*.c'),
target='pebble-app.elf')
if os.path.exists('worker_src'):
ctx.pbl_worker(source=ctx.path.ant_glob('worker_src/**/*.c'),
target='pebble-worker.elf')
ctx.pbl_bundle(elf='pebble-app.elf',
worker_elf='pebble-worker.elf',
js='pebble-js-app.js' if has_js else [])
else:
ctx.pbl_bundle(elf='pebble-app.elf',
js='pebble-js-app.js' if has_js else [])
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment